From fdf4663d9f39afebde7f0a572a4ff86fd4bfc83b Mon Sep 17 00:00:00 2001 From: Mythri P K Date: Wed, 12 Oct 2011 13:20:12 +0530 Subject: 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 --- drivers/video/omap2/dss/dss_features.c | 2 +- drivers/video/omap2/dss/ti_hdmi.h | 2 + drivers/video/omap2/dss/ti_hdmi_5xxx_ip.c | 107 ++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) (limited to 'drivers/video') 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) { -- cgit v1.2.3