]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: dc: support HDMI avi format values
authorJon Mayo <jmayo@nvidia.com>
Tue, 11 Dec 2012 21:02:12 +0000 (13:02 -0800)
committerDan Willemsen <dwillemsen@nvidia.com>
Sat, 14 Sep 2013 08:28:44 +0000 (01:28 -0700)
Support all HDMI VIC format values using cea_modes[] list for determining the
the AVI format number.  Stores aspect ratio in fb_videmode and tegra_dc_mode so
that ambiguous modes are resolved.

Bug 1167856
Bug 1173814

Change-Id: Icf66753732076b99dd0ff0163f4a4f6a9f90ae57
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/170279
Reviewed-by: Mrutyunjay Sawant <msawant@nvidia.com>
Tested-by: Mrutyunjay Sawant <msawant@nvidia.com>
arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/dc/mode.c

index 251c9e92c6f6f101bc38b9845af61140fdb8948c..0e2f7e7d8f1ae075a3458b575ace65ac5ba7d501 100644 (file)
@@ -318,11 +318,16 @@ struct tegra_dc_mode {
        int     v_front_porch;
        int     stereo_mode;
        u32     flags;
+       u8      avi_m;
 };
 
 #define TEGRA_DC_MODE_FLAG_NEG_V_SYNC  (1 << 0)
 #define TEGRA_DC_MODE_FLAG_NEG_H_SYNC  (1 << 1)
 
+/* aspect ratio. 0 means unspecified or default. */
+#define TEGRA_DC_MODE_AVI_M_4_3                0x1
+#define TEGRA_DC_MODE_AVI_M_16_9       0x2
+
 enum {
        TEGRA_DC_OUT_RGB,
        TEGRA_DC_OUT_HDMI,
index d871bea4d0947990236a896814b872bc8003b996..78e377086690fb6de78daf79bd6387b3540bfb09 100644 (file)
@@ -1509,6 +1509,30 @@ static void tegra_dc_hdmi_write_infopack(struct tegra_dc *dc, int header_reg,
        }
 }
 
+static int tegra_dc_find_cea_vic(const struct tegra_dc_mode *mode)
+{
+       struct fb_videomode m;
+       unsigned i;
+
+       tegra_dc_to_fb_videomode(&m, mode);
+
+       for (i = 1; i < CEA_MODEDB_SIZE; i++) {
+               const struct fb_videomode *curr = &cea_modes[i];
+               if (fb_mode_is_equal(&m, curr)) {
+                       /* if either flag is set, then match is required */
+                       if (m.flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) {
+                               if (m.flag & curr->flag & FB_FLAG_RATIO_4_3)
+                                       return i;
+                               if (m.flag & curr->flag & FB_FLAG_RATIO_16_9)
+                                       return i;
+                       } else {
+                               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);
@@ -1529,52 +1553,9 @@ static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
        else
                tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
 
-       if (dc->mode.v_active == 480) {
-               if (dc->mode.h_active == 640) {
-                       avi.m = HDMI_AVI_M_4_3;
-                       avi.vic = 1;
-               } else {
-                       avi.m = HDMI_AVI_M_16_9;
-                       avi.vic = 3;
-               }
-       } else if (dc->mode.v_active == 576) {
-               /* CEC modes 17 and 18 differ only by the pysical size of the
-                * screen so we have to calculation the physical aspect
-                * ratio.  4 * 10 / 3  is 13
-                */
-               if ((dc->out->h_size * 10) / dc->out->v_size > 14) {
-                       avi.m = HDMI_AVI_M_16_9;
-                       avi.vic = 18;
-               } else {
-                       avi.m = HDMI_AVI_M_4_3;
-                       avi.vic = 17;
-               }
-       } else if (dc->mode.v_active == 720 ||
-               (dc->mode.v_active == 1470 && dc->mode.stereo_mode)) {
-               /* VIC for both 720p and 720p 3D mode */
-               avi.m = HDMI_AVI_M_16_9;
-               if (dc->mode.h_front_porch == 110)
-                       avi.vic = 4; /* 60 Hz */
-               else
-                       avi.vic = 19; /* 50 Hz */
-       } else if (dc->mode.v_active == 1080 ||
-               (dc->mode.v_active == 2205 && dc->mode.stereo_mode)) {
-               /* VIC for both 1080p and 1080p 3D mode */
-               avi.m = HDMI_AVI_M_16_9;
-               if (dc->mode.h_front_porch == 88) {
-                       if (dc->mode.pclk > 74250000)
-                               avi.vic = 16; /* 60 Hz */
-                       else
-                               avi.vic = 34; /* 30 Hz */
-               } else if (dc->mode.h_front_porch == 528)
-                       avi.vic = 31; /* 50 Hz */
-               else
-                       avi.vic = 32; /* 24 Hz */
-       } else {
-               avi.m = HDMI_AVI_M_16_9;
-               avi.vic = 0;
-       }
-
+       avi.vic = tegra_dc_find_cea_vic(&dc->mode);
+       avi.m = dc->mode.avi_m;
+       dev_dbg(&dc->ndev->dev, "HDMI AVI vic=%d m=%d\n", avi.vic, avi.m);
 
        tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
                                     HDMI_INFOFRAME_TYPE_AVI,
@@ -1718,6 +1699,7 @@ static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
 
        /* program HDMI registers and SOR sequencer */
 
+       tegra_dc_io_start(dc);
        tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
        tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
                        DC_DISP_DISP_COLOR_CONTROL);
@@ -1891,6 +1873,7 @@ static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
        tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
        tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1);
+       tegra_dc_io_end(dc);
 }
 
 static void tegra_dc_hdmi_disable(struct tegra_dc *dc)
