video: tegra: dc: use side-by-side stereo HDMI mode
Andrija Bosnjakovic [Tue, 14 Feb 2012 02:41:26 +0000 (18:41 -0800)]
Add a config option to limit HDMI stereo 3D output to 74.25MHz pixel clock.

When this option is set,
substitute the frame pack stereo modes
for side-by-side (half) left-right stereo modes
to meet this pixel clock restriction.

By default, do not use it (use frame packed HDMI mode as usual).

Bug 938807

Change-Id: I2ce2ca72cbb15ac1939af0f3386dd23650262435
Reviewed-on: http://git-master/r/84252
Reviewed-by: Andrija Bosnjakovic <abosnjakovic@nvidia.com>
Tested-by: Andrija Bosnjakovic <abosnjakovic@nvidia.com>
Reviewed-by: Jon Mayo <jmayo@nvidia.com>

drivers/video/tegra/Kconfig
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/edid.c
drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/fb.c

index 041afed..1429f36 100644 (file)
@@ -121,5 +121,12 @@ config TEGRA_NVHDCP
          Say Y here to support NVHDCP upstream and downstream protocols, this
          requires a correctly fused chip to negotiate keys.
 
+config TEGRA_HDMI_74MHZ_LIMIT
+       bool "Support only up to 74.25 MHz HDMI pixel frequency"
+       default n
+       help
+         Say Y here to make kernel report only low bandwidth modes.
+         Useful only for boards which can't deliver 148.50 MHz.
+
 endif
 
index 0756430..e64b935 100644 (file)
@@ -1755,6 +1755,8 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc,
                mode.h_ref_to_sync, mode.v_ref_to_sync
        );
 
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
+       /* Double the pixel clock and update v_active only for frame packed mode */
        if (mode.stereo_mode) {
                mode.pclk *= 2;
                /* total v_active = yres*2 + activespace */
@@ -1763,6 +1765,7 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc,
                                fbmode->upper_margin +
                                fbmode->lower_margin;
        }
+#endif
 
        mode.flags = 0;
 
index dd92154..fbcf2cc 100644 (file)
@@ -388,7 +388,11 @@ int tegra_edid_get_monspecs_test(struct tegra_edid *edid,
                                        if (tegra_edid_mode_support_stereo(
                                                &specs->modedb[j]))
                                                specs->modedb[j].vmode |=
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
                                                FB_VMODE_STEREO_FRAME_PACK;
+#else
+                                               FB_VMODE_STEREO_LEFT_RIGHT;
+#endif
                                }
                        }
                }
@@ -466,7 +470,11 @@ int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs)
                                        if (tegra_edid_mode_support_stereo(
                                                &specs->modedb[j]))
                                                specs->modedb[j].vmode |=
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
                                                FB_VMODE_STEREO_FRAME_PACK;
+#else
+                                               FB_VMODE_STEREO_LEFT_RIGHT;
+#endif
                                }
                        }
                }
index 58af4c9..4d5bccc 100644 (file)
@@ -128,7 +128,11 @@ const struct fb_videomode tegra_dc_hdmi_supported_modes[] = {
                .right_margin = 110,    /* h_front_porch */
                .lower_margin = 5,      /* v_front_porch */
                .vmode = FB_VMODE_NONINTERLACED |
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
                                 FB_VMODE_STEREO_FRAME_PACK,
+#else
+                                FB_VMODE_STEREO_LEFT_RIGHT,
+#endif
                .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
        },
 
@@ -189,7 +193,11 @@ const struct fb_videomode tegra_dc_hdmi_supported_modes[] = {
                .right_margin = 638,    /* h_front_porch */
                .lower_margin = 4,      /* v_front_porch */
                .vmode = FB_VMODE_NONINTERLACED |
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
                                 FB_VMODE_STEREO_FRAME_PACK,
+#else
+                                FB_VMODE_STEREO_LEFT_RIGHT,
+#endif
                .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
        },
 
@@ -714,6 +722,11 @@ static bool tegra_dc_hdmi_mode_filter(const struct tegra_dc *dc,
        if (!mode->pixclock)
                return false;
 
+#ifdef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
+       if (PICOS2KHZ(mode->pixclock) > 74250)
+               return false;
+#endif
+
        for (i = 0; i < ARRAY_SIZE(tegra_dc_hdmi_supported_modes); i++) {
                const struct fb_videomode *supported_mode
                                = &tegra_dc_hdmi_supported_modes[i];
@@ -1523,7 +1536,12 @@ static void tegra_dc_hdmi_setup_stereo_infoframe(struct tegra_dc *dc)
        stereo.regid1 = 0x0c;
        stereo.regid2 = 0x00;
        stereo.hdmi_video_format = 2; /* 3D_Structure present */
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
        stereo._3d_structure = 0; /* frame packing */
+#else
+       stereo._3d_structure = 8; /* side-by-side (half) */
+       stereo._3d_ext_data = 0; /* something which fits into 00XX bit req */
+#endif
 
        tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
                                        HDMI_INFOFRAME_TYPE_VENDOR,
index f7b3fd1..350cede 100644 (file)
@@ -134,7 +134,11 @@ static int tegra_fb_set_par(struct fb_info *info)
                 * client requests it
                 */
                stereo = !!(var->vmode & info->mode->vmode &
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
                                        FB_VMODE_STEREO_FRAME_PACK);
+#else
+                                       FB_VMODE_STEREO_LEFT_RIGHT);
+#endif
 
                tegra_dc_set_fb_mode(tegra_fb->win->dc, info->mode, stereo);