diff options
author | Sandor Yu <R01008@freescale.com> | 2011-11-22 20:25:32 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 21:08:08 +0800 |
commit | a31d875aaf366af6d11952e542d9013328499056 (patch) | |
tree | 43affda6498830b3800cdb89e6a6a922150458f8 /drivers/video | |
parent | c7c60b9a52b8962a73f283fa6a863e2a7b3629c0 (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.c | 63 |
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++) { /* |