index 747706ef45dbc8610a62c71ea9b03ecfb9ec509c..c9812f46527c8162bdd6b8c135cae50fe658172c 100644 (file)
@@ -327,6 +327,11 @@ int tegra_dc_to_fb_videomode(struct fb_videomode *fbmode,
                fbmode->sync |=  FB_SYNC_HOR_HIGH_ACT;
        if (!(mode->flags & TEGRA_DC_MODE_FLAG_NEG_V_SYNC))
                fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+       if (mode->avi_m == TEGRA_DC_MODE_AVI_M_16_9)
+               fbmode->flag |= FB_FLAG_RATIO_16_9;
+       else if (mode->avi_m == TEGRA_DC_MODE_AVI_M_4_3)
+               fbmode->flag |= FB_FLAG_RATIO_4_3;
+
        if (mode->rated_pclk >= 1000)
                fbmode->pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
        else if (mode->pclk >= 1000)
@@ -361,6 +366,21 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc,
        mode.h_front_porch = fbmode->right_margin;
        mode.v_front_porch = fbmode->lower_margin;
        mode.stereo_mode = stereo_mode;
+       if (fbmode->flag & FB_FLAG_RATIO_16_9)
+               mode.avi_m = TEGRA_DC_MODE_AVI_M_16_9;
+       else if (fbmode->flag & FB_FLAG_RATIO_4_3)
+               mode.avi_m = TEGRA_DC_MODE_AVI_M_4_3;
+       else if (dc->out) { /* if ratio is unspecified, detect a default */
+               unsigned h_size = dc->out->h_size;
+               unsigned v_size = dc->out->v_size;
+
+               /* get aspect ratio */
+               if (h_size * 18 > v_size * 31 && h_size * 18 < v_size * 33)
+                       mode.avi_m = TEGRA_DC_MODE_AVI_M_16_9;
+               if (h_size * 18 > v_size * 23 && h_size * 18 < v_size * 25)
+                       mode.avi_m = TEGRA_DC_MODE_AVI_M_4_3;
+       }
+
        if (dc->out->type == TEGRA_DC_OUT_HDMI) {
                /* HDMI controller requires h_ref=1, v_ref=1 */
                mode.h_ref_to_sync = 1;