video: tegra: dc: HDMI VSI for extended resolution
Jon Mayo [Wed, 12 Dec 2012 00:50:41 +0000 (16:50 -0800)]
Bug 1167856

Change-Id: I40ef0501d7cbd61eb2176b45a7d9289d1d23865d
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/170281
(cherry picked from commit 33f73a0600ffd60174cfee2554d31216dfd4c343)
Reviewed-on: http://git-master/r/193499
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Rakesh Iyer <riyer@nvidia.com>

drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/dc/hdmi.h

index 27f7014..131269d 100644 (file)
@@ -1520,6 +1520,22 @@ static int tegra_dc_find_cea_vic(const struct tegra_dc_mode *mode)
        return 0;
 }
 
+static int tegra_dc_find_hdmi_vic(const struct tegra_dc_mode *mode)
+{
+       struct fb_videomode m;
+       unsigned i;
+
+       tegra_dc_to_fb_videomode(&m, mode);
+
+       for (i = 1; i < HDMI_EXT_MODEDB_SIZE; i++) {
+               const struct fb_videomode *curr = &hdmi_ext_modes[i];
+
+               if (fb_mode_is_equal(&m, curr))
+                       return i;
+       }
+       return 0;
+}
+
 static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
 {
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
@@ -1553,18 +1569,24 @@ static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
                          HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
 }
 
+static void tegra_dc_hdmi_disable_generic_infoframe(struct tegra_dc *dc)
+{
+       struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+       u32 val;
+
+       val  = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+       val &= ~GENERIC_CTRL_ENABLE;
+       tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+}
+
 static void tegra_dc_hdmi_setup_stereo_infoframe(struct tegra_dc *dc)
 {
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
        struct hdmi_stereo_infoframe stereo;
        u32 val;
 
-       if (!dc->mode.stereo_mode) {
-               val  = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-               val &= ~GENERIC_CTRL_ENABLE;
-               tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
-               return;
-       }
+       WARN(!dc->mode.stereo_mode,
+               "function assumes 3D/stereo mode is disabled\n");
 
        memset(&stereo, 0x0, sizeof(stereo));
 
@@ -1590,6 +1612,35 @@ static void tegra_dc_hdmi_setup_stereo_infoframe(struct tegra_dc *dc)
        tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
 }
 
+static void tegra_dc_hdmi_setup_hdmi_vic_infoframe(struct tegra_dc *dc)
+{
+       struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
+       struct hdmi_extres_infoframe extres;
+       int hdmi_vic;
+       u32 val;
+
+       hdmi_vic = tegra_dc_find_hdmi_vic(&dc->mode);
+       if (hdmi_vic <= 0) {
+               tegra_dc_hdmi_disable_generic_infoframe(dc);
+               return;
+       }
+
+       extres.csum = 0;
+       extres.regid0 = 0x03;
+       extres.regid1 = 0x0c;
+       extres.regid2 = 0x00;
+       extres.hdmi_video_format = 1; /* Extended Resolution Format */
+       extres.hdmi_vic = hdmi_vic;
+
+       tegra_dc_hdmi_write_infopack(dc,
+               HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
+               HDMI_INFOFRAME_TYPE_VENDOR, HDMI_VENDOR_VERSION,
+               &extres, 5);
+       val = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+       val |= GENERIC_CTRL_ENABLE;
+       tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
+}
+
 static void tegra_dc_hdmi_setup_audio_infoframe(struct tegra_dc *dc, bool dvi)
 {
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
@@ -1764,7 +1815,13 @@ static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
 
        tegra_dc_hdmi_setup_avi_infoframe(dc, hdmi->dvi);
        tegra_dc_hdmi_setup_audio_infoframe(dc, hdmi->dvi);
-       tegra_dc_hdmi_setup_stereo_infoframe(dc);
+
+       if (dc->mode.stereo_mode)
+               tegra_dc_hdmi_setup_stereo_infoframe(dc);
+       else if (dc->mode.avi_m) /* Extended resolution format */
+               tegra_dc_hdmi_setup_hdmi_vic_infoframe(dc);
+       else /* else disable sending of this infoframe */
+               tegra_dc_hdmi_disable_generic_infoframe(dc);
 
        /* TMDS CONFIG */
        for (i = 0; i < ARRAY_SIZE(tdms_config); i++) {
index d6509ef..9313baa 100644 (file)
@@ -72,7 +72,7 @@ struct hdmi_avi_infoframe {
 
        /* PB12-13 */
        u16             right_bar_start_pixel;
-} __attribute__((packed));
+} __packed;
 
 #define HDMI_AVI_VERSION               0x02
 
@@ -133,7 +133,7 @@ struct hdmi_audio_infoframe {
        u8              res8;
        u8              res9;
        u8              res10;
-} __attribute__((packed));
+} __packed;
 
 #define HDMI_AUDIO_VERSION             0x01
 
@@ -208,7 +208,29 @@ struct hdmi_stereo_infoframe {
        unsigned        res3:4;
        unsigned        _3d_ext_data:4;
 
-} __attribute__((packed));
+} __packed;
+
+/* Vendor Specific Infoframe - Extended resolution format */
+struct hdmi_extres_infoframe {
+       /* PB0 */
+       u8              csum;
+
+       /* PB1 */
+       u8              regid0;
+
+       /* PB2 */
+       u8              regid1;
+
+       /* PB3 */
+       u8              regid2;
+
+       /* PB4 */
+       unsigned        res1:5;
+       unsigned        hdmi_video_format:3;
+
+       /* PB5 */
+       u8              hdmi_vic;
+} __packed;
 
 #define HDMI_VENDOR_VERSION 0x01