Change check of DDC status. Instead of silently not reading EDID when in "IDLE" state [1]. Wait for HDCP being initialized because the EDID and HDCP block shares memory [2]. [1] ADV7511 Programming Guide revision G: Table 11: DDCController Status: 0xC8 [3:0] DDC Controller State 0b0000 In Reset (No Hot Plug Detected) 0b0001 Reading EDID 0b0010 IDLE (Waiting for HDCP Requested) 0b0011 Initializing HDCP 0b0100 HDCP Enabled 0b0101 Initializing HDCP Repeater [2] ADV7511 Programming Guide revision G: 4.6.1.1 EDID Definitions: EDID and HDCP use a shared memory space. During HDCP repeater initialization, the EDID data is overwritten with HDCP information. EDID is not re-read after HDCP initialization. If the user would like to re-buffer an EDID segment the EDID re-read register described in section 4.6.1.4 should be used. Fixes: 9c8af882bf12 ("drm: Add adv7511 encoder driver") Signed-off-by: Emil Svendsen <emas@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/bridge/adv7511/adv7511.h | 9 +++ drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 65 ++++++++++++++++---- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index 39c9ece373b0..16d77f4a0aa8 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -247,6 +247,15 @@ enum adv7511_input_sync_pulse { ADV7511_INPUT_SYNC_PULSE_NONE = 3, }; +enum adv7511_ddc_status { + ADV7511_DDC_STATUS_IN_RESET = 0, + ADV7511_DDC_STATUS_READING_EDID = 1, + ADV7511_DDC_STATUS_WAIT_HDCP = 2, + ADV7511_DDC_STATUS_INIT_HDCP = 3, + ADV7511_DDC_STATUS_HDCP_ENABLED = 4, + ADV7511_DDC_STATUS_INIT_HDCP_REPEATER = 5, +}; + /** * enum adv7511_sync_polarity - Polarity for the input sync signals * @ADV7511_SYNC_POLARITY_PASSTHROUGH: Sync polarity matches that of diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 9b6294120516..f50efb3beb69 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -533,6 +533,48 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) return adv7511->edid_read ? 0 : -EIO; } +static int adv7511_wait_for_hdcp(struct adv7511 *adv7511) +{ + struct device *dev = &adv7511->i2c_edid->dev; + unsigned int status = 0; + const int interval = 25; + int timeout = 100; + int ret = -EINVAL; + + for (; timeout > 0; timeout -= interval) { + ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS, + &status); + if (ret < 0) + return ret; + + status &= 0x0F; + + switch (status) { + case ADV7511_DDC_STATUS_IN_RESET: + case ADV7511_DDC_STATUS_READING_EDID: + case ADV7511_DDC_STATUS_HDCP_ENABLED: + return 0; + case ADV7511_DDC_STATUS_WAIT_HDCP: + case ADV7511_DDC_STATUS_INIT_HDCP: + case ADV7511_DDC_STATUS_INIT_HDCP_REPEATER: + dev_dbg(dev, "DDC status 0x%x\n", status); + break; + default: + dev_err(dev, "Unknown status 0x%x\n", status); + return -EIO; + } + + msleep(interval); + } + + if (status) { + dev_warn(dev, "Stuck in HDCP state 0x%x\n", status); + ret = -EAGAIN; + } + + return ret; +} + static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) { @@ -547,21 +589,20 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, return -EINVAL; if (adv7511->current_edid_segment != edid_segment) { - unsigned int status; - - ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS, - &status); + /* + * EDID and HDCP shares memory so make sure HDCP is done before + * reading EDID. + */ + ret = adv7511_wait_for_hdcp(adv7511); if (ret < 0) return ret; - if (status != 2) { - adv7511->edid_read = false; - regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, - edid_segment); - ret = adv7511_wait_for_edid(adv7511, 200); - if (ret < 0) - return ret; - } + adv7511->edid_read = false; + regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, + edid_segment); + ret = adv7511_wait_for_edid(adv7511, 200); + if (ret < 0) + return ret; /* Break this apart, hopefully more I2C controllers will * support 64 byte transfers than 256 byte transfers -- 2.34.1