summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorSandor Yu <R01008@freescale.com>2011-11-22 20:25:32 +0800
committerJason Liu <r64343@freescale.com>2012-01-09 21:08:08 +0800
commita31d875aaf366af6d11952e542d9013328499056 (patch)
tree43affda6498830b3800cdb89e6a6a922150458f8 /drivers/video
parentc7c60b9a52b8962a73f283fa6a863e2a7b3629c0 (diff)
ENGR00162881 Workaround for some MX6x boards failed read EDID data
HDMI video mode setting in command line will not work if no EDID data reading from HDMI sink. Creat a default modelist for HDMI video mode when no EDID data. Then default video mode can work even if no EDID data. Signed-off-by: Sandor Yu <R01008@freescale.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/mxc_hdmi.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c
index 95083f2ebd3a..0298c243b1a9 100644
--- a/drivers/video/mxc_hdmi.c
+++ b/drivers/video/mxc_hdmi.c
@@ -138,6 +138,8 @@ struct mxc_hdmi {
struct i2c_client *hdmi_i2c;
+extern const struct fb_videomode mxc_cea_mode[64];
+
/*!
* this submodule is responsible for the video data synchronization.
* for example, for RGB 4:4:4 input, the data map is defined as
@@ -1226,6 +1228,9 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi,
ret = mxc_edid_read(hdmi_i2c->adapter, hdmi_i2c->addr,
hdmi->edid, &hdmi->edid_cfg, fbi);
+ if (ret < 0)
+ return ret;
+
if (!memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN))
ret = -2;
return ret;
@@ -1298,9 +1303,27 @@ static void mxc_hdmi_disable(struct mxc_hdmi *hdmi)
clk_disable(hdmi->hdmi_iahb_clk);
}
+static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi)
+{
+ u32 i;
+ const struct fb_videomode *mode;
+
+ fb_destroy_modelist(&hdmi->fbi->modelist);
+
+ for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) {
+ mode = &mxc_cea_mode[i];
+ if ((mode->xres == hdmi->fbi->var.xres) &&
+ (mode->yres == hdmi->fbi->var.yres) &&
+ !(mode->vmode & FB_VMODE_INTERLACED))
+ fb_add_videomode(mode, &hdmi->fbi->modelist);
+ }
+}
+
static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
{
int ret;
+ struct fb_videomode m;
+ const struct fb_videomode *mode;
dev_dbg(&hdmi->pdev->dev, "cable connected\n");
@@ -1308,14 +1331,10 @@ static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
/* edid read */
ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi);
- if (ret == -1)
- dev_err(&hdmi->pdev->dev, "read edid fail\n");
- else if (ret == -2)
+ if (ret == -2)
dev_info(&hdmi->pdev->dev, "same edid\n");
else if (hdmi->fbi->monspecs.modedb_len > 0) {
int i;
- const struct fb_videomode *mode;
- struct fb_videomode m;
fb_destroy_modelist(&hdmi->fbi->modelist);
@@ -1343,8 +1362,19 @@ static int mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi)
fb_videomode_to_var(&hdmi->fbi->var, mode);
hdmi->need_mode_change = true;
- } else
+ } else {
+ /* If not EDID data readed, setup default modelist */
dev_info(&hdmi->pdev->dev, "No modes read from edid\n");
+ mxc_hdmi_default_modelist(hdmi);
+
+ fb_var_to_videomode(&m, &hdmi->fbi->var);
+ mode = fb_find_nearest_mode(&m,
+ &hdmi->fbi->modelist);
+
+ fb_videomode_to_var(&hdmi->fbi->var, mode);
+ hdmi->need_mode_change = true;
+ }
+
return 0;
}
@@ -1593,6 +1623,9 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
int irq = platform_get_irq(hdmi->pdev, 0);
bool found = false;
u8 val;
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+ struct fb_var_screeninfo var;
if (!plat || irq < 0)
return -ENODEV;
@@ -1658,13 +1691,19 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_entry *disp)
/* try to read edid */
ret = mxc_hdmi_read_edid(hdmi, hdmi->fbi);
- if (ret < 0)
- dev_warn(&hdmi->pdev->dev, "Can not read edid\n");
- else if (hdmi->fbi->monspecs.modedb_len > 0) {
+ if (ret < 0) {
+ /* If not EDID data readed, setup default modelist */
+ dev_info(&hdmi->pdev->dev, "No modes read from edid\n");
+ mxc_hdmi_default_modelist(hdmi);
+
+ fb_var_to_videomode(&m, &hdmi->fbi->var);
+ mode = fb_find_nearest_mode(&m,
+ &hdmi->fbi->modelist);
+
+ fb_videomode_to_var(&hdmi->fbi->var, mode);
+ hdmi->need_mode_change = true;
+ } else if (hdmi->fbi->monspecs.modedb_len > 0) {
int i;
- const struct fb_videomode *mode;
- struct fb_videomode m;
- struct fb_var_screeninfo var;
for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) {
/*