Re: [PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
On 15.02.2019 20:36, Vasily Khoruzhick wrote: > On Fri, Feb 15, 2019 at 1:13 AM Andrzej Hajda wrote: > > Hi Andrzej, > > Thanks for review! > >>> +#include >> Do you need this header? > I'll drop it. > >>> +#include >> drmP.h is/should be deprecated. > Same here > >>> +struct anx6345_platform_data { >>> + struct regulator *dvdd12; >>> + struct regulator *dvdd25; >>> + struct gpio_desc *gpiod_reset; >>> +}; >> Why do you need this struct, why just do not embed it's fields directly >> into struct anx6345 ? > OK, I'll embed it into struct anx6345 > >>> + if (WARN_ON(anx6345->powered)) >>> + return; >> It should not happen, you can remove this warn. > OK > >>> + if (pdata->dvdd12) { >> If regulators are required this will be never null. > Right, and regulator subsystem will return dummy regulator if it's > missing in dts. > I'll remove redundant checks. > >>> + >>> + if (pdata->dvdd25) { >> ditto > OK > >>> + >>> + if (anx6345->panel) >>> + drm_panel_prepare(anx6345->panel); >> again, here and below: panel is never null, check can be removed. > That's not true, panel is optional. It can be DP connector, not a panel. > >>> + >>> + gpiod_set_value_cansleep(pdata->gpiod_reset, 0); >>> + usleep_range(1000, 2000); >>> + >>> + gpiod_set_value_cansleep(pdata->gpiod_reset, 1); >> >> Start/stop sequence seems odd regarding reset gpio: >> >> 1. In probe reset is set to low, in poweroff to high - incosistent. >> >> 2. If in case of disabled device reset should be 0, there is no point to >> set it again to 0 three lines above. >> >> 3. I suspect in dts reset gpio should be declared as active_low, and the >> logic in the driver should be reverted, in power off it should be set to >> high, in power on it should be lowered (logically). > OK, I'll look into it. > >>> +err_poweroff: >>> + DRM_ERROR("Failed DisplayPort transmitter initialization: %d\n", err); >> redundant message > OK, will drop. > >>> + DRM_ERROR("Get sink count failed %d\n", err); >> The rule of thumb I heard is that if you start message capitalized you >> should end with dot. Since I do not know if it is enforced in kernel I >> leave the decision up to you. > I grepped DRM_ERROR in driver/gpu/drm and they do exactly the same as here. > So I'll just keep it as is for consistency. > >>> +static bool anx6345_bridge_mode_fixup(struct drm_bridge *bridge, >>> + const struct drm_display_mode *mode, >>> + struct drm_display_mode *adjusted_mode) >>> +{ >>> + if (mode->flags & DRM_MODE_FLAG_INTERLACE) >>> + return false; >>> + >>> + /* Max 1200p at 5.4 Ghz, one lane */ >>> + if (mode->clock > 154000) >>> + return false; >> These checks should be in mode_valid callback. > OK > >>> + /* Map slave addresses of ANX6345 */ >>> + for (i = 0; i < I2C_NUM_ADDRESSES; i++) { >>> + if (anx6345_i2c_addresses[i] >> 1 != client->addr) >>> + anx6345->i2c_clients[i] = >>> i2c_new_dummy(client->adapter, >>> + anx6345_i2c_addresses[i] >> >>> 1); >>> + else >>> + anx6345->i2c_clients[i] = client; >> >> I see this contredanse is copy/pasted from anx78*, but it looks quite >> complicated. As I understand there are two i2c addresses, why we cannot >> assume one address is for control interfaces and another is dummy? It would >> simplify the code here and in other places. > Sorry, I don't get you, could you elaborate? Note that anx6345 uses > both addresses, > i2c_new_dummy() just registers new i2c device bound to a dummy driver and it's > supposed to be used for devices that consume more than one i2c address. My idea was to assume that ANALOGIX_I2C_DPTX is the main address, ie. address which should be set in dts in device node reg property. Other addresses should be registered as dummy devices during probe - simple loop without conditionals, without redundant fields in anx6345 context - i2c_clients, client. I do not insist on this change but I suggest as it should simplify the code. And moreover, you can consider removing direction bit from i2c addresses, it could be also confusing and against i2c kernel api. > >>> + if (!found) { >>> + DRM_ERROR("ANX%x (ver. %d) not supported by this driver\n", >>> + anx6345->chipid, version); >>> + err = -ENODEV; >>> + goto err_poweroff; >>> + } >> >> As I see chip becomes powered forever, is it OK? Usually it should be >> powered only when pipeline starts, and powered-off after pipeline stops. > I'll look into how hard it would be to implement but personally I > think it's OK for now. > We can add more sophisticated power management once this driver is merged. But the rule is every resource allocated/set during lifetime of the driver should be dropped on driver removal, so please
Re: [linux-sunxi] [PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
On Thu, Feb 14, 2019 at 09:09:51PM -0800, Vasily Khoruzhick wrote: > From: Icenowy Zheng > > The ANX6345 is an ultra-low power DisplayPower/eDP transmitter designed > for portable devices. This driver adds initial support for RGB to eDP > mode, without HPD and interrupts. > > This is a configuration usually seen in eDP applications. > > Signed-off-by: Icenowy Zheng > Signed-off-by: Vasily Khoruzhick > --- > drivers/gpu/drm/bridge/analogix/Kconfig | 11 + > drivers/gpu/drm/bridge/analogix/Makefile | 1 + > .../drm/bridge/analogix/analogix-anx6345.c| 845 ++ > .../drm/bridge/analogix/analogix-i2c-dptx.c | 2 +- > .../drm/bridge/analogix/analogix-i2c-dptx.h | 8 + > .../bridge/analogix/analogix-i2c-txcommon.h | 3 + > 6 files changed, 869 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-anx6345.c > [ ... ] > + > +static int anx6345_start(struct anx6345 *anx6345) > +{ > + int err; > + > + if (!anx6345->powered) > + anx6345_poweron(anx6345); > + > + /* Power on needed modules */ > + err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], > + SP_POWERDOWN_CTRL_REG, > + SP_VIDEO_PD | SP_LINK_PD); > + > + err = anx6345_tx_initialization(anx6345); > + if (err) { > + DRM_ERROR("Failed transmitter initialization: %d\n", err); > + goto err_poweroff; You can move the whole err_poweroff section from below here and drop the goto. > + } > + > + /* > + * This delay seems to help keep the hardware in a good state. Without > + * it, there are times where it fails silently. > + */ > + usleep_range(1, 15000); > + > + return 0; > + > +err_poweroff: > + DRM_ERROR("Failed DisplayPort transmitter initialization: %d\n", err); > + anx6345_poweroff(anx6345); > + > + return err; > +} > + [ ... ] ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [linux-sunxi] [PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
On Fri, Feb 15, 2019 at 12:23 AM Priit Laes wrote: > > + err = anx6345_tx_initialization(anx6345); > > + if (err) { > > + DRM_ERROR("Failed transmitter initialization: %d\n", err); > > + goto err_poweroff; > > You can move the whole err_poweroff section from below here and drop the goto. Thanks, will do. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
On Fri, Feb 15, 2019 at 1:13 AM Andrzej Hajda wrote: Hi Andrzej, Thanks for review! > > +#include > Do you need this header? I'll drop it. > > +#include > > drmP.h is/should be deprecated. Same here > > +struct anx6345_platform_data { > > + struct regulator *dvdd12; > > + struct regulator *dvdd25; > > + struct gpio_desc *gpiod_reset; > > +}; > > Why do you need this struct, why just do not embed it's fields directly > into struct anx6345 ? OK, I'll embed it into struct anx6345 > > + if (WARN_ON(anx6345->powered)) > > + return; > > It should not happen, you can remove this warn. OK > > + if (pdata->dvdd12) { > > If regulators are required this will be never null. Right, and regulator subsystem will return dummy regulator if it's missing in dts. I'll remove redundant checks. > > + > > + if (pdata->dvdd25) { > > ditto OK > > + > > + if (anx6345->panel) > > + drm_panel_prepare(anx6345->panel); > > again, here and below: panel is never null, check can be removed. That's not true, panel is optional. It can be DP connector, not a panel. > > + > > + gpiod_set_value_cansleep(pdata->gpiod_reset, 0); > > + usleep_range(1000, 2000); > > + > > + gpiod_set_value_cansleep(pdata->gpiod_reset, 1); > > > Start/stop sequence seems odd regarding reset gpio: > > 1. In probe reset is set to low, in poweroff to high - incosistent. > > 2. If in case of disabled device reset should be 0, there is no point to > set it again to 0 three lines above. > > 3. I suspect in dts reset gpio should be declared as active_low, and the > logic in the driver should be reverted, in power off it should be set to > high, in power on it should be lowered (logically). OK, I'll look into it. > > +err_poweroff: > > + DRM_ERROR("Failed DisplayPort transmitter initialization: %d\n", err); > > redundant message OK, will drop. > > + DRM_ERROR("Get sink count failed %d\n", err); > > The rule of thumb I heard is that if you start message capitalized you > should end with dot. Since I do not know if it is enforced in kernel I > leave the decision up to you. I grepped DRM_ERROR in driver/gpu/drm and they do exactly the same as here. So I'll just keep it as is for consistency. > > +static bool anx6345_bridge_mode_fixup(struct drm_bridge *bridge, > > + const struct drm_display_mode *mode, > > + struct drm_display_mode *adjusted_mode) > > +{ > > + if (mode->flags & DRM_MODE_FLAG_INTERLACE) > > + return false; > > + > > + /* Max 1200p at 5.4 Ghz, one lane */ > > + if (mode->clock > 154000) > > + return false; > > These checks should be in mode_valid callback. OK > > + /* Map slave addresses of ANX6345 */ > > + for (i = 0; i < I2C_NUM_ADDRESSES; i++) { > > + if (anx6345_i2c_addresses[i] >> 1 != client->addr) > > + anx6345->i2c_clients[i] = > > i2c_new_dummy(client->adapter, > > + anx6345_i2c_addresses[i] >> > > 1); > > + else > > + anx6345->i2c_clients[i] = client; > > > I see this contredanse is copy/pasted from anx78*, but it looks quite > complicated. As I understand there are two i2c addresses, why we cannot > assume one address is for control interfaces and another is dummy? It would > simplify the code here and in other places. Sorry, I don't get you, could you elaborate? Note that anx6345 uses both addresses, i2c_new_dummy() just registers new i2c device bound to a dummy driver and it's supposed to be used for devices that consume more than one i2c address. > > + if (!found) { > > + DRM_ERROR("ANX%x (ver. %d) not supported by this driver\n", > > + anx6345->chipid, version); > > + err = -ENODEV; > > + goto err_poweroff; > > + } > > > As I see chip becomes powered forever, is it OK? Usually it should be > powered only when pipeline starts, and powered-off after pipeline stops. I'll look into how hard it would be to implement but personally I think it's OK for now. We can add more sophisticated power management once this driver is merged. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
From: Icenowy Zheng The ANX6345 is an ultra-low power DisplayPower/eDP transmitter designed for portable devices. This driver adds initial support for RGB to eDP mode, without HPD and interrupts. This is a configuration usually seen in eDP applications. Signed-off-by: Icenowy Zheng Signed-off-by: Vasily Khoruzhick --- drivers/gpu/drm/bridge/analogix/Kconfig | 11 + drivers/gpu/drm/bridge/analogix/Makefile | 1 + .../drm/bridge/analogix/analogix-anx6345.c| 845 ++ .../drm/bridge/analogix/analogix-i2c-dptx.c | 2 +- .../drm/bridge/analogix/analogix-i2c-dptx.h | 8 + .../bridge/analogix/analogix-i2c-txcommon.h | 3 + 6 files changed, 869 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-anx6345.c diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index ed2d05c12546..3c6ec535d361 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -1,3 +1,14 @@ +config DRM_ANALOGIX_ANX6345 + tristate "Analogix ANX6345 bridge" + select DRM_ANALOGIX_DP_I2C + select DRM_KMS_HELPER + select REGMAP_I2C + help + ANX6345 is an ultra-low Full-HD DisplayPort/eDP + transmitter designed for portable devices. The + ANX6345 transforms the LVTTL RGB output of an + application processor to eDP or DisplayPort. + config DRM_ANALOGIX_ANX78XX tristate "Analogix ANX78XX bridge" select DRM_ANALOGIX_DP_I2C diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile index 2d523b67487d..12fed7b04e1e 100644 --- a/drivers/gpu/drm/bridge/analogix/Makefile +++ b/drivers/gpu/drm/bridge/analogix/Makefile @@ -1,5 +1,6 @@ analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o analogix_dp_i2c-objs := analogix-i2c-dptx.o +obj-$(CONFIG_DRM_ANALOGIX_ANX6345) += analogix-anx6345.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 diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c new file mode 100644 index ..6098e245e074 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c @@ -0,0 +1,845 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(c) Icenowy Zheng + * Based on analogix-anx6345.c, which is: + * Copyright(c) 2016, Analogix Semiconductor. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "analogix-i2c-dptx.h" +#include "analogix-i2c-txcommon.h" + +#define I2C_NUM_ADDRESSES 2 +#define I2C_IDX_DPTX 0 +#define I2C_IDX_TXCOM 1 + +#define XTAL_CLK 270 /* 27M */ + +#define POLL_DELAY 5 /* us */ +#define POLL_TIMEOUT 500 /* us */ + +static const u8 anx6345_i2c_addresses[] = { + [I2C_IDX_DPTX] = ANALOGIX_I2C_DPTX, + [I2C_IDX_TXCOM] = ANALOGIX_I2C_TXCOMMON, +}; + +struct anx6345_platform_data { + struct regulator *dvdd12; + struct regulator *dvdd25; + struct gpio_desc *gpiod_reset; +}; + +struct anx6345 { + struct drm_dp_aux aux; + struct drm_bridge bridge; + struct i2c_client *client; + struct edid *edid; + struct drm_connector connector; + struct drm_dp_link link; + struct drm_panel *panel; + struct anx6345_platform_data pdata; + struct mutex lock; + + /* +* I2C Slave addresses of ANX6345 are mapped as DPTX and SYS +*/ + struct i2c_client *i2c_clients[I2C_NUM_ADDRESSES]; + struct regmap *map[I2C_NUM_ADDRESSES]; + + u16 chipid; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + + bool powered; +}; + +static inline struct anx6345 *connector_to_anx6345(struct drm_connector *c) +{ + return container_of(c, struct anx6345, connector); +} + +static inline struct anx6345 *bridge_to_anx6345(struct drm_bridge *bridge) +{ + return container_of(bridge, struct anx6345, bridge); +} + +static int anx6345_set_bits(struct regmap *map, u8 reg, u8 mask) +{ + return regmap_update_bits(map, reg, mask, mask); +} + +static int anx6345_clear_bits(struct regmap *map, u8 reg, u8 mask) +{ + return regmap_update_bits(map, reg, mask, 0); +} + +static ssize_t anx6345_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + struct anx6345 *anx6345 = container_of(aux, struct anx6345, aux); + + return anx_aux_transfer(anx6345->map[I2C_IDX_DPTX], msg); +} + +static int anx6345_dp_link_training(struct anx6345 *anx6345) +{ + unsigned int value; + u8 dp_bw; + int err; + + err =
Re: [PATCH v3 05/11] drm/bridge: Add Analogix anx6345 support
On 15.02.2019 06:09, Vasily Khoruzhick wrote: > From: Icenowy Zheng > > The ANX6345 is an ultra-low power DisplayPower/eDP transmitter designed > for portable devices. This driver adds initial support for RGB to eDP > mode, without HPD and interrupts. > > This is a configuration usually seen in eDP applications. > > Signed-off-by: Icenowy Zheng > Signed-off-by: Vasily Khoruzhick > --- > drivers/gpu/drm/bridge/analogix/Kconfig | 11 + > drivers/gpu/drm/bridge/analogix/Makefile | 1 + > .../drm/bridge/analogix/analogix-anx6345.c| 845 ++ > .../drm/bridge/analogix/analogix-i2c-dptx.c | 2 +- > .../drm/bridge/analogix/analogix-i2c-dptx.h | 8 + > .../bridge/analogix/analogix-i2c-txcommon.h | 3 + > 6 files changed, 869 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-anx6345.c > > diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig > b/drivers/gpu/drm/bridge/analogix/Kconfig > index ed2d05c12546..3c6ec535d361 100644 > --- a/drivers/gpu/drm/bridge/analogix/Kconfig > +++ b/drivers/gpu/drm/bridge/analogix/Kconfig > @@ -1,3 +1,14 @@ > +config DRM_ANALOGIX_ANX6345 > + tristate "Analogix ANX6345 bridge" > + select DRM_ANALOGIX_DP_I2C > + select DRM_KMS_HELPER > + select REGMAP_I2C > + help > + ANX6345 is an ultra-low Full-HD DisplayPort/eDP > + transmitter designed for portable devices. The > + ANX6345 transforms the LVTTL RGB output of an > + application processor to eDP or DisplayPort. > + > config DRM_ANALOGIX_ANX78XX > tristate "Analogix ANX78XX bridge" > select DRM_ANALOGIX_DP_I2C > diff --git a/drivers/gpu/drm/bridge/analogix/Makefile > b/drivers/gpu/drm/bridge/analogix/Makefile > index 2d523b67487d..12fed7b04e1e 100644 > --- a/drivers/gpu/drm/bridge/analogix/Makefile > +++ b/drivers/gpu/drm/bridge/analogix/Makefile > @@ -1,5 +1,6 @@ > analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o > analogix_dp_i2c-objs := analogix-i2c-dptx.o > +obj-$(CONFIG_DRM_ANALOGIX_ANX6345) += analogix-anx6345.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 > diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c > b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c > new file mode 100644 > index ..6098e245e074 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c > @@ -0,0 +1,845 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright(c) Icenowy Zheng > + * Based on analogix-anx6345.c, which is: > + * Copyright(c) 2016, Analogix Semiconductor. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include Do you need this header? > +#include > +#include > +#include > +#include > +#include > + > +#include drmP.h is/should be deprecated. > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "analogix-i2c-dptx.h" > +#include "analogix-i2c-txcommon.h" > + > +#define I2C_NUM_ADDRESSES2 > +#define I2C_IDX_DPTX 0 > +#define I2C_IDX_TXCOM1 > + > +#define XTAL_CLK 270 /* 27M */ > + > +#define POLL_DELAY 5 /* us */ > +#define POLL_TIMEOUT 500 /* us */ > + > +static const u8 anx6345_i2c_addresses[] = { > + [I2C_IDX_DPTX] = ANALOGIX_I2C_DPTX, > + [I2C_IDX_TXCOM] = ANALOGIX_I2C_TXCOMMON, > +}; > + > +struct anx6345_platform_data { > + struct regulator *dvdd12; > + struct regulator *dvdd25; > + struct gpio_desc *gpiod_reset; > +}; Why do you need this struct, why just do not embed it's fields directly into struct anx6345 ? > + > +struct anx6345 { > + struct drm_dp_aux aux; > + struct drm_bridge bridge; > + struct i2c_client *client; > + struct edid *edid; > + struct drm_connector connector; > + struct drm_dp_link link; > + struct drm_panel *panel; > + struct anx6345_platform_data pdata; > + struct mutex lock; > + > + /* > + * I2C Slave addresses of ANX6345 are mapped as DPTX and SYS > + */ > + struct i2c_client *i2c_clients[I2C_NUM_ADDRESSES]; > + struct regmap *map[I2C_NUM_ADDRESSES]; > + > + u16 chipid; > + u8 dpcd[DP_RECEIVER_CAP_SIZE]; > + > + bool powered; > +}; > + > +static inline struct anx6345 *connector_to_anx6345(struct drm_connector *c) > +{ > + return container_of(c, struct anx6345, connector); > +} > + > +static inline struct anx6345 *bridge_to_anx6345(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct anx6345, bridge); > +} > + > +static int anx6345_set_bits(struct regmap *map, u8 reg, u8 mask) > +{ > + return regmap_update_bits(map, reg, mask, mask); > +} > + > +static int anx6345_clear_bits(struct regmap *map, u8 reg, u8 mask) > +{ > + return regmap_update_bits(map, reg, mask, 0); > +} > + > +static ssize_t