In preparation of adding DRM bridge support to the hdmi4 encoder code, rework the EDID read to isolate data read. Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 94 +++++++++++++++--------- drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 59 +++------------ drivers/gpu/drm/omapdrm/dss/hdmi4_core.h | 4 +- 3 files changed, 73 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e15fa3862922..37536b9f3114 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -272,23 +272,6 @@ static int hdmi_dump_regs(struct seq_file *s, void *p) return 0; } -static int read_edid(struct omap_hdmi *hdmi, u8 *buf, int len) -{ - int r; - - mutex_lock(&hdmi->lock); - - r = hdmi_runtime_get(hdmi); - BUG_ON(r); - - r = hdmi4_read_edid(&hdmi->core, buf, len); - - hdmi_runtime_put(hdmi); - mutex_unlock(&hdmi->lock); - - return r; -} - static void hdmi_start_audio_stream(struct omap_hdmi *hd) { hdmi_wp_audio_enable(&hd->wp, true); @@ -407,10 +390,8 @@ static void hdmi_disconnect(struct omap_dss_device *src, #define MAX_EDID 512 -static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev) +static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi) { - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - bool need_enable; u8 *edid; int r; @@ -418,32 +399,79 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev) if (!edid) return NULL; + r = hdmi4_core_ddc_read(&hdmi->core, edid, 0, EDID_LENGTH); + if (r) + goto error; + + if (edid[0x7e] > 0) { + char checksum = 0; + unsigned int i; + + r = hdmi4_core_ddc_read(&hdmi->core, edid + EDID_LENGTH, 1, + EDID_LENGTH); + if (r) + goto error; + + for (i = 0; i < EDID_LENGTH; ++i) + checksum += edid[EDID_LENGTH + i]; + + if (checksum != 0) { + DSSERR("E-EDID checksum failed!!\n"); + goto error; + } + } + + return (struct edid *)edid; + +error: + kfree(edid); + return NULL; +} + +static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev) +{ + struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); + struct edid *edid = NULL; + unsigned int cec_addr; + bool need_enable; + int r; + need_enable = hdmi->core_enabled == false; if (need_enable) { r = hdmi4_core_enable(&hdmi->core); - if (r) { - kfree(edid); + if (r) return NULL; - } } - r = read_edid(hdmi, edid, MAX_EDID); - if (r < 0) { - kfree(edid); - edid = NULL; + mutex_lock(&hdmi->lock); + r = hdmi_runtime_get(hdmi); + BUG_ON(r); + + r = hdmi4_core_ddc_init(&hdmi->core); + if (r) + goto done; + + edid = hdmi_read_edid_data(hdmi); + +done: + hdmi_runtime_put(hdmi); + mutex_unlock(&hdmi->lock); + + if (edid && edid->extensions) { + unsigned int len = (edid->extensions + 1) * EDID_LENGTH; + + cec_addr = cec_get_edid_phys_addr((u8 *)edid, len, NULL); } else { - unsigned int cec_addr; - - cec_addr = r >= 256 ? cec_get_edid_phys_addr(edid, r, NULL) - : CEC_PHYS_ADDR_INVALID; - hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr); + cec_addr = CEC_PHYS_ADDR_INVALID; } + hdmi4_cec_set_phys_addr(&hdmi->core, cec_addr); + if (need_enable) hdmi4_core_disable(&hdmi->core); - return (struct edid *)edid; + return edid; } static void hdmi_lost_hotplug(struct omap_dss_device *dssdev) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index 5d5d5588ebc1..62175e85f0ef 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -32,7 +32,7 @@ static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core) return core->base + HDMI_CORE_AV; } -static int hdmi_core_ddc_init(struct hdmi_core_data *core) +int hdmi4_core_ddc_init(struct hdmi_core_data *core) { void __iomem *base = core->base; @@ -74,13 +74,11 @@ static int hdmi_core_ddc_init(struct hdmi_core_data *core) return 0; } -static int hdmi_core_ddc_edid(struct hdmi_core_data *core, - u8 *pedid, int ext) +int hdmi4_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len) { + struct hdmi_core_data *core = data; void __iomem *base = core->base; u32 i; - char checksum; - u32 offset = 0; /* HDMI_CORE_DDC_STATUS_IN_PROG */ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, @@ -89,24 +87,21 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core, return -ETIMEDOUT; } - if (ext % 2 != 0) - offset = 0x80; - /* Load Segment Address Register */ - REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, block / 2, 7, 0); /* Load Slave Address Register */ REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); /* Load Offset Address Register */ - REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, block % 2 ? 0x80 : 0, 7, 0); /* Load Byte Count */ - REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); + REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, len, 7, 0); REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); /* Set DDC_CMD */ - if (ext) + if (block) REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); else REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); @@ -122,7 +117,7 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core, return -EIO; } - for (i = 0; i < 0x80; ++i) { + for (i = 0; i < len; ++i) { int t; /* IN_PROG */ @@ -141,48 +136,12 @@ static int hdmi_core_ddc_edid(struct hdmi_core_data *core, udelay(1); } - pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); - } - - checksum = 0; - for (i = 0; i < 0x80; ++i) - checksum += pedid[i]; - - if (checksum != 0) { - DSSERR("E-EDID checksum failed!!\n"); - return -EIO; + buf[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); } return 0; } -int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len) -{ - int r, l; - - if (len < 128) - return -EINVAL; - - r = hdmi_core_ddc_init(core); - if (r) - return r; - - r = hdmi_core_ddc_edid(core, edid, 0); - if (r) - return r; - - l = 128; - - if (len >= 128 * 2 && edid[0x7e] > 0) { - r = hdmi_core_ddc_edid(core, edid + 0x80, 1); - if (r) - return r; - l += 128; - } - - return l; -} - static void hdmi_core_init(struct hdmi_core_video_config *video_cfg) { DSSDBG("Enter hdmi_core_init\n"); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h index 11c4b7ba1eee..dc64ae2aa300 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h @@ -249,7 +249,9 @@ struct hdmi_core_packet_enable_repeat { u32 generic_pkt_repeat; }; -int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len); +int hdmi4_core_ddc_init(struct hdmi_core_data *core); +int hdmi4_core_ddc_read(void *data, u8 *buf, unsigned int block, size_t len); + void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg); void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); -- Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel