summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorMythri P K <mythripk@ti.com>2011-10-12 13:20:12 +0530
committerAndy Green <andy.green@linaro.org>2012-06-22 10:04:55 +0800
commitfdf4663d9f39afebde7f0a572a4ff86fd4bfc83b (patch)
treec8120c74607f11dc6c329c12999df3ebc12f6398 /drivers/video
parentda1be31f2442106fc928b630a371ac5713bc96fa (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>
Diffstat (limited to 'drivers/video')
-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.c107
3 files changed, 110 insertions, 1 deletions
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index a697bf3d0522..e55223253740 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -704,7 +704,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 b592af07c0fa..17a3b58f2615 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -203,4 +203,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 f9b978eba841..8a56c938663c 100644
--- a/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c
@@ -61,6 +61,113 @@ 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)
{