summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2012-05-18 19:45:02 +0530
committerAndy Green <andy.green@linaro.org>2012-11-27 11:42:19 +0800
commitbbde67d791804e9f5566aeb2a096494eac38cf91 (patch)
tree4be8ee6c68ba03e5c3c4a72ee179db28c3d378e7
parent62e743d4e1d0aec2d3278b85e28c5aae9d67ebab (diff)
OMAPDSS: HDMI: Add EDID read support for OMAP5
Core block in OMAP5 HDMI is different from OMAP4. so add support to read EDID. Signed-off-by: Mythri P K <mythripk@ti.com> Conflicts: drivers/video/omap2/dss/ti_hdmi.h
-rw-r--r--drivers/video/omap2/dss/dss_features.c2
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h2
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c115
3 files changed, 118 insertions, 1 deletions
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index cca823ab94b..f039303524e 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -831,7 +831,7 @@ static const struct ti_hdmi_ip_ops omap5_hdmi_functions = {
.video_configure = ti_hdmi_5xxx_basic_configure,
.phy_enable = ti_hdmi_4xxx_phy_enable,
.phy_disable = ti_hdmi_4xxx_phy_disable,
- .read_edid = NULL,
+ .read_edid = ti_hdmi_5xxx_read_edid,
.pll_enable = ti_hdmi_4xxx_pll_enable,
.pll_disable = ti_hdmi_4xxx_pll_disable,
.video_enable = ti_hdmi_4xxx_wp_video_start,
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 5246319c34c..e3c6336f937 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -186,4 +186,6 @@ int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
#endif
void ti_hdmi_5xxx_basic_configure(struct hdmi_ip_data *ip_data);
void ti_hdmi_5xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
+int ti_hdmi_5xxx_read_edid(struct hdmi_ip_data *ip_data,
+ u8 *edid, int len);
#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c
index c55d844e37a..04807862e25 100644
--- a/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c
@@ -61,6 +61,121 @@ static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
return val;
}
+static inline void hdmi_core_ddc_req_addr(struct hdmi_ip_data *ip_data,
+ u8 addr, int ext)
+{
+ u8 seg_ptr = ext / 2;
+ u8 edidaddr = ((ext % 2) * 0x80) + addr;
+ void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_ADDRESS, edidaddr, 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SEGPTR, seg_ptr, 7, 0);
+
+ if (seg_ptr)
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_OPERATION, 1, 1, 1);
+ else
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_OPERATION, 1, 0, 0);
+}
+
+static void hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
+{
+ void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+
+ /*Mask the interrupts*/
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_CTLINT, 0x0, 2, 2);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_CTLINT, 0x0, 6, 6);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_INT, 0x0, 2, 2);
+
+ /* Master clock division */
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_DIV, 0x5, 2, 0);
+
+ /* Standard speed counter */
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR, 0x0,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR, 0x79,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR, 0x0,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR, 0x91,
+ 7, 0);
+
+ /* Fast speed counter*/
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR, 0x0,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR, 0x0F,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR, 0x0,
+ 7, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR, 0x21,
+ 7, 0);
+
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SLAVE, 0x50, 6, 0);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_SEGADDR, 0x30, 6, 0);
+}
+
+static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
+ u8 *pedid, int ext)
+{
+ u8 cur_addr = 0;
+ char checksum = 0;
+ void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
+
+ hdmi_core_ddc_req_addr(ip_data, cur_addr, ext);
+
+ /* Unmask the interrupts*/
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6);
+ REG_FLD_MOD(core_sys_base, HDMI_CORE_I2CM_INT, 0x1, 2, 2);
+
+ /* FIXME:This is a hack to read only 128 bytes data with a mdelay
+ * Ideally the read has to be based on the done interrupt and
+ * status which is not received thus it is ignored for now
+ */
+ while (cur_addr < 128) {
+ #if 0
+ if (hdmi_wait_for_bit_change(HDMI_CORE_I2CM_INT,
+ 0, 0, 1) != 1) {
+ DSSERR("Failed to recieve done interrupt\n");
+ return -ETIMEDOUT;
+ }
+ #endif
+ mdelay(1);
+ pedid[cur_addr] = REG_GET(core_sys_base,
+ HDMI_CORE_I2CM_DATAI, 7, 0);
+ DSSDBG("pedid[%d] = %d", cur_addr, pedid[cur_addr]);
+ checksum += pedid[cur_addr++];
+ hdmi_core_ddc_req_addr(ip_data, cur_addr, ext);
+ }
+ return 0;
+
+}
+
+int ti_hdmi_5xxx_read_edid(struct hdmi_ip_data *ip_data,
+ u8 *edid, int len)
+{
+ int r, l;
+
+ if (len < 128)
+ return -EINVAL;
+
+ hdmi_core_ddc_init(ip_data);
+
+ r = hdmi_core_ddc_edid(ip_data, edid, 0);
+ if (r)
+ return r;
+
+ l = 128;
+
+ if (len >= 128 * 2 && edid[0x7e] > 0) {
+ r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
+ if (r)
+ return r;
+ l += 128;
+ }
+
+ return l;
+}
+
void ti_hdmi_5xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
{