gfx: Fix for HDMI i2c operation not detected by some monitors.
authorAmit Bhanagay <amit.bhanagay@intel.com>
Fri, 30 Mar 2012 02:43:23 +0000 (19:43 -0700)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:48 +0000 (12:30 +0300)
HDMI i2c operations are streamlined by adding appropriate sleeps
between the operations to complete properly and avoid subsequent
failures. HDMI i2c write operation to write 2 messages
(message and payload) is changed to writing 1 message instead
(message and payload combined). Some monitors don't handle 2
messages properly.

Issue: ANDROID-238
Signed-off-by: Amit Bhanagay <amit.bhanagay@intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
drivers/staging/mrst/drv/otm_hdmi/Makefile
drivers/staging/mrst/drv/otm_hdmi/os/android/android_hdmi.c
drivers/staging/mrst/drv/otm_hdmi/pil/common/hdcp.c
drivers/staging/mrst/drv/psb_intel_hdmi.c

index 74779e8..d52c583 100644 (file)
@@ -81,6 +81,9 @@ ccflags-y += \
 #only for internal testing
 ccflags-y += -DOTM_HDMI_UNIT_TEST
 
+#enable HDCP
+ccflags-y += -DOTM_HDMI_HDCP_ENABLE
+
 ifeq ($(CONFIG_MDFD_HDMI_GREENRIDGE),y)
 ccflags-y += \
        -I$(srctree)/$(src)/drv/otm_hdmi/pil/specific/oktl \
index 0ab960f..516a3a9 100644 (file)
@@ -127,6 +127,7 @@ static u32 debug_modes_count;
 
 /*OTM_HDMI_FIXME: this should be from get attribute interface*/
 #define OTM_HDMI_I2C_ADAPTER_NUM 8
+#define OTM_HDMI_MAX_DDC_WRITE_SIZE 20
 
 #define SWITCH_DEV_HDMI_NAME "hdmi"
 #define SWITCH_DEV_DVI_NAME "dvi"
@@ -298,21 +299,41 @@ static int hdmi_ddc_read_write(bool read,
                        int size)
 {
        struct i2c_adapter *adapter = i2c_get_adapter(OTM_HDMI_I2C_ADAPTER_NUM);
-       struct i2c_msg msgs[] = {
-               {
-                       .addr   = i2c_addr,
-                       .flags  = 0,
-                       .len    = 1,
-                       .buf    = &offset,
-               }, {
-                       .addr   = i2c_addr,
-                       .flags  = ((read) ? I2C_M_RD : 0),
-                       .len    = size,
-                       .buf    = buffer,
-               }
-       };
+       struct i2c_msg msgs[2];
+       int num_of_msgs = 0;
+       uint8_t wr_buffer[OTM_HDMI_MAX_DDC_WRITE_SIZE];
+
+       /* Use one i2c message to write and two to read as some
+        * monitors don't handle two write messages properly
+       */
+       if (read) {
+               msgs[0].addr   = i2c_addr,
+               msgs[0].flags  = 0,
+               msgs[0].len    = 1,
+               msgs[0].buf    = &offset,
+
+               msgs[1].addr   = i2c_addr,
+               msgs[1].flags  = ((read) ? I2C_M_RD : 0),
+               msgs[1].len    = size,
+               msgs[1].buf    = buffer,
+
+               num_of_msgs = 2;
+       } else {
+               BUG_ON(size + 1 > OTM_HDMI_MAX_DDC_WRITE_SIZE);
+
+               wr_buffer[0] = offset;
+               memcpy(&wr_buffer[1], buffer, size);
+
+               msgs[0].addr   = i2c_addr,
+               msgs[0].flags  = 0,
+               msgs[0].len    = size + 1,
+               msgs[0].buf    = wr_buffer,
+
+               num_of_msgs = 1;
+       }
 
-       if (adapter != NULL && i2c_transfer(adapter, msgs, 2) == 2)
+       if (adapter != NULL && i2c_transfer(adapter, msgs, num_of_msgs) ==
+                                                               num_of_msgs)
                return 1;
 
        return 0;
index 6f99bdd..557cce1 100644 (file)
@@ -326,6 +326,8 @@ static bool hdcp_send_an_aksv(uint8_t *an, uint8_t an_size,
           aksv != NULL  && aksv_size == HDCP_KSV_SIZE) {
                if (hdcp_ddc_write(HDCP_RX_AN_ADDR, an, HDCP_AN_SIZE) ==
                        true) {
+                       /* wait 20ms for i2c write for An to complete */
+                       msleep(20);
                        if (hdcp_ddc_write(HDCP_RX_AKSV_ADDR, aksv,
                                        HDCP_KSV_SIZE) == true)
                                ret = true;
@@ -417,10 +419,16 @@ static int hdcp_stage1_authentication(bool *is_repeater)
        pr_debug("hdcp: bksv: %02x%02x%02x%02x%02x\n",
                        bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
 
+       /* wait 20ms for i2c read for bksv to complete */
+       msleep(20);
+
        if (hdcp_read_bcaps(&bcaps.value) == false)
                return false;
        pr_debug("hdcp: bcaps: %x\n", bcaps.value);
 
+       /* wait 20ms for i2c read for bcaps to complete */
+       msleep(20);
+
        /* Read BSTATUS */
        if (hdcp_read_bstatus(&bstatus.value) == false)
                return false;
@@ -445,15 +453,15 @@ static int hdcp_stage1_authentication(bool *is_repeater)
 
        pr_debug("hdcp: auth started\n");
 
-       /* Wait for 100ms */
-       msleep_interruptible(100);
+       /* Wait for 120ms before reading R0' */
+       msleep(120);
 
        /* Check if R0 Ready */
        retry = 20;
        do {
                if (ipil_hdcp_is_r0_ready() == true)
                        break;
-               msleep_interruptible(5);
+               msleep(5);
                retry--;
        } while (retry);
 
index e985487..78696f3 100644 (file)
@@ -337,6 +337,8 @@ static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode)
        }
        REG_READ(hdmi_priv->hdmib_reg);
 
+       android_hdmi_dpms(encoder, mode);
+
        ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
 }