Received: by 2002:a25:86ce:0:0:0:0:0 with SMTP id y14csp1448709ybm; Thu, 23 May 2019 00:56:28 -0700 (PDT) X-Google-Smtp-Source: APXvYqzuq4N5GTsolASfXvIbBnujN19QEnqjFPF4AhTogJkgaMnElOcZIXc65RzL5IWzgiV3Agnr X-Received: by 2002:a63:6bc3:: with SMTP id g186mr83660690pgc.21.1558598188692; Thu, 23 May 2019 00:56:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558598188; cv=none; d=google.com; s=arc-20160816; b=WCZcxfP70336HrjjZfYuKO1suqdGJiXcmfWdot/0BJgpPrByyRhnh4A+91mRiDa/tw DLFIMhta2yTF6Nh81rJHut/vRXUN1W77Wd8NbgZWa9lf1KHVn5qs+Hbfx8tkR9NfkigO f9wzhmKh2MdHIo+7E36xd5xvmppnXjOaMFOAWJ+ebeW6RxcPO0uKfYNAtJ2yaXa3pFTS jVsQioK6ZWSoTANwnp6lwnDjZ1fS0t6URCTtfWJO54pXLPqL9rRVhDj/qArZfWmuROSc SmG0MMC88w8TXqEClIGI6Cui3JyQ8MFoz86VPphJJfHRiiSLErjscCsv+hxKLJ61a+Z0 ui/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=3vPPHF6NINH2nBiuig+yF26uprtI24dsbJd0RzRyR8U=; b=WsyqDmWNpkD/YvbOSag+pAnJLEKvIIArlIs9ddPgU+ZjG1iL+KtSccpPZ5Uxo3MYkX sc810fZ+wRSjinlm+/3ByEdUrzTOqamrDa4ca8xhyAFFcYqylNldRnBOVmPrs8FR8oYU i1eZgpYwJwsKKPTav36DIdaa4y3ahC41sJA6rNZ+HAJ8GoBNSqLdwEgzs5mb9lk9GjWW 0cXJi/vCm1QYg0b/c0KfhVoqCYH75DHdLZHbFC8jSoEaCf0AoM9lRXIeRF5M8GPNpSOl c+kxPBY3V7Kb0rfzm4lo7CP5GKij6HS9mUPzFL8yir2w2nBYmDyQg6JVIhqVNUZJwgfb +30Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=c0fRSrDV; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t4si29234710pfh.261.2019.05.23.00.56.10; Thu, 23 May 2019 00:56:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=c0fRSrDV; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728309AbfEWHyl (ORCPT + 99 others); Thu, 23 May 2019 03:54:41 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:39908 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726070AbfEWHyl (ORCPT ); Thu, 23 May 2019 03:54:41 -0400 Received: from pendragon.ideasonboard.com (85-76-106-214-nat.elisa-mobile.fi [85.76.106.214]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C11DB337; Thu, 23 May 2019 09:54:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1558598078; bh=dU/mJ1aukZubatyFnvvf7TFqfO/hWUhosSC2Ax4I6rg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=c0fRSrDVQQDjKQkW5BbtIenYInPYHiOMGE0fvkvSi9cmNTZYNt+WlJbvbgfFXfLWm e+MhxWEGgOzDhesMzRDeJSimKzhgqCwgqECUaDXjhjhxgKmlBNtm+w0MuzqfTZ6LoY 8ujoW4QzA9UZA3Avahlbnru17EuceT6KDq4fxOqU= Date: Thu, 23 May 2019 10:54:17 +0300 From: Laurent Pinchart To: Torsten Duwe Cc: Maxime Ripard , Chen-Yu Tsai , Rob Herring , Mark Rutland , Thierry Reding , David Airlie , Daniel Vetter , Andrzej Hajda , Icenowy Zheng , Sean Paul , Vasily Khoruzhick , Harald Geyer , Greg Kroah-Hartman , Thomas Gleixner , dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH 3/6] drm/bridge: extract some Analogix I2C DP common code Message-ID: <20190523075417.GB5971@pendragon.ideasonboard.com> References: <20190523065013.2719D68B05@newverein.lst.de> <20190523065352.8FD7668B05@newverein.lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20190523065352.8FD7668B05@newverein.lst.de> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Torsten, Thank you for the patch. On Thu, May 23, 2019 at 08:53:52AM +0200, Torsten Duwe wrote: > From: Icenowy Zheng > > Some code can be shared within different DP bridges by Analogix. > > Extract them to a new module. > > Signed-off-by: Icenowy Zheng > Signed-off-by: Vasily Khoruzhick > Signed-off-by: Torsten Duwe > --- > drivers/gpu/drm/bridge/analogix/Kconfig | 4 + > drivers/gpu/drm/bridge/analogix/Makefile | 2 + > drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 146 +----------------- > .../gpu/drm/bridge/analogix/analogix-i2c-dptx.c | 169 +++++++++++++++++++++ > .../gpu/drm/bridge/analogix/analogix-i2c-dptx.h | 2 + > 5 files changed, 178 insertions(+), 145 deletions(-) > create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c > > diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig > index c4d343a2f04d..ed2d05c12546 100644 > --- a/drivers/gpu/drm/bridge/analogix/Kconfig > +++ b/drivers/gpu/drm/bridge/analogix/Kconfig > @@ -1,6 +1,7 @@ > # SPDX-License-Identifier: GPL-2.0-only > config DRM_ANALOGIX_ANX78XX > tristate "Analogix ANX78XX bridge" > + select DRM_ANALOGIX_DP_I2C > select DRM_KMS_HELPER > select REGMAP_I2C > help > @@ -11,3 +12,6 @@ config DRM_ANALOGIX_ANX78XX > config DRM_ANALOGIX_DP > tristate > depends on DRM > + > +config DRM_ANALOGIX_DP_I2C > + tristate > diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile > index ce1687e60975..2d523b67487d 100644 > --- a/drivers/gpu/drm/bridge/analogix/Makefile > +++ b/drivers/gpu/drm/bridge/analogix/Makefile > @@ -1,4 +1,6 @@ > # SPDX-License-Identifier: GPL-2.0-only > analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o > +analogix_dp_i2c-objs := analogix-i2c-dptx.o > obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o > obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o > +obj-$(CONFIG_DRM_ANALOGIX_DP_I2C) += analogix_dp_i2c.o Do we need a separate module for this, or could it be included in analogix_dp ? > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > index f8433c93f463..bf8291d0ddd0 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c > @@ -45,8 +45,6 @@ > #define I2C_IDX_RX_P1 4 > > #define XTAL_CLK 270 /* 27M */ > -#define AUX_CH_BUFFER_SIZE 16 > -#define AUX_WAIT_TIMEOUT_MS 15 > > static const u8 anx78xx_i2c_addresses[] = { > [I2C_IDX_TX_P0] = TX_P0, > @@ -109,153 +107,11 @@ static int anx78xx_clear_bits(struct regmap *map, u8 reg, u8 mask) > return regmap_update_bits(map, reg, mask, 0); > } > > -static bool anx78xx_aux_op_finished(struct anx78xx *anx78xx) > -{ > - unsigned int value; > - int err; > - > - err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL2_REG, > - &value); > - if (err < 0) > - return false; > - > - return (value & SP_AUX_EN) == 0; > -} > - > -static int anx78xx_aux_wait(struct anx78xx *anx78xx) > -{ > - unsigned long timeout; > - unsigned int status; > - int err; > - > - timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1; > - > - while (!anx78xx_aux_op_finished(anx78xx)) { > - if (time_after(jiffies, timeout)) { > - if (!anx78xx_aux_op_finished(anx78xx)) { > - DRM_ERROR("Timed out waiting AUX to finish\n"); > - return -ETIMEDOUT; > - } > - > - break; > - } > - > - usleep_range(1000, 2000); > - } > - > - /* Read the AUX channel access status */ > - err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_CH_STATUS_REG, > - &status); > - if (err < 0) { > - DRM_ERROR("Failed to read from AUX channel: %d\n", err); > - return err; > - } > - > - if (status & SP_AUX_STATUS) { > - DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n", > - status); > - return -ETIMEDOUT; > - } > - > - return 0; > -} > - > -static int anx78xx_aux_address(struct anx78xx *anx78xx, unsigned int addr) > -{ > - int err; > - > - err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_7_0_REG, > - addr & 0xff); > - if (err) > - return err; > - > - err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_15_8_REG, > - (addr & 0xff00) >> 8); > - if (err) > - return err; > - > - /* > - * DP AUX CH Address Register #2, only update bits[3:0] > - * [7:4] RESERVED > - * [3:0] AUX_ADDR[19:16], Register control AUX CH address. > - */ > - err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0], > - SP_AUX_ADDR_19_16_REG, > - SP_AUX_ADDR_19_16_MASK, > - (addr & 0xf0000) >> 16); > - > - if (err) > - return err; > - > - return 0; > -} > - > static ssize_t anx78xx_aux_transfer(struct drm_dp_aux *aux, > struct drm_dp_aux_msg *msg) > { > struct anx78xx *anx78xx = container_of(aux, struct anx78xx, aux); > - u8 ctrl1 = msg->request; > - u8 ctrl2 = SP_AUX_EN; > - u8 *buffer = msg->buffer; > - int err; > - > - /* The DP AUX transmit and receive buffer has 16 bytes. */ > - if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE)) > - return -E2BIG; > - > - /* Zero-sized messages specify address-only transactions. */ > - if (msg->size < 1) > - ctrl2 |= SP_ADDR_ONLY; > - else /* For non-zero-sized set the length field. */ > - ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT; > - > - if ((msg->request & DP_AUX_I2C_READ) == 0) { > - /* When WRITE | MOT write values to data buffer */ > - err = regmap_bulk_write(anx78xx->map[I2C_IDX_TX_P0], > - SP_DP_BUF_DATA0_REG, buffer, > - msg->size); > - if (err) > - return err; > - } > - > - /* Write address and request */ > - err = anx78xx_aux_address(anx78xx, msg->address); > - if (err) > - return err; > - > - err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL1_REG, > - ctrl1); > - if (err) > - return err; > - > - /* Start transaction */ > - err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0], > - SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY | > - SP_AUX_EN, ctrl2); > - if (err) > - return err; > - > - err = anx78xx_aux_wait(anx78xx); > - if (err) > - return err; > - > - msg->reply = DP_AUX_I2C_REPLY_ACK; > - > - if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) { > - /* Read values from data buffer */ > - err = regmap_bulk_read(anx78xx->map[I2C_IDX_TX_P0], > - SP_DP_BUF_DATA0_REG, buffer, > - msg->size); > - if (err) > - return err; > - } > - > - err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0], > - SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY); > - if (err) > - return err; > - > - return msg->size; > + return anx_aux_transfer(anx78xx->map[I2C_IDX_TX_P0], msg); > } > > static int anx78xx_set_hpd(struct anx78xx *anx78xx) > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c > new file mode 100644 > index 000000000000..9cb30962032e > --- /dev/null > +++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c > @@ -0,0 +1,169 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright(c) 2017 Icenowy Zheng > + * > + * Based on analogix-anx78xx.c, which is: > + * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. > + */ > + > +#include > +#include > + > +#include > +#include > +#include > + > +#include "analogix-i2c-dptx.h" > + > +#define AUX_WAIT_TIMEOUT_MS 15 > +#define AUX_CH_BUFFER_SIZE 16 > + > +static int anx_clear_bits(struct regmap *map, u8 reg, u8 mask) > +{ > + return regmap_update_bits(map, reg, mask, 0); > +} > + > +static bool anx_aux_op_finished(struct regmap *map_dptx) > +{ > + unsigned int value; > + int err; > + > + err = regmap_read(map_dptx, SP_DP_AUX_CH_CTRL2_REG, &value); > + if (err < 0) > + return false; > + > + return (value & SP_AUX_EN) == 0; > +} > + > +static int anx_aux_wait(struct regmap *map_dptx) > +{ > + unsigned long timeout; > + unsigned int status; > + int err; > + > + timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1; > + > + while (!anx_aux_op_finished(map_dptx)) { > + if (time_after(jiffies, timeout)) { > + if (!anx_aux_op_finished(map_dptx)) { > + DRM_ERROR("Timed out waiting AUX to finish\n"); > + return -ETIMEDOUT; > + } > + > + break; > + } > + > + usleep_range(1000, 2000); > + } > + > + /* Read the AUX channel access status */ > + err = regmap_read(map_dptx, SP_AUX_CH_STATUS_REG, &status); > + if (err < 0) { > + DRM_ERROR("Failed to read from AUX channel: %d\n", err); > + return err; > + } > + > + if (status & SP_AUX_STATUS) { > + DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n", > + status); > + return -ETIMEDOUT; > + } > + > + return 0; > +} > + > +static int anx_aux_address(struct regmap *map_dptx, unsigned int addr) > +{ > + int err; > + > + err = regmap_write(map_dptx, SP_AUX_ADDR_7_0_REG, addr & 0xff); > + if (err) > + return err; > + > + err = regmap_write(map_dptx, SP_AUX_ADDR_15_8_REG, > + (addr & 0xff00) >> 8); > + if (err) > + return err; > + > + /* > + * DP AUX CH Address Register #2, only update bits[3:0] > + * [7:4] RESERVED > + * [3:0] AUX_ADDR[19:16], Register control AUX CH address. > + */ > + err = regmap_update_bits(map_dptx, SP_AUX_ADDR_19_16_REG, > + SP_AUX_ADDR_19_16_MASK, > + (addr & 0xf0000) >> 16); > + > + if (err) > + return err; > + > + return 0; > +} > + > +ssize_t anx_aux_transfer(struct regmap *map_dptx, struct drm_dp_aux_msg *msg) > +{ > + u8 ctrl1 = msg->request; > + u8 ctrl2 = SP_AUX_EN; > + u8 *buffer = msg->buffer; > + int err; > + > + /* The DP AUX transmit and receive buffer has 16 bytes. */ > + if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE)) > + return -E2BIG; > + > + /* Zero-sized messages specify address-only transactions. */ > + if (msg->size < 1) > + ctrl2 |= SP_ADDR_ONLY; > + else /* For non-zero-sized set the length field. */ > + ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT; > + > + if ((msg->request & DP_AUX_I2C_READ) == 0) { > + /* When WRITE | MOT write values to data buffer */ > + err = regmap_bulk_write(map_dptx, > + SP_DP_BUF_DATA0_REG, buffer, > + msg->size); > + if (err) > + return err; > + } > + > + /* Write address and request */ > + err = anx_aux_address(map_dptx, msg->address); > + if (err) > + return err; > + > + err = regmap_write(map_dptx, SP_DP_AUX_CH_CTRL1_REG, ctrl1); > + if (err) > + return err; > + > + /* Start transaction */ > + err = regmap_update_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG, > + SP_ADDR_ONLY | SP_AUX_EN, ctrl2); > + if (err) > + return err; > + > + err = anx_aux_wait(map_dptx); > + if (err) > + return err; > + > + msg->reply = DP_AUX_I2C_REPLY_ACK; > + > + if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) { > + /* Read values from data buffer */ > + err = regmap_bulk_read(map_dptx, > + SP_DP_BUF_DATA0_REG, buffer, > + msg->size); > + if (err) > + return err; > + } > + > + err = anx_clear_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY); > + if (err) > + return err; > + > + return msg->size; > +} > +EXPORT_SYMBOL(anx_aux_transfer); As the code license is GPL and the analogic DP core core is exported with EXPORT_SYMBOL_GPL, should it be the case here too ? > + > +MODULE_DESCRIPTION("Analogix DisplayPort Transmitter common code"); > +MODULE_AUTHOR("Icenowy Zheng "); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h > index bc0831b127bf..c2ca854613a0 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h > +++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h > @@ -245,4 +245,6 @@ > /* DP AUX Buffer Data Registers */ > #define SP_DP_BUF_DATA0_REG 0xf0 > > +ssize_t anx_aux_transfer(struct regmap *map_dptx, struct drm_dp_aux_msg *msg); The name is a bit generic, should it be anx_dp_aux_transfer() ? > + > #endif -- Regards, Laurent Pinchart