adv7511 EDID probing improvements
Subsystems (3)
v3 cover adv7511 EDID probing improvements
Hope everyone had a good newyears!
Wanted to re-send out v3 of this patch set improving the EDID probing on the adv7511 used on HiKey, for consideration for merging for 4.11
The first three patches are fixups that are hopefully straight forward, integrating feedback I got from Laurant.
The last two patches try to clean up and resue code, which as a side effect avoids an issue I'm seeing where something is going wrong with the regmap cache state for the ADV7511_REG_EDID_I2C_ADDR(0x43) register which results in i2c_transfer errors if we don't do the regcache_sync/_mark_dirty() calls. I suspect there might be a better solution there, but have not gotten any other suggestions so I wanted to go ahead and submit these.
Thoughts and feedback would be appreciated!
thanks
-john
New in v3:
* Addressed naming improvements and drm_kms_helper_hotplug_event usage corrections as suggested by Laurent.
Archit Taneja (1):
drm/bridge: adv7511: Enable HPD interrupts to support hotplug and
improve monitor detection
John Stultz (4):
drm/bridge: adv7511: Use work_struct to defer hotplug handing to out
of irq context
drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event() drm/bridge: adv7511: Rework adv7511_power_on/off() so they can be
reused internally
drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDID
drivers/gpu/drm/bridge/adv7511/adv7511.h | 2 + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 62 +++++++++++++++++++--------- 2 files changed, 44 insertions(+), 20 deletions(-)
Signature · 1 line
2.7.4
PATCH v3 1/5 drm/bridge: adv7511: Use work_struct to defer hotplug handing to out of irq context
I was recently seeing issues with EDID probing, where the logic to wait for the EDID read bit to be set by the IRQ wasn't happening and the code would time out and fail.
Digging deeper, I found this was due to the fact that IRQs were disabled as we were running in IRQ context from the HPD signal.
Thus this patch changes the logic to handle the HPD signal via a work_struct so we can be out of irq context.
With this patch, the EDID probing on hotplug does not time out.
---
v3: Rename irq_work to hpd_work and remove extra whitespace, as
suggested by Laurent
drivers/gpu/drm/bridge/adv7511/adv7511.h | 2 ++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/adv7511/adv7511.h +2 -0
@@ -317,6 +317,8 @@ struct adv7511 {bool edid_read;wait_queue_head_t wq; +struct work_struct hpd_work; +struct drm_bridge bridge;struct drm_connector connector;
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +10 -1
@@ -402,6 +402,13 @@ static bool adv7511_hpd(struct adv7511 *adv7511)return false; } +static void adv7511_hpd_work (struct work_struct *work) +{ + struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work); + +drm_helper_hpd_irq_event (adv7511->connector.dev); +} +static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd) {unsigned int irq0, irq1;
@@ -419,7 +426,7 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)regmap_write (adv7511->regmap,ADV7511_REG_INT (1 ), irq1);if (process_hpd && irq0 &ADV7511_INT0_HPD && adv7511->bridge.encoder) -drm_helper_hpd_irq_event (adv7511->connector.dev); +schedule_work (&adv7511->hpd_work);if (irq0 &ADV7511_INT0_EDID_READY || irq1 &ADV7511_INT1_DDC_ERROR ) { adv7511->edid_read = true;
@@ -1006,6 +1013,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) goto err_i2c_unregister_edid; } +INIT_WORK (&adv7511->hpd_work, adv7511_hpd_work); +if (i2c->irq) {init_waitqueue_head (&adv7511->wq);
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 2/5 drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event()
In reply to John StultzIn chasing down a previous issue with EDID probing from calling drm_helper_hpd_irq_event() from irq context, Laurent noticed that the DRM documentation suggests that drm_kms_helper_hotplug_event() should be used instead.
Thus this patch replaces drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event(), which requires we update the connector.status entry and only call _hotplug_event() when the status changes.
---
v3: Update connector.status value and only call __hotplug_event()
when that status changes, as suggested by Laurent.
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +15 -1
@@ -405,8 +405,22 @@ static bool adv7511_hpd(struct adv7511 *adv7511)static void adv7511_hpd_work (struct work_struct *work) { struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work); +enum drm_connector_status status; +unsigned int val; +int ret; + + ret =regmap_read (adv7511->regmap,ADV7511_REG_STATUS , &val); +if (ret <0 ) + status = connector_status_disconnected; +else if (val &ADV7511_STATUS_HPD ) + status = connector_status_connected; +else + status = connector_status_disconnected; + +if (adv7511->connector.status != status) +drm_kms_helper_hotplug_event (adv7511->connector.dev); -drm_helper_hpd_irq_event (adv7511->connector.dev); + adv7511->connector.status = status; }static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd)
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [PATCH 2/5 v3] drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event()
Hi John,
Thank you for the patch.
Quoted 30 lines · On Tuesday 03 Jan 2017 11:41:39 John Stultz wrote:
In chasing down a previous issue with EDID probing from calling
drm_helper_hpd_irq_event()from irq context, Laurent noticed that the DRM documentation suggests thatdrm_kms_helper_hotplug_event()should be used instead.Thus this patch replaces
drm_helper_hpd_irq_event()withdrm_kms_helper_hotplug_event(), which requires we update the connector.status entry and only call_hotplug_event()when the status changes.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Signed-off-by John Stultz <[email protected]>---
v3: Update connector.status value and only call__hotplug_event()
when that status changes, as suggested by Laurent.drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex 4fcea44..d93d66f 100644
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 407
Quoted 3 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0@@ -405,8 +405,22 @@ static bool adv7511_hpd(struct adv7511 *adv7511)static void adv7511_hpd_work (struct work_struct *work) { struct adv7511 *adv7511 = container_of(work, struct adv7511,
hpd_work);
Quoted 7 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +7
-0+enum drm_connector_status status; +unsigned int val; +int ret; + + ret =regmap_read (adv7511->regmap,ADV7511_REG_STATUS , &val); +if (ret <0 ) + status = connector_status_disconnected;
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 423
Quoted 10 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +8
-1+else if (val &ADV7511_STATUS_HPD ) + status = connector_status_connected; +else + status = connector_status_disconnected; + +if (adv7511->connector.status != status) +drm_kms_helper_hotplug_event (adv7511->connector.dev); -drm_helper_hpd_irq_event (adv7511->connector.dev); + adv7511->connector.status = status;
Shouldn't you update the status before calling drm_kms_helper_hotplug_event() ? Doing it after not only creates a small race condition as drm_kms_helper_hotplug_event() sends an event to userspace that could result in an ioctl call to retrieve the status, but the status is also checked by drm_setup_crtcs() called by drm_fb_helper_hotplug_event().
Quoted 3 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0}static int adv7511_irq_process (struct adv7511 *adv7511,bool process_hpd)
Signature · 3 lines
Regards, Laurent Pinchart
Re: [PATCH 2/5 v3] drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event()
Quoted 59 lines · On Monday 16 Jan 2017 17:47:46 Laurent Pinchart wrote:
Hi John,
Thank you for the patch.
Quoted 31 lines · On Tuesday 03 Jan 2017 11:41:39 John Stultz wrote:
In chasing down a previous issue with EDID probing from calling
drm_helper_hpd_irq_event()from irq context, Laurent noticed that the DRM documentation suggests thatdrm_kms_helper_hotplug_event()should be used instead.Thus this patch replaces
drm_helper_hpd_irq_event()withdrm_kms_helper_hotplug_event(), which requires we update the connector.status entry and only call_hotplug_event()when the status changes.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Signed-off-by John Stultz <[email protected]>---
v3: Update connector.status value and only call__hotplug_event()when that status changes, as suggested by Laurent.
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex 4fcea44..d93d66f 100644drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 409
Quoted 5 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0@@ -405,8 +405,22 @@ static bool adv7511_hpd(struct adv7511 *adv7511)static void adv7511_hpd_work (struct work_struct *work) { struct adv7511 *adv7511 = container_of(work, struct adv7511,
hpd_work);Quoted 15 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +14
-0+enum drm_connector_status status; +unsigned int val; +int ret; + + ret =regmap_read (adv7511->regmap,ADV7511_REG_STATUS , &val); +if (ret <0 ) + status = connector_status_disconnected; +else if (val &ADV7511_STATUS_HPD ) + status = connector_status_connected; +else + status = connector_status_disconnected; + +if (adv7511->connector.status != status) +drm_kms_helper_hotplug_event (adv7511->connector.dev);
Quoted 9 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 423
Quoted 2 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +1
-1-drm_helper_hpd_irq_event (adv7511->connector.dev); + adv7511->connector.status = status;Shouldn't you update the status before calling
drm_kms_helper_hotplug_event()? Doing it after not only creates a small race condition asdrm_kms_helper_hotplug_event()sends an event to userspace that could result in an ioctl call to retrieve the status, but the status is also checked bydrm_setup_crtcs()called bydrm_fb_helper_hotplug_event().
With
if (adv7511->connector.status != status) {
adv7511->connector.status = status;
drm_kms_helper_hotplug_event(adv7511->connector.dev);
}Quoted 3 lines
Quoted 3 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0}static int
adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
Signature · 3 lines
Regards, Laurent Pinchart
Re: [PATCH 2/5 v3] drm/bridge: adv7511: Switch to using drm_kms_helper_hotplug_event()
Quoted 72 lines · Laurent Pinchart
Quoted 59 lines · On Monday 16 Jan 2017 17:47:46 Laurent Pinchart wrote:
Hi John,
Thank you for the patch.
Quoted 31 lines · On Tuesday 03 Jan 2017 11:41:39 John Stultz wrote:
In chasing down a previous issue with EDID probing from calling
drm_helper_hpd_irq_event()from irq context, Laurent noticed that the DRM documentation suggests thatdrm_kms_helper_hotplug_event()should be used instead.Thus this patch replaces
drm_helper_hpd_irq_event()withdrm_kms_helper_hotplug_event(), which requires we update the connector.status entry and only call_hotplug_event()when the status changes.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Signed-off-by John Stultz <[email protected]>---
v3: Update connector.status value and only call__hotplug_event()when that status changes, as suggested by Laurent.
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex 4fcea44..d93d66f 100644drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 409
Quoted 5 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0@@ -405,8 +405,22 @@ static bool adv7511_hpd(struct adv7511 *adv7511)static void adv7511_hpd_work (struct work_struct *work) { struct adv7511 *adv7511 = container_of(work, struct adv7511,
hpd_work);Quoted 15 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +14
-0+enum drm_connector_status status; +unsigned int val; +int ret; + + ret =regmap_read (adv7511->regmap,ADV7511_REG_STATUS , &val); +if (ret <0 ) + status = connector_status_disconnected; +else if (val &ADV7511_STATUS_HPD ) + status = connector_status_connected; +else + status = connector_status_disconnected; + +if (adv7511->connector.status != status) +drm_kms_helper_hotplug_event (adv7511->connector.dev);Quoted 9 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static bool adv7511_hpd(struct adv7511 *adv7511) · line 423
Quoted 2 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +1
-1-drm_helper_hpd_irq_event (adv7511->connector.dev); + adv7511->connector.status = status;Shouldn't you update the status before calling
drm_kms_helper_hotplug_event()? Doing it after not only creates a small race condition asdrm_kms_helper_hotplug_event()sends an event to userspace that could result in an ioctl call to retrieve the status, but the status is also checked bydrm_setup_crtcs()called bydrm_fb_helper_hotplug_event().With
Quoted 7 lines
if (adv7511->connector.status != status) { adv7511->connector.status = status; drm_kms_helper_hotplug_event(adv7511->connector.dev); }Reviewed-by Laurent Pinchart <[email protected]>Tested-by Laurent Pinchart <[email protected]>
Thanks so much for catching this! I'll respin the patches with this fix and resend a v4.
thanks again!
-john
PATCH v3 3/5 drm/bridge: adv7511: Enable HPD interrupts to support hotplug and improve monitor detection
In reply to John StultzFrom: Archit Taneja <[email protected]>
On some adv7511 implementations, we can get some spurious disconnect signals which can cause monitor probing to fail.
This patch enables HPD (hot plug detect) interrupt support which allows the monitor to be properly re-initialized when the spurious disconnect signal goes away.
This also enables proper hotplug support.
--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +5 -1
@@ -338,7 +338,7 @@ static void adv7511_power_on(struct adv7511 *adv7511)* Still, let's be safe and stick to the documentation. */ regmap_write (adv7511->regmap,ADV7511_REG_INT_ENABLE (0 ), -ADV7511_INT0_EDID_READY ); +ADV7511_INT0_EDID_READY |ADV7511_INT0_HPD );regmap_write (adv7511->regmap,ADV7511_REG_INT_ENABLE (1 ),ADV7511_INT1_DDC_ERROR ); }
@@ -846,6 +846,10 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge)if (adv->type ==ADV7533 ) ret =adv7533_attach_dsi (adv); +if (adv->i2c_main->irq) +regmap_write (adv->regmap,ADV7511_REG_INT_ENABLE (0 ), +ADV7511_INT0_HPD ); +return ret; }
Signature · 1 line
2.7.4
PATCH v3 4/5 drm/bridge: adv7511: Rework adv7511_power_on/off() so they can be reused internally
In reply to John StultzIn chasing down issues with EDID probing, I found some duplicated but incomplete logic used to power the chip on and off.
This patch refactors the adv7511_power_on/off functions, so they can be used for internal needs.
--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +10 -4
@@ -325,7 +325,7 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } -static void adv7511_power_on (struct adv7511 *adv7511) +static void __adv7511_power_on (struct adv7511 *adv7511) { adv7511->current_edid_segment =-1 ;
@@ -359,24 +359,30 @@ static void adv7511_power_on(struct adv7511 *adv7511)* Most of the registers are reset during power down or when HPD is low. */ regcache_sync (adv7511->regmap); +} +static void adv7511_power_on (struct adv7511 *adv7511) +{ +__adv7511_power_on (adv7511);if (adv7511->type ==ADV7533 )adv7533_dsi_power_on (adv7511); - adv7511->powered = true; } -static void adv7511_power_off (struct adv7511 *adv7511) +static void __adv7511_power_off (struct adv7511 *adv7511) {/* TODO: setup additional power down modes */ regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER ,ADV7511_POWER_POWER_DOWN ,ADV7511_POWER_POWER_DOWN );regcache_mark_dirty (adv7511->regmap); +} +static void adv7511_power_off (struct adv7511 *adv7511) +{ +__adv7511_power_off (adv7511);if (adv7511->type ==ADV7533 )adv7533_dsi_power_off (adv7511); - adv7511->powered = false; }
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/5 v3] drm/bridge: adv7511: Rework adv7511_power_on/off() so they can be reused internally
Hi John,
Thank you for the patch.
Quoted 4 lines · On Tuesday 03 Jan 2017 11:41:41 John Stultz wrote:
In chasing down issues with EDID probing, I found some duplicated but incomplete logic used to power the chip on and off.
Quoted 8 lines
This patch refactors the adv7511_power_on/off functions, so they can be used for internal needs.
Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>
Quoted 21 lines
Signed-off-by John Stultz <[email protected]>--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex 4b90975..dbdb71c 100644drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +1
-1@@ -325,7 +325,7 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, adv7511->rgb = config->input_colorspace ==HDMI_COLORSPACE_RGB ; } -static void adv7511_power_on (struct adv7511 *adv7511) +static void __adv7511_power_on (struct adv7511 *adv7511) { adv7511->current_edid_segment =-1 ;
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static void adv7511_power_on(struct adv7511 *adv7511) · line 359
Quoted 1 line
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0@@ -359,24 +359,30 @@ static void adv7511_power_on(struct adv7511 *adv7511)* Most of the registers are reset during power down or when HPD is
low.
Quoted 31 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +9
-3*/ regcache_sync (adv7511->regmap); +} +static void adv7511_power_on (struct adv7511 *adv7511) +{ +__adv7511_power_on (adv7511);if (adv7511->type ==ADV7533 )adv7533_dsi_power_on (adv7511); - adv7511->powered = true; } -static void adv7511_power_off (struct adv7511 *adv7511) +static void __adv7511_power_off (struct adv7511 *adv7511) {/* TODO: setup additional power down modes */ regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER ,ADV7511_POWER_POWER_DOWN ,ADV7511_POWER_POWER_DOWN );regcache_mark_dirty (adv7511->regmap); +} +static void adv7511_power_off (struct adv7511 *adv7511) +{ +__adv7511_power_off (adv7511);if (adv7511->type ==ADV7533 )adv7533_dsi_power_off (adv7511); - adv7511->powered = false; }
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v3 5/5 drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDID
In reply to John StultzI've found that by just turning the chip on and off via the POWER_DOWN register, I end up getting i2c_transfer errors on HiKey.
Investigating further, it seems some of the register state in the regmap cache is somehow getting lost. Using the logic in __adv7511_power_on/off() which syncs and dirtys the cache avoids this issue.
Thus this patch changes the EDID probing logic so that we re-use the __adv7511_power_on/off() calls.
--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +3 -14
@@ -572,24 +572,13 @@ static int adv7511_get_modes(struct adv7511 *adv7511,unsigned int count;/* Reading the EDID only works if the device is powered */ -if (!adv7511->powered) { -regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER , -ADV7511_POWER_POWER_DOWN ,0 ); -if (adv7511->i2c_main->irq) { -regmap_write (adv7511->regmap,ADV7511_REG_INT_ENABLE (0 ), -ADV7511_INT0_EDID_READY ); -regmap_write (adv7511->regmap,ADV7511_REG_INT_ENABLE (1 ), -ADV7511_INT1_DDC_ERROR ); - } - adv7511->current_edid_segment =-1 ; - } +if (!adv7511->powered) +__adv7511_power_on (adv7511); edid =drm_do_get_edid (connector, adv7511_get_edid_block, adv7511);if (!adv7511->powered) -regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER , -ADV7511_POWER_POWER_DOWN , -ADV7511_POWER_POWER_DOWN ); +__adv7511_power_off (adv7511);kfree (adv7511->edid); adv7511->edid = edid;
Signature · 1 line
2.7.4
Laurent Pinchart
reviewerRe: [PATCH 5/5 v3] drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDID
Hi John,
Thank you for the patch.
Quoted 11 lines · On Tuesday 03 Jan 2017 11:41:42 John Stultz wrote:
I've found that by just turning the chip on and off via the
POWER_DOWNregister, I end up gettingi2c_transfererrors on HiKey.Investigating further, it seems some of the register state in the regmap cache is somehow getting lost. Using the logic in __adv7511_power_on/off() which syncs and dirtys the cache avoids this issue.
Thus this patch changes the EDID probing logic so that we re-use the __adv7511_power_on/off() calls.
regcache_sync() is quite costly as it will write a bunch of registers. Wouldn't it be more efficient to only write the registers that are needed for EDID access ?
Quoted 17 lines
Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Signed-off-by John Stultz <[email protected]>--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex dbdb71c..24573e0 100644
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 579
Quoted 8 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-5@@ -572,24 +572,13 @@ static int adv7511_get_modes(struct adv7511 *adv7511,unsigned int count;/* Reading the EDID only works if the device is powered */ -if (!adv7511->powered) { -regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER , -ADV7511_POWER_POWER_DOWN ,0 ); -if (adv7511->i2c_main->irq) { - regmap_write(adv7511->regmap,
ADV7511_REG_INT_ENABLE(0),
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 581
Quoted 2 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-2- ADV7511_INT0_EDID_READY); - regmap_write(adv7511->regmap,
ADV7511_REG_INT_ENABLE(1),
Quoted 17 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +3
-7- ADV7511_INT1_DDC_ERROR); - } - adv7511->current_edid_segment =-1 ; - } +if (!adv7511->powered) +__adv7511_power_on (adv7511); edid =drm_do_get_edid (connector, adv7511_get_edid_block, adv7511);if (!adv7511->powered) -regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER , -ADV7511_POWER_POWER_DOWN , -ADV7511_POWER_POWER_DOWN ); +__adv7511_power_off (adv7511);kfree (adv7511->edid); adv7511->edid = edid;
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 5/5 v3] drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDID
Quoted 14 lines · Laurent Pinchart
Hi John,
Thank you for the patch.
Quoted 9 lines · On Tuesday 03 Jan 2017 11:41:42 John Stultz wrote:
I've found that by just turning the chip on and off via the
POWER_DOWNregister, I end up gettingi2c_transfererrors on HiKey.Investigating further, it seems some of the register state in the regmap cache is somehow getting lost. Using the logic in __adv7511_power_on/off() which syncs and dirtys the cache avoids this issue.
Quoted 6 lines
Quoted 2 lines
Thus this patch changes the EDID probing logic so that we re-use the __adv7511_power_on/off() calls.
regcache_sync()is quite costly as it will write a bunch of registers. Wouldn't it be more efficient to only write the registers that are needed for EDID access ?
So yes, you've mentioned this concern before, and I did spend some time to narrow which lost-register state (0x43
- ADV7511_REG_EDID_I2C_ADDR) was causing the trouble with i2c
trasnfer errors I was seeing:
https://lkml.org/lkml/2016/11/22/677
However, I didn't get much feedback on that, and it seems (to me at least) concerning that we are losing the underlying state of a register in the cache, so just syncing that one register back to the hardware might solve the issue I was seeing, but I worry what other registers might also be out of sync.
The comment above the regmap_sync in adv7511_power_on after all states:
"Most of the registers are reset during power down or when HPD is low."
So it seems like if we're setting the power down (and setting HPD in cases where Archit had a patch to add HPD pulsing to the adv7511_get_modes path), it seems reasonable to do the same regmap_sync()?
But, I'm not really picky here, and I'm very open to other approaches (including something like the patch in the link above) if you have suggestions/preferences. I just want it to work reliably on my hardware. :)
And just so I can better understand it, can you explain some about the impact of your efficiency concerns?
thanks
-john
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [PATCH 5/5 v3] drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDID
Hi John,
Quoted 24 lines · On Monday 16 Jan 2017 12:14:48 John Stultz wrote:
Quoted 10 lines · Laurent Pinchart
Quoted 9 lines · On Tuesday 03 Jan 2017 11:41:42 John Stultz wrote:
I've found that by just turning the chip on and off via the
POWER_DOWNregister, I end up gettingi2c_transfererrors on HiKey.Investigating further, it seems some of the register state in the regmap cache is somehow getting lost. Using the logic in __adv7511_power_on/off() which syncs and dirtys the cache avoids this issue.
Quoted 6 lines
Quoted 2 lines
Thus this patch changes the EDID probing logic so that we re-use the __adv7511_power_on/off() calls.
regcache_sync()is quite costly as it will write a bunch of registers. Wouldn't it be more efficient to only write the registers that are needed for EDID access ?So yes, you've mentioned this concern before, and I did spend some time to narrow which lost-register state (
0x43
-ADV7511_REG_EDID_I2C_ADDR) was causing the trouble with i2c
trasnfer errors I was seeing:
https://lkml.org/lkml/2016/11/22/677
Quoted 8 lines
However, I didn't get much feedback on that, and it seems (to me at least) concerning that we are losing the underlying state of a register in the cache, so just syncing that one register back to the hardware might solve the issue I was seeing, but I worry what other registers might also be out of sync.
The comment above the
regmap_syncinadv7511_power_onafter all states:
"Most of the registers are reset during power down or when HPD is low."
You're right that most registers will be out of sync.
Quoted 4 lines
So it seems like if we're setting the power down (and setting HPD in cases where Archit had a patch to add HPD pulsing to the
adv7511_get_modespath), it seems reasonable to do the sameregmap_sync()?
It would be if we had to keep the device powered up, but we're powering it down right after reading the EDID. I don't think there's a need to reconfigure it completely, only setting the registers needed to read the EDID should be enough.
Quoted 7 lines
But, I'm not really picky here, and I'm very open to other approaches (including something like the patch in the link above) if you have suggestions/preferences. I just want it to work reliably on my hardware. :)
And just so I can better understand it, can you explain some about the impact of your efficiency concerns?
I'm not too picky either :-) If we can't find a reliable way to read the EDID by just configuring the registers we need, we could go for a full reconfiguration. However, restoring the value of all cached registers will result in lots of I2C writes, which are time-consuming operations. EDID read would be sped up if we could avoid that.
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
RFC PATCH 1/1 drm/bridge: adv7511: Re-write the i2c address as it may have been lost
Laurent: Would something like the following be preferred? Seems to work as well for me..
thanks
-john
I've found that by just turning the chip on and off via the POWER_DOWN register, I end up getting i2c_transfer errors on HiKey.
Investigating further, it seems some of the register state in the regmap cache is somehow getting lost, likely as the device registers were reset during power off.
Thus this patch simply re-writes the i2c address to the ADV7511_REG_EDID_I2C_ADDR register to ensure its properly set before we try to read the EDID data.
--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +5 -0
@@ -567,6 +567,8 @@ static int adv7511_get_modes(struct adv7511 *adv7511,/* Reading the EDID only works if the device is powered */ if (!adv7511->powered) { +unsigned int edid_i2c_addr = (adv7511->i2c_main->addr <<1 ) +4 ; +regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER ,ADV7511_POWER_POWER_DOWN ,0 );if (adv7511->i2c_main->irq) {
@@ -576,6 +578,9 @@ static int adv7511_get_modes(struct adv7511 *adv7511, ADV7511_INT1_DDC_ERROR); } adv7511->current_edid_segment =-1 ; + +/* Reset the EDID_I2C_ADDR register as it may have been cleared */ +regmap_write (adv7511->regmap,ADV7511_REG_EDID_I2C_ADDR , edid_i2c_addr); } edid =drm_do_get_edid (connector, adv7511_get_edid_block, adv7511);
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Laurent Pinchart
reviewerRe: [RFC][PATCH] drm/bridge: adv7511: Re-write the i2c address as it may have been lost
Hi John,
Thank you for the patch.
Quoted 2 lines · On Monday 16 Jan 2017 15:16:51 John Stultz wrote:
Laurent: Would something like the following be preferred? Seems to work as well for me..
That looks good to me. Feel free to still de-duplicate the power on/off code if you want (but of course without adding the regcache_sync to the common power on function this time).
Please see below for an additional comment.
Quoted 29 lines
I've found that by just turning the chip on and off via the
POWER_DOWNregister, I end up gettingi2c_transfererrors on HiKey.Investigating further, it seems some of the register state in the regmap cache is somehow getting lost, likely as the device registers were reset during power off.
Thus this patch simply re-writes the i2c address to the
ADV7511_REG_EDID_I2C_ADDRregister to ensure its properly set before we try to read the EDID data.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Signed-off-by John Stultz <[email protected]>--- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 5 +++++ 1 file changed, 5 insertions(+)(quoted diff) +0
-0
b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.cindex 405e460..32c59cb 100644
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 570
Quoted 4 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +1
-0@@ -567,6 +567,8 @@ static int adv7511_get_modes(struct adv7511 *adv7511,/* Reading the EDID only works if the device is powered */ if (!adv7511->powered) { + unsigned int edid_i2c_addr = (adv7511->i2c_main->addr << 1) +
4;
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 582
Quoted 10 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +3
-0+regmap_update_bits (adv7511->regmap,ADV7511_REG_POWER ,ADV7511_POWER_POWER_DOWN ,0 );if (adv7511->i2c_main->irq) {@@ -576,6 +578,9 @@ static int adv7511_get_modes(struct adv7511 *adv7511, ADV7511_INT1_DDC_ERROR); } adv7511->current_edid_segment =-1 ; + +/* Reset the EDID_I2C_ADDR register as it may have been
cleared */
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 583
Quoted 1 line
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +1
-0+ regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
edid_i2c_addr);
As powering the device off called regcache_mark_dirty(), this will perform an I2C write and cache the value. If we then try to read the EDID a second time without going through a full power on/off sequence, I believe that regmap will skip the write the second time, as the cache will contain the same value and won't be marked as dirty. Should we call regcache_mark_dirty() when powering the device down further down this function ?
Quoted 3 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +0
-0} edid =drm_do_get_edid (connector, adv7511_get_edid_block, adv7511);
Signature · 3 lines
Regards, Laurent Pinchart
Re: [RFC][PATCH] drm/bridge: adv7511: Re-write the i2c address as it may have been lost
Quoted 11 lines · Laurent Pinchart
Hi John,
Thank you for the patch.
Quoted 2 lines · On Monday 16 Jan 2017 15:16:51 John Stultz wrote:
Laurent: Would something like the following be preferred? Seems to work as well for me..
That looks good to me. Feel free to still de-duplicate the power on/off code if you want (but of course without adding the
regcache_syncto the common power on function this time).
Ok. Will do that. Thanks again for the feedback/direction here!
Quoted 8 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c static int adv7511_get_modes(struct adv7511 *adv7511, · line 582
Quoted 6 lines
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +2
-0@@ -576,6 +578,9 @@ static int adv7511_get_modes(struct adv7511 *adv7511, ADV7511_INT1_DDC_ERROR); } adv7511->current_edid_segment =-1 ; + +/* Reset the EDID_I2C_ADDR register as it may have been cleared */
Review static int adv7511_get_modes(struct adv7511 *adv7511, · line 583
Quoted 1 line
(quoted diff) +1
-0+ regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
Quoted 8 lines
edid_i2c_addr);As powering the device off called
regcache_mark_dirty(), this will perform an I2C write and cache the value. If we then try to read the EDID a second time without going through a full power on/off sequence, I believe that regmap will skip the write the second time, as the cache will contain the same value and won't be marked as dirty. Should we callregcache_mark_dirty()when powering the device down further down this function ?
Ah. Right. I had this in my earlier attempt, but thought I was simplifying things here. I'll correct this in the next revision.
Thanks again!
-john
Hi,
Quoted 18 lines · John Stultz
Hope everyone had a good newyears!
Wanted to re-send out v3 of this patch set improving the EDID probing on the adv7511 used on HiKey, for consideration for merging for 4.11
The first three patches are fixups that are hopefully straight forward, integrating feedback I got from Laurant.
The last two patches try to clean up and resue code, which as a side effect avoids an issue I'm seeing where something is going wrong with the regmap cache state for the
ADV7511_REG_EDID_I2C_ADDR(0x43)register which results ini2c_transfererrors if we don't do the regcache_sync/_mark_dirty() calls. I suspect there might be a better solution there, but have not gotten any other suggestions so I wanted to go ahead and submit these.
Quoted 1 line
Thoughts and feedback would be appreciated!
Tested on DB410c on 4.10-rc3. Works well for me.
Thanks,
Archit
Quoted 31 lines
thanks
-johnNew in v3:
* Addressed naming improvements anddrm_kms_helper_hotplug_eventusage corrections as suggested by Laurent.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Archit Taneja (1):
drm/bridge: adv7511: Enable HPD interrupts to support hotplug and
improve monitor detectionJohn Stultz (4):
drm/bridge: adv7511: Usework_structto defer hotplug handing to out
of irq context
drm/bridge: adv7511: Switch to usingdrm_kms_helper_hotplug_event()drm/bridge: adv7511: Rework adv7511_power_on/off() so they can be
reused internally
drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDIDdrivers/gpu/drm/bridge/adv7511/adv7511.h | 2 + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 62 +++++++++++++++++++--------- 2 files changed, 44 insertions(+), 20 deletions(-)
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 22 lines · Archit Taneja
Hi,
Quoted 19 lines · John Stultz
Hope everyone had a good newyears!
Wanted to re-send out v3 of this patch set improving the EDID probing on the adv7511 used on HiKey, for consideration for merging for 4.11
The first three patches are fixups that are hopefully straight forward, integrating feedback I got from Laurant.
The last two patches try to clean up and resue code, which as a side effect avoids an issue I'm seeing where something is going wrong with the regmap cache state for the
ADV7511_REG_EDID_I2C_ADDR(0x43)register which results ini2c_transfererrors if we don't do the regcache_sync/_mark_dirty() calls. I suspect there might be a better solution there, but have not gotten any other suggestions so I wanted to go ahead and submit these.
Quoted 4 lines
Quoted 1 line
Thoughts and feedback would be appreciated!
Tested on DB410c on 4.10-rc3. Works well for me.
Archit: Thanks for the testing! Is there anything else you need from me (or others) to queue this for 4.11? Or should I be submitting it to someone else?
thanks
-john
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 23 lines · John Stultz
Quoted 22 lines · Archit Taneja
Hi,
Quoted 19 lines · John Stultz
Hope everyone had a good newyears!
Wanted to re-send out v3 of this patch set improving the EDID probing on the adv7511 used on HiKey, for consideration for merging for 4.11
The first three patches are fixups that are hopefully straight forward, integrating feedback I got from Laurant.
The last two patches try to clean up and resue code, which as a side effect avoids an issue I'm seeing where something is going wrong with the regmap cache state for the
ADV7511_REG_EDID_I2C_ADDR(0x43)register which results ini2c_transfererrors if we don't do the regcache_sync/_mark_dirty() calls. I suspect there might be a better solution there, but have not gotten any other suggestions so I wanted to go ahead and submit these.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Thoughts and feedback would be appreciated!
Tested on DB410c on 4.10-rc3. Works well for me.
Archit: Thanks for the testing! Is there anything else you need from me (or others) to queue this for 4.11? Or should I be submitting it to someone else?
A final Ack/Test from Laurent for ADV7511 would be nice. I'll be the one queuing it to drm-misc for 4.11.
Thanks,
Archit
Quoted 4 lines
thanks
-john
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Hi John,
Thank you for the patches.
Quoted 18 lines · On Tuesday 03 Jan 2017 11:41:37 John Stultz wrote:
Hope everyone had a good newyears!
Wanted to re-send out v3 of this patch set improving the EDID probing on the adv7511 used on HiKey, for consideration for merging for 4.11
The first three patches are fixups that are hopefully straight forward, integrating feedback I got from Laurant.
The last two patches try to clean up and resue code, which as a side effect avoids an issue I'm seeing where something is going wrong with the regmap cache state for the
ADV7511_REG_EDID_I2C_ADDR(0x43)register which results ini2c_transfererrors if we don't do the regcache_sync/_mark_dirty() calls. I suspect there might be a better solution there, but have not gotten any other suggestions so I wanted to go ahead and submit these.
Quoted 1 line
Thoughts and feedback would be appreciated!
For the whole series,
Quoted 27 lines
New in v3:
* Addressed naming improvements anddrm_kms_helper_hotplug_eventusage corrections as suggested by Laurent.Cc David Airlie <[email protected]>Cc Archit Taneja <[email protected]>Cc Wolfram Sang <[email protected]>Cc Lars-Peter Clausen <[email protected]>Cc Laurent Pinchart <[email protected]>Archit Taneja (1):
drm/bridge: adv7511: Enable HPD interrupts to support hotplug and
improve monitor detectionJohn Stultz (4):
drm/bridge: adv7511: Usework_structto defer hotplug handing to out
of irq context
drm/bridge: adv7511: Switch to usingdrm_kms_helper_hotplug_event()drm/bridge: adv7511: Rework adv7511_power_on/off() so they can be
reused internally
drm/bridge: adv7511: Reuse __adv7511_power_on/off() when probing EDIDdrivers/gpu/drm/bridge/adv7511/adv7511.h | 2 + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 62+++++++++++++++++++--------- 2 files changed, 44 insertions(+), 20 deletions(-)
Signature · 8 lines
Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel