veyron: Pulse the i2c clock once if sda was low

On one particular TV the TV was holding SDA low when it came up.  It
would release the SDA when the SCL went low the first time.
Unfortunately the HDMI i2c port wouldn't transmit until the SDA was
released.

Let's detect this case and insert a bogus clock pulse to try to get the
other side to release SDA.

It's unclear why the kernel doesn't have this problem.

BRANCH=none
BUG=chrome-os-partner:46256
TEST=Insignia TV works now

Change-Id: I4b6361877e0576cc4ea2f643f073f1aab660e434
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/309258
Reviewed-by: Agnes Cheng <agnescheng@google.com>
Commit-Queue: Agnes Cheng <agnescheng@google.com>
Trybot-Ready: Agnes Cheng <agnescheng@google.com>
Tested-by: Agnes Cheng <agnescheng@google.com>
This commit is contained in:
Douglas Anderson 2015-10-27 16:05:15 -07:00 committed by Agnes Cheng
commit 1bf29c99f1
4 changed files with 16 additions and 12 deletions

View file

@ -86,10 +86,6 @@ static void configure_hdmi(void)
/* set POWER_HDMI_ON */
gpio_output(GPIO(7, A, 2), 1);
/* HDMI I2C */
writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda);
writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl);
}
static void mainboard_init(device_t dev)

View file

@ -141,10 +141,6 @@ static void configure_hdmi(void)
gpio_output(GPIO(5, C, 3), 1);
break;
}
/* HDMI I2C */
writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda);
writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl);
}
static void mainboard_init(device_t dev)

View file

@ -82,10 +82,6 @@ static void configure_vop(void)
static void configure_hdmi(void)
{
/* HDMI I2C */
writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda);
writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl);
gpio_output(GPIO(7, B, 3), 1); /* POWER_HDMI_ON */
}

View file

@ -15,6 +15,7 @@
#include <console/console.h>
#include <delay.h>
#include <edid.h>
#include <gpio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@ -775,8 +776,23 @@ int rk_hdmi_get_edid(struct edid *edid)
{
u8 edid_buf[HDMI_EDID_BLOCK_SIZE * 2];
u32 edid_size = HDMI_EDID_BLOCK_SIZE;
gpio_t hdmi_i2c_sda = GPIO(7, C, 3);
gpio_t hdmi_i2c_scl = GPIO(7, C, 4);
int ret;
/* If SDA is low, try to clock once to fix it */
gpio_input_pullup(hdmi_i2c_sda);
if (gpio_get(hdmi_i2c_sda) == 0) {
gpio_output(hdmi_i2c_scl, 0);
udelay(1000);
gpio_input_pullup(hdmi_i2c_scl);
udelay(1000);
}
/* HDMI I2C */
writel(IOMUX_HDMI_EDP_I2C_SDA, &rk3288_grf->iomux_i2c5sda);
writel(IOMUX_HDMI_EDP_I2C_SCL, &rk3288_grf->iomux_i2c5scl);
ret = hdmi_read_edid(0, edid_buf);
if (ret) {
hdmi_debug("failed to read edid.\n");