summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30-panel.c268
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30.h3
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20-panel.c270
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20.h3
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30-panel.c278
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30.h3
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h9
-rw-r--r--drivers/video/tegra/dc/ext/dev.c4
-rw-r--r--drivers/video/tegra/dc/mode.c186
-rw-r--r--drivers/video/tegra/fb.c235
10 files changed, 332 insertions, 927 deletions
diff --git a/arch/arm/mach-tegra/board-apalis_t30-panel.c b/arch/arm/mach-tegra/board-apalis_t30-panel.c
index cb76ca99c083..1be339dce6ef 100644
--- a/arch/arm/mach-tegra/board-apalis_t30-panel.c
+++ b/arch/arm/mach-tegra/board-apalis_t30-panel.c
@@ -211,278 +211,15 @@ static struct resource apalis_t30_disp2_resources[] = {
};
#endif /* CONFIG_TEGRA_DC */
-static struct tegra_dc_mode apalis_t30_panel_modes[] = {
-#ifdef TEGRA_FB_VGA
- {
- /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
- .pclk = 25175000, /* pixclock */
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 96, /* hsync_len */
- .v_sync_width = 2, /* vsync_len */
- .h_back_porch = 48, /* left_margin */
- .v_back_porch = 33, /* upper_margin */
- .h_active = 640,
- .v_active = 480,
- .h_front_porch = 16, /* right_margin */
- .v_front_porch = 10, /* lower_margin */
- },
- {
- /* 800x480@60 (e.g. EDT ET070080DH6) */
- .pclk = 32460000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 64,
- .v_sync_width = 3,
- .h_back_porch = 128,
- .v_back_porch = 22,
- .h_active = 800,
- .v_active = 480,
- .h_front_porch = 64,
- .v_front_porch = 20,
- },
- {
- /* 800x600@60 */
- .pclk = 39272727,
- .h_sync_width = 80,
- .v_sync_width = 2,
- .h_back_porch = 160,
- .v_back_porch = 21,
- .h_active = 800,
- .v_active = 600,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
- CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
- .pclk = 48000000,
- .h_sync_width = 5,
- .v_sync_width = 5,
- .h_back_porch = 104,
- .v_back_porch = 24,
- .h_active = 1024,
- .v_active = 600,
- .h_front_porch = 43,
- .v_front_porch = 20,
- },
- {
- /* 1024x768@60 */
- .pclk = 78800000,
- .h_sync_width = 96,
- .v_sync_width = 3,
- .h_back_porch = 176,
- .v_back_porch = 28,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* 1024x768@75 */
- .pclk = 82000000,
- .h_sync_width = 104,
- .v_sync_width = 4,
- .h_back_porch = 168,
- .v_back_porch = 34,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 64,
- .v_front_porch = 3,
- },
- {
- /* 1280x720@60 */
- .pclk = 74250000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 40,
- .v_sync_width = 5,
- .h_back_porch = 220,
- .v_back_porch = 20,
- .h_active = 1280,
- .v_active = 720,
- .h_front_porch = 110,
- .v_front_porch = 5,
-//high active sync polarities
- },
- {
- /* 1280x1024@60 */
- .pclk = 108000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 144,
- .v_sync_width = 3,
- .h_back_porch = 248,
- .v_back_porch = 38,
- .h_active = 1280,
- .v_active = 1024,
- .h_front_porch = 16,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- /* 1366x768@60 */
- .pclk = 72072000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 58,
- .v_sync_width = 4,
- .h_back_porch = 58,
- .v_back_porch = 4,
- .h_active = 1366,
- .v_active = 768,
- .h_front_porch = 58,
- .v_front_porch = 4,
- },
- {
- /* 1600x1200@60 */
- .pclk = 162000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 192,
- .v_sync_width = 3,
- .h_back_porch = 304,
- .v_back_porch = 46,
- .h_active = 1600,
- .v_active = 1200,
- .h_front_porch = 64,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- .pclk = 119000000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 32,
- .v_sync_width = 6,
- .h_back_porch = 80,
- .v_back_porch = 21,
- .h_active = 1680,
- .v_active = 1050,
- .h_front_porch = 48,
- .v_front_porch = 3,
- },
- {
- /* 1680x1050@60 */
- .pclk = 147140000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 184,
- .v_sync_width = 3,
- .h_back_porch = 288,
- .v_back_porch = 33,
- .h_active = 1680,
- .v_active = 1050,
- .h_front_porch = 104,
- .v_front_porch = 1,
-//high active vertical sync polarity
- },
-#else /* TEGRA_FB_VGA */
- {
- /* LG LP156WF1 15.6 inch full HD dual channel LVDS panel */
- .pclk = 138500000,
- .h_sync_width = 32,
- .v_sync_width = 5,
- .h_back_porch = 80,
- .v_back_porch = 46,
- .h_active = 1920,
- .v_active = 1080,
- .h_front_porch = 48,
- .v_front_porch = 6,
- //low active sync polarities, high pixel clock polarity
- },
- {
- /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
- .pclk = 148500000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 44,
- .v_sync_width = 5,
- .h_back_porch = 148,
- .v_back_porch = 36,
- .h_active = 1920,
- .v_active = 1080,
- .h_front_porch = 88,
- .v_front_porch = 4,
-//high active sync polarities
- },
- {
- .pclk = 154000000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 32,
- .v_sync_width = 6,
- .h_back_porch = 80,
- .v_back_porch = 26,
- .h_active = 1920,
- .v_active = 1200,
- .h_front_porch = 48,
- .v_front_porch = 3,
- },
-
- /* portrait modes */
-
- {
- .pclk = 18000000,
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 1,
- .h_back_porch = 20,
- .v_back_porch = 7,
- .h_active = 480,
- .v_active = 640,
- .h_front_porch = 8,
- .v_front_porch = 8,
- },
- {
- .pclk = 10000000,
- .h_ref_to_sync = 4,
- .v_ref_to_sync = 1,
- .h_sync_width = 16,
- .v_sync_width = 1,
- .h_back_porch = 32,
- .v_back_porch = 1,
- .h_active = 540,
- .v_active = 960,
- .h_front_porch = 32,
- .v_front_porch = 2,
- },
- {
- .pclk = 61417000,
- .h_ref_to_sync = 2,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 4,
- .h_back_porch = 100,
- .v_back_porch = 14,
- .h_active = 720,
- .v_active = 1280,
- .h_front_porch = 4,
- .v_front_porch = 4,
- },
-#endif /* TEGRA_FB_VGA */
-};
#ifdef CONFIG_TEGRA_DC
static struct tegra_fb_data apalis_t30_fb_data = {
.win = 0,
-#ifdef TEGRA_FB_VGA
- .xres = 640,
- .yres = 480,
-#else /* TEGRA_FB_VGA */
- .xres = 1920,
- .yres = 1080,
-#endif /* TEGRA_FB_VGA */
- .bits_per_pixel = 16,
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
static struct tegra_fb_data apalis_t30_hdmi_fb_data = {
.win = 0,
- .xres = 640,
- .yres = 480,
- .bits_per_pixel = 16,
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
@@ -511,8 +248,7 @@ static struct tegra_dc_out apalis_t30_disp1_out = {
.depth = 24,
.dither = TEGRA_DC_ORDERED_DITHER,
- .modes = apalis_t30_panel_modes,
- .n_modes = ARRAY_SIZE(apalis_t30_panel_modes),
+ .default_mode = "640x480-16@60",
.out_pins = apalis_t30_dc_out_pins,
.n_out_pins = ARRAY_SIZE(apalis_t30_dc_out_pins),
@@ -531,6 +267,8 @@ static struct tegra_dc_out apalis_t30_disp2_out = {
.max_pixclock = KHZ2PICOS(148500),
+ .default_mode = "640x480-16@60",
+
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
diff --git a/arch/arm/mach-tegra/board-apalis_t30.h b/arch/arm/mach-tegra/board-apalis_t30.h
index 8c11647b8319..9fde9ef1d89e 100644
--- a/arch/arm/mach-tegra/board-apalis_t30.h
+++ b/arch/arm/mach-tegra/board-apalis_t30.h
@@ -26,9 +26,6 @@
#include <mach/gpio.h>
#include <mach/irqs.h>
-/* Run framebuffer in VGA mode */
-//#define TEGRA_FB_VGA
-
/* GPIO */
#define APALIS_GPIO1 TEGRA_GPIO_PS2
diff --git a/arch/arm/mach-tegra/board-colibri_t20-panel.c b/arch/arm/mach-tegra/board-colibri_t20-panel.c
index 6c6ff73eb318..c4746590d209 100644
--- a/arch/arm/mach-tegra/board-colibri_t20-panel.c
+++ b/arch/arm/mach-tegra/board-colibri_t20-panel.c
@@ -208,268 +208,13 @@ static struct resource colibri_t20_disp2_resources[] = {
},
};
-static struct tegra_dc_mode colibri_t20_panel_modes[] = {
-#ifdef TEGRA_FB_VGA
- {
- /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
- .pclk = 25175000, /* pixclock */
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 96, /* hsync_len */
- .v_sync_width = 2, /* vsync_len */
- .h_back_porch = 48, /* left_margin */
- .v_back_porch = 33, /* upper_margin */
- .h_active = 640,
- .v_active = 480,
- .h_front_porch = 16, /* right_margin */
- .v_front_porch = 10, /* lower_margin */
- },
-#else /* TEGRA_FB_VGA */
- {
- /* 800x480@60 (e.g. EDT ET070080DH6) */
- .pclk = 32460000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 64,
- .v_sync_width = 3,
- .h_back_porch = 128,
- .v_back_porch = 22,
- .h_active = 800,
- .v_active = 480,
- .h_front_porch = 64,
- .v_front_porch = 20,
- },
- {
- /* 800x600@60 */
- .pclk = 39272727,
- .h_sync_width = 80,
- .v_sync_width = 2,
- .h_back_porch = 160,
- .v_back_porch = 21,
- .h_active = 800,
- .v_active = 600,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
- CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
- .pclk = 48000000,
- .h_sync_width = 5,
- .v_sync_width = 5,
- .h_back_porch = 104,
- .v_back_porch = 24,
- .h_active = 1024,
- .v_active = 600,
- .h_front_porch = 43,
- .v_front_porch = 20,
- },
- {
- /* 1024x768@60 */
-//pll_c 76Hz
- .pclk = 78800000,
- .h_sync_width = 96,
- .v_sync_width = 3,
- .h_back_porch = 176,
- .v_back_porch = 28,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* 1024x768@75 */
- .pclk = 82000000,
- .h_sync_width = 104,
- .v_sync_width = 4,
- .h_back_porch = 168,
- .v_back_porch = 34,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 64,
- .v_front_porch = 3,
- },
- {
- /* 1280x720@70 */
- .pclk = 86400000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 40,
- .v_sync_width = 5,
- .h_back_porch = 220,
- .v_back_porch = 20,
- .h_active = 1280,
- .v_active = 720,
- .h_front_porch = 110,
- .v_front_porch = 5,
-//high active sync polarities
- },
- {
- /* 1280x1024@60 */
- .pclk = 108000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 144,
- .v_sync_width = 3,
- .h_back_porch = 248,
- .v_back_porch = 38,
- .h_active = 1280,
- .v_active = 1024,
- .h_front_porch = 16,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- /* 1366x768@60 */
- .pclk = 72072000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 58,
- .v_sync_width = 4,
- .h_back_porch = 58,
- .v_back_porch = 4,
- .h_active = 1366,
- .v_active = 768,
- .h_front_porch = 58,
- .v_front_porch = 4,
- },
- {
- /* 1600x1200@60 */
- .pclk = 144000000,
-//[ 1.423072] tegradc tegradc.0: can't divide 216000000 clock to 162000000 -1/+9% 144000000 160380000 176580000
-// .pclk = 162000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 192,
- .v_sync_width = 3,
- .h_back_porch = 304,
- .v_back_porch = 46,
- .h_active = 1600,
- .v_active = 1200,
- .h_front_porch = 64,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- /* 1680x1050@60 */
- .pclk = 144000000,
-//[ 1.423139] tegradc tegradc.0: can't divide 216000000 clock to 147140000 -1/+9% 144000000 145668600 160382600
-// .pclk = 147140000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 184,
- .v_sync_width = 3,
- .h_back_porch = 288,
- .v_back_porch = 33,
- .h_active = 1680,
- .v_active = 1050,
- .h_front_porch = 104,
- .v_front_porch = 1,
-//high active vertical sync polarity
- },
- {
- /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
- .pclk = 144000000,
-//[ 3.361002] tegradc tegradc.0: can't divide 216000000 clock to 148500000 -1/+9% 144000000 147015000 161865000
-// .pclk = 148500000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 44,
- .v_sync_width = 5,
- .h_back_porch = 148,
- .v_back_porch = 36,
- .h_active = 1920,
- .v_active = 1080,
- .h_front_porch = 88,
- .v_front_porch = 4,
-//high active sync polarities
- },
- {
- .pclk = 144000000,
-//[ 3.371657] tegradc tegradc.0: can't divide 216000000 clock to 154000000 -1/+9% 144000000 152460000 167860000
-// .pclk = 154000000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 32,
- .v_sync_width = 6,
- .h_back_porch = 80,
- .v_back_porch = 26,
- .h_active = 1920,
- .v_active = 1200,
- .h_front_porch = 48,
- .v_front_porch = 3,
- },
-
- /* portrait modes */
-
- {
- .pclk = 18000000,
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 1,
- .h_back_porch = 20,
- .v_back_porch = 7,
- .h_active = 480,
- .v_active = 640,
- .h_front_porch = 8,
- .v_front_porch = 8,
- },
- {
- .pclk = 10000000,
- .h_ref_to_sync = 4,
- .v_ref_to_sync = 1,
- .h_sync_width = 16,
- .v_sync_width = 1,
- .h_back_porch = 32,
- .v_back_porch = 1,
- .h_active = 540,
- .v_active = 960,
- .h_front_porch = 32,
- .v_front_porch = 2,
- },
- {
- .pclk = 61417000,
- .h_ref_to_sync = 2,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 4,
- .h_back_porch = 100,
- .v_back_porch = 14,
- .h_active = 720,
- .v_active = 1280,
- .h_front_porch = 4,
- .v_front_porch = 4,
- },
-#endif /* TEGRA_FB_VGA */
-};
-
static struct tegra_fb_data colibri_t20_fb_data = {
.win = 0,
-#ifdef TEGRA_FB_VGA
- .xres = 640,
- .yres = 480,
-#else /* TEGRA_FB_VGA */
- .xres = 800,
- .yres = 480,
-#endif /* TEGRA_FB_VGA */
-#ifndef CONFIG_ANDROID
- .bits_per_pixel = 16,
-#else
- .bits_per_pixel = 32,
-#endif
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
static struct tegra_fb_data colibri_t20_hdmi_fb_data = {
.win = 0,
- .xres = 640,
- .yres = 480,
-#ifndef CONFIG_ANDROID
- .bits_per_pixel = 16,
-#else
- .bits_per_pixel = 32,
-#endif
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
@@ -499,8 +244,12 @@ static struct tegra_dc_out colibri_t20_disp1_out = {
.depth = 18,
.dither = TEGRA_DC_ORDERED_DITHER,
- .modes = colibri_t20_panel_modes,
- .n_modes = ARRAY_SIZE(colibri_t20_panel_modes),
+ /* Use 32-bit depth for android builds */
+#ifdef CONFIG_ANDROID
+ .default_mode = "640x480-32@60",
+#else /* CONFIG_ANDROID */
+ .default_mode = "640x480-16@60",
+#endif /* CONFIG_ANDROID */
.out_pins = colibri_t20_dc_out_pins,
.n_out_pins = ARRAY_SIZE(colibri_t20_dc_out_pins),
@@ -518,6 +267,13 @@ static struct tegra_dc_out colibri_t20_disp2_out = {
.max_pixclock = KHZ2PICOS(148500),
+ /* Use 32-bit depth for android builds */
+#ifdef CONFIG_ANDROID
+ .default_mode = "640x480-32@60",
+#else /* CONFIG_ANDROID */
+ .default_mode = "640x480-16@60",
+#endif /* CONFIG_ANDROID */
+
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
diff --git a/arch/arm/mach-tegra/board-colibri_t20.h b/arch/arm/mach-tegra/board-colibri_t20.h
index c7f2c5dcad33..23e9cdbda749 100644
--- a/arch/arm/mach-tegra/board-colibri_t20.h
+++ b/arch/arm/mach-tegra/board-colibri_t20.h
@@ -23,9 +23,6 @@
#define COLIBRI_T20_VI
#endif
-/* Run framebuffer in VGA mode */
-#define TEGRA_FB_VGA
-
/* Uncomment to activate 32-bit GMI address/databus */
//#define GMI_32BIT
diff --git a/arch/arm/mach-tegra/board-colibri_t30-panel.c b/arch/arm/mach-tegra/board-colibri_t30-panel.c
index bbbbbe3dddd3..14c711039f41 100644
--- a/arch/arm/mach-tegra/board-colibri_t30-panel.c
+++ b/arch/arm/mach-tegra/board-colibri_t30-panel.c
@@ -213,277 +213,14 @@ static struct resource colibri_t30_disp2_resources[] = {
.flags = IORESOURCE_MEM,
},
};
-#endif /* CONFIG_TEGRA_DC */
-static struct tegra_dc_mode colibri_t30_panel_modes[] = {
-#ifdef TEGRA_FB_VGA
- {
- /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
- .pclk = 25175000, /* pixclock */
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 96, /* hsync_len */
- .v_sync_width = 2, /* vsync_len */
- .h_back_porch = 48, /* left_margin */
- .v_back_porch = 33, /* upper_margin */
- .h_active = 640,
- .v_active = 480,
- .h_front_porch = 16, /* right_margin */
- .v_front_porch = 10, /* lower_margin */
- },
-#else /* TEGRA_FB_VGA */
- {
- /* 800x480@60 (e.g. EDT ET070080DH6) */
- .pclk = 32460000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 64,
- .v_sync_width = 3,
- .h_back_porch = 128,
- .v_back_porch = 22,
- .h_active = 800,
- .v_active = 480,
- .h_front_porch = 64,
- .v_front_porch = 20,
- },
- {
- /* 800x600@60 */
- .pclk = 39272727,
- .h_sync_width = 80,
- .v_sync_width = 2,
- .h_back_porch = 160,
- .v_back_porch = 21,
- .h_active = 800,
- .v_active = 600,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
- CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
- .pclk = 48000000,
- .h_sync_width = 5,
- .v_sync_width = 5,
- .h_back_porch = 104,
- .v_back_porch = 24,
- .h_active = 1024,
- .v_active = 600,
- .h_front_porch = 43,
- .v_front_porch = 20,
- },
- {
- /* 1024x768@60 */
- .pclk = 78800000,
- .h_sync_width = 96,
- .v_sync_width = 3,
- .h_back_porch = 176,
- .v_back_porch = 28,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 16,
- .v_front_porch = 1,
- },
- {
- /* 1024x768@75 */
- .pclk = 82000000,
- .h_sync_width = 104,
- .v_sync_width = 4,
- .h_back_porch = 168,
- .v_back_porch = 34,
- .h_active = 1024,
- .v_active = 768,
- .h_front_porch = 64,
- .v_front_porch = 3,
- },
- {
- /* 1280x720@60 */
- .pclk = 74250000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 40,
- .v_sync_width = 5,
- .h_back_porch = 220,
- .v_back_porch = 20,
- .h_active = 1280,
- .v_active = 720,
- .h_front_porch = 110,
- .v_front_porch = 5,
-//high active sync polarities
- },
- {
- /* 1280x1024@60 */
- .pclk = 108000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 144,
- .v_sync_width = 3,
- .h_back_porch = 248,
- .v_back_porch = 38,
- .h_active = 1280,
- .v_active = 1024,
- .h_front_porch = 16,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- /* 1366x768@60 */
- .pclk = 72072000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 58,
- .v_sync_width = 4,
- .h_back_porch = 58,
- .v_back_porch = 4,
- .h_active = 1366,
- .v_active = 768,
- .h_front_porch = 58,
- .v_front_porch = 4,
- },
- {
- /* 1600x1200@60 */
- .pclk = 162000000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 192,
- .v_sync_width = 3,
- .h_back_porch = 304,
- .v_back_porch = 46,
- .h_active = 1600,
- .v_active = 1200,
- .h_front_porch = 64,
- .v_front_porch = 1,
-//high active sync polarities
- },
- {
- .pclk = 119000000,
- .h_ref_to_sync = 1,
- .v_ref_to_sync = 1,
- .h_sync_width = 32,
- .v_sync_width = 6,
- .h_back_porch = 80,
- .v_back_porch = 21,
- .h_active = 1680,
- .v_active = 1050,
- .h_front_porch = 48,
- .v_front_porch = 3,
- },
- {
- /* 1680x1050@60 */
- .pclk = 147140000,
-// .h_ref_to_sync = 1,
-// .v_ref_to_sync = 1,
- .h_sync_width = 184,
- .v_sync_width = 3,
- .h_back_porch = 288,
- .v_back_porch = 33,
- .h_active = 1680,
- .v_active = 1050,
- .h_front_porch = 104,
- .v_front_porch = 1,
-//high active vertical sync polarity
- },
- {
- /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
- .pclk = 148500000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 44,
- .v_sync_width = 5,
- .h_back_porch = 148,
- .v_back_porch = 36,
- .h_active = 1920,
- .v_active = 1080,
- .h_front_porch = 88,
- .v_front_porch = 4,
-//high active sync polarities
- },
- {
- .pclk = 154000000,
- .h_ref_to_sync = 11,
- .v_ref_to_sync = 1,
- .h_sync_width = 32,
- .v_sync_width = 6,
- .h_back_porch = 80,
- .v_back_porch = 26,
- .h_active = 1920,
- .v_active = 1200,
- .h_front_porch = 48,
- .v_front_porch = 3,
- },
-
- /* portrait modes */
-
- {
- .pclk = 18000000,
- .h_ref_to_sync = 8,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 1,
- .h_back_porch = 20,
- .v_back_porch = 7,
- .h_active = 480,
- .v_active = 640,
- .h_front_porch = 8,
- .v_front_porch = 8,
- },
- {
- .pclk = 10000000,
- .h_ref_to_sync = 4,
- .v_ref_to_sync = 1,
- .h_sync_width = 16,
- .v_sync_width = 1,
- .h_back_porch = 32,
- .v_back_porch = 1,
- .h_active = 540,
- .v_active = 960,
- .h_front_porch = 32,
- .v_front_porch = 2,
- },
- {
- .pclk = 61417000,
- .h_ref_to_sync = 2,
- .v_ref_to_sync = 2,
- .h_sync_width = 4,
- .v_sync_width = 4,
- .h_back_porch = 100,
- .v_back_porch = 14,
- .h_active = 720,
- .v_active = 1280,
- .h_front_porch = 4,
- .v_front_porch = 4,
- },
-#endif /* TEGRA_FB_VGA */
-};
-
-#ifdef CONFIG_TEGRA_DC
static struct tegra_fb_data colibri_t30_fb_data = {
.win = 0,
-#ifdef TEGRA_FB_VGA
- .xres = 640,
- .yres = 480,
-#else /* TEGRA_FB_VGA */
- .xres = 800,
- .yres = 480,
-#endif /* TEGRA_FB_VGA */
-#ifndef CONFIG_ANDROID
- .bits_per_pixel = 16,
-#else
- .bits_per_pixel = 32,
-#endif
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
static struct tegra_fb_data colibri_t30_hdmi_fb_data = {
.win = 0,
-#ifndef CONFIG_ANDROID
- .xres = 640,
- .yres = 480,
- .bits_per_pixel = 16,
-#else /* CONFIG_ANDROID */
- .xres = 1920,
- .yres = 1080,
- .bits_per_pixel = 32,
-#endif /* !CONFIG_ANDROID */
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
@@ -512,8 +249,12 @@ static struct tegra_dc_out colibri_t30_disp1_out = {
.depth = 18,
.dither = TEGRA_DC_ORDERED_DITHER,
- .modes = colibri_t30_panel_modes,
- .n_modes = ARRAY_SIZE(colibri_t30_panel_modes),
+ /* Use 32-bit depth for android builds */
+#ifdef CONFIG_ANDROID
+ .default_mode = "640x480-32@60",
+#else /* CONFIG_ANDROID */
+ .default_mode = "640x480-16@60",
+#endif /* CONFIG_ANDROID */
.out_pins = colibri_t30_dc_out_pins,
.n_out_pins = ARRAY_SIZE(colibri_t30_dc_out_pins),
@@ -532,6 +273,13 @@ static struct tegra_dc_out colibri_t30_disp2_out = {
.max_pixclock = KHZ2PICOS(148500),
+ /* Use 32-bit depth and Full HD for android builds */
+#ifdef CONFIG_ANDROID
+ .default_mode = "1920x1080-32@60",
+#else /* CONFIG_ANDROID */
+ .default_mode = "640x480-16@60",
+#endif /* CONFIG_ANDROID */
+
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
diff --git a/arch/arm/mach-tegra/board-colibri_t30.h b/arch/arm/mach-tegra/board-colibri_t30.h
index 21de318173ea..85563fe222ba 100644
--- a/arch/arm/mach-tegra/board-colibri_t30.h
+++ b/arch/arm/mach-tegra/board-colibri_t30.h
@@ -32,9 +32,6 @@
#define COLIBRI_T30_VI
#endif
-/* Run framebuffer in VGA mode */
-#define TEGRA_FB_VGA
-
/* GPIO */
#define DDC_SCL TEGRA_GPIO_PV4 /* X2-15 */
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index d22a58f22a60..13dc8c0be03a 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -353,6 +353,8 @@ struct tegra_dc_out {
unsigned depth;
unsigned dither;
+ const char *default_mode;
+
struct tegra_dc_mode *modes;
int n_modes;
@@ -550,6 +552,8 @@ bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts);
bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts);
#endif /* !CONFIG_ANDROID */
+int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var,
+ struct tegra_dc_mode *mode);
int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode);
struct fb_videomode;
int tegra_dc_set_fb_mode(struct tegra_dc *dc, const struct fb_videomode *fbmode,
@@ -594,8 +598,9 @@ struct tegra_dc_edid {
struct tegra_dc_edid *tegra_dc_get_edid(struct tegra_dc *dc);
void tegra_dc_put_edid(struct tegra_dc_edid *edid);
-int tegra_dc_set_flip_callback(void (*callback)(void));
+int tegra_dc_set_flip_callback(int (*callback)(void));
int tegra_dc_unset_flip_callback(void);
int tegra_dc_get_panel_sync_rate(void);
-
+int tegra_fb_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const char* option, unsigned int default_bpp);
#endif
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index c8104deb5ed6..37a6d9bd3f80 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -296,7 +296,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
#endif /* !CONFIG_ANDROID */
}
-static void (*flip_callback)(void);
+static int (*flip_callback)(void);
static spinlock_t flip_callback_lock;
static bool init_tegra_dc_flip_callback_called;
@@ -309,7 +309,7 @@ static int __init init_tegra_dc_flip_callback(void)
pure_initcall(init_tegra_dc_flip_callback);
-int tegra_dc_set_flip_callback(void (*callback)(void))
+int tegra_dc_set_flip_callback(int (*callback)(void))
{
WARN_ON(!init_tegra_dc_flip_callback_called);
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
index 6457f9604e90..be0d2bc5f035 100644
--- a/drivers/video/tegra/dc/mode.c
+++ b/drivers/video/tegra/dc/mode.c
@@ -26,6 +26,84 @@
#include "dc_reg.h"
#include "dc_priv.h"
+const struct fb_videomode tegra_modes[] = {
+ /* TouchRevolution Fusion 10" aka Chunghwa Picture Tubes
+ * CLAA100NC05 10.1 inch 1024x600 single channel LVDS panel
+ */
+ {
+ .name = "1024x600", .refresh = 60, .xres = 1024, .yres = 600,
+ .pixclock = 20833, .left_margin = 104, .right_margin = 43,
+ .upper_margin = 24, .lower_margin = 20,
+ .hsync_len = 5, .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ /* EDT 5.7" ET070080DH or TouchRevolution Fusion 7" */
+ {
+ .name = "800x480", .refresh = 60, .xres = 800, .yres = 480,
+ .pixclock = 30807, .left_margin = 128, .right_margin = 64,
+ .upper_margin = 22, .lower_margin = 20,
+ .hsync_len = 64, .vsync_len = 3,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ /* Portrait modes */
+ {
+ .name = "480x640", .refresh = 60, .xres = 480, .yres = 640,
+ .pixclock = 55555, .left_margin = 20, .right_margin = 8,
+ .upper_margin = 7, .lower_margin = 8,
+ .hsync_len = 4, .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
+ .name = "540x960", .refresh = 60, .xres = 540, .yres = 960,
+ .pixclock = 100000, .left_margin = 32, .right_margin = 32,
+ .upper_margin = 1, .lower_margin = 2,
+ .hsync_len = 16, .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
+ .name = "720x1280", .refresh = 60, .xres = 720, .yres = 1280,
+ .pixclock = 16282, .left_margin = 100, .right_margin = 4,
+ .upper_margin = 14, .lower_margin = 4,
+ .hsync_len = 4, .vsync_len = 4,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+};
+
+/* try to find best matching mode using our modes, VESA and CEA modes from
+ * modedb
+ */
+int tegra_fb_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const char* option, unsigned int default_bpp)
+{
+ int out;
+
+ out = fb_find_mode(var, info, option, tegra_modes,
+ ARRAY_SIZE(tegra_modes), NULL, default_bpp);
+
+ /* Only accept this mode if we found a reasonable match (resolution) */
+ if (out == 1 || out == 2)
+ return out;
+
+ out = fb_find_mode(&info->var, info, option,
+ cea_modes, CEA_MODEDB_SIZE, NULL, default_bpp);
+
+ /* Check if we found a full match */
+ if (out == 1 || out == 2)
+ return out;
+
+ return fb_find_mode(&info->var, info, option,
+ vesa_modes, VESA_MODEDB_SIZE, NULL, default_bpp);
+}
+EXPORT_SYMBOL(tegra_fb_find_mode);
+
+
/* return non-zero if constraint is violated */
static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
{
@@ -272,6 +350,11 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
{
memcpy(&dc->mode, mode, sizeof(dc->mode));
+ dev_info(&dc->ndev->dev, "using mode %dx%d pclk=%d href=%d vref=%d\n",
+ mode->h_active, mode->v_active, mode->pclk,
+ mode->h_ref_to_sync, mode->v_ref_to_sync
+ );
+
if (dc->out->type == TEGRA_DC_OUT_RGB)
panel_sync_rate = tegra_dc_calc_refresh(mode);
else if (dc->out->type == TEGRA_DC_OUT_DSI)
@@ -286,9 +369,89 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
}
EXPORT_SYMBOL(tegra_dc_set_mode);
+int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var,
+ struct tegra_dc_mode *mode)
+{
+ bool stereo_mode = false;
+ int err;
+
+ if (!var->pixclock)
+ return -EINVAL;
+
+ mode->pclk = PICOS2KHZ(var->pixclock) * 1000;
+ mode->h_sync_width = var->hsync_len;
+ mode->v_sync_width = var->vsync_len;
+ mode->h_back_porch = var->left_margin;
+ mode->v_back_porch = var->upper_margin;
+ mode->h_active = var->xres;
+ mode->v_active = var->yres;
+ mode->h_front_porch = var->right_margin;
+ mode->v_front_porch = var->lower_margin;
+ mode->stereo_mode = stereo_mode;
+
+ /*
+ * HACK:
+ * If v_front_porch is only 1, we would violate Constraint 5/6
+ * in this case, increase front porch by 1
+ */
+ if (mode->v_front_porch <= 1)
+ mode->v_front_porch = 2;
+
+
+ if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+ /* HDMI controller requires h_ref=1, v_ref=1 */
+ mode->h_ref_to_sync = 1;
+ mode->v_ref_to_sync = 1;
+ } else {
+ /* Calculate ref_to_sync signals */
+ err = calc_ref_to_sync(mode);
+ if (err) {
+ dev_err(&dc->ndev->dev, "display timing ref_to_sync"
+ "calculation failed with code %d\n", err);
+ return -EINVAL;
+ }
+ dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n",
+ mode->h_ref_to_sync, mode->v_ref_to_sync);
+ }
+ if (!check_ref_to_sync(mode)) {
+ dev_err(&dc->ndev->dev,
+ "display timing doesn't meet restrictions.\n");
+ return -EINVAL;
+ }
+
+#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 */
+ mode->v_active = var->yres * 2 +
+ var->vsync_len +
+ var->upper_margin +
+ var->lower_margin;
+ }
+#endif
+
+ mode->flags = 0;
+
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ mode->flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
+
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ mode->flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_var_to_dc_mode);
+
+/*
+ * This method is only used by sysfs interface
+ * /sys/devices/tegradc.1/nvdps
+ */
int tegra_dc_set_fb_mode(struct tegra_dc *dc,
const struct fb_videomode *fbmode, bool stereo_mode)
{
+ int err;
struct tegra_dc_mode mode;
if (!fbmode->pixclock)
@@ -309,17 +472,28 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc,
mode.h_ref_to_sync = 1;
mode.v_ref_to_sync = 1;
} else {
- calc_ref_to_sync(&mode);
+ /*
+ * HACK:
+ * If v_front_porch is only 1, we would violate Constraint 5/6
+ * in this case, increase front porch by 1
+ */
+ if (mode.v_front_porch <= 1)
+ mode.v_front_porch = 2;
+
+ err = calc_ref_to_sync(&mode);
+ if (err) {
+ dev_err(&dc->ndev->dev, "display timing ref_to_sync"
+ "calculation failed with code %d\n", err);
+ return -EINVAL;
+ }
+ dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n",
+ mode.h_ref_to_sync, mode.v_ref_to_sync);
}
if (!check_ref_to_sync(&mode)) {
dev_err(&dc->ndev->dev,
- "Display timing doesn't meet restrictions.\n");
+ "display timing doesn't meet restrictions.\n");
return -EINVAL;
}
- dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
- mode.h_active, mode.v_active, mode.pclk,
- 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
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index f14ffb46b2dd..70b82bde9e43 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -55,9 +55,6 @@ struct tegra_fb_info {
bool valid;
struct resource *fb_mem;
-
- int xres;
- int yres;
};
/* palette array used by the fbcon */
@@ -87,8 +84,35 @@ static int tegra_fb_check_var(struct fb_var_screeninfo *var,
}
/* Double yres_virtual to allow double buffering through pan_display */
+ var->xres_virtual = var->xres;
var->yres_virtual = var->yres * 2;
+ /* we only support RGB ordering for now */
+ switch (var->bits_per_pixel) {
+ case 32:
+ case 24:
+ var->bits_per_pixel = 32;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 16;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ case 16:
+ default:
+ var->bits_per_pixel = 16;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+ }
+
return 0;
}
@@ -97,108 +121,61 @@ static int tegra_fb_set_par(struct fb_info *info)
struct tegra_fb_info *tegra_fb = info->par;
struct fb_var_screeninfo *var = &info->var;
struct tegra_dc *dc = tegra_fb->win->dc;
+ int err;
- if (var->bits_per_pixel) {
- /* we only support RGB ordering for now */
- switch (var->bits_per_pixel) {
- case 32:
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 16;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5;
- break;
-
- default:
- return -EINVAL;
- }
- /* if line_length unset, then pad the stride */
- info->fix.line_length = var->xres * var->bits_per_pixel / 8;
- info->fix.line_length = round_up(info->fix.line_length,
- TEGRA_LINEAR_PITCH_ALIGNMENT);
- tegra_fb->win->stride = info->fix.line_length;
- tegra_fb->win->stride_uv = 0;
- tegra_fb->win->phys_addr_u = 0;
- tegra_fb->win->phys_addr_v = 0;
- }
-
- if (var->pixclock) {
- bool stereo;
- unsigned old_len = 0;
- struct fb_videomode m;
- struct fb_videomode *old_mode = NULL;
-
- fb_var_to_videomode(&m, var);
+ struct tegra_dc_mode mode;
-#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_COLIBRI_T30)
- /* Hack: avoid 24 Hz mode in X resulting in no display at all */
- if (m.refresh < 50) m.refresh = 60;
-#endif /* CONFIG_MACH_APALIS_T30 | CONFIG_MACH_COLIBRI_T30 */
-
- /* Load framebuffer info with new mode details*/
- old_mode = info->mode;
- old_len = info->fix.line_length;
-
- info->mode = (struct fb_videomode *)
- fb_find_nearest_mode(&m, &info->modelist);
- if (!info->mode) {
- dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n");
- info->mode = old_mode;
- return -EINVAL;
- }
+ /* This is usually altered to 16/32 by tegra_fb_check_var
+ * above which is called before this function
+ */
+ switch (var->bits_per_pixel) {
+ case 32:
+ tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8;
+ break;
+ case 16:
+ tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
- /* Update fix line_length and window stride as per new mode */
- info->fix.line_length = var->xres * var->bits_per_pixel / 8;
- info->fix.line_length = round_up(info->fix.line_length,
- TEGRA_LINEAR_PITCH_ALIGNMENT);
- tegra_fb->win->stride = info->fix.line_length;
+ /* if line_length unset, then pad the stride */
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
+ info->fix.line_length = round_up(info->fix.line_length,
+ TEGRA_LINEAR_PITCH_ALIGNMENT);
+ tegra_fb->win->stride = info->fix.line_length;
+ tegra_fb->win->stride_uv = 0;
+ tegra_fb->win->phys_addr_u = 0;
+ tegra_fb->win->phys_addr_v = 0;
+
+ tegra_fb->win->w.full = dfixed_const(var->xres);
+ tegra_fb->win->h.full = dfixed_const(var->yres);
+ tegra_fb->win->out_w = var->xres;
+ tegra_fb->win->out_h = var->yres;
+
+ dev_info(&tegra_fb->ndev->dev, "switching framebuffer to %dx%d\n",
+ var->xres, var->yres);
+
+ err = tegra_dc_var_to_dc_mode(dc, var, &mode);
+ if (err) {
+ dev_warn(&tegra_fb->ndev->dev, "could not convert var %d\n", err);
+ return -EINVAL;
+ }
- /*
- * only enable stereo if the mode supports it and
- * 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
+ err = tegra_dc_set_mode(dc, &mode);
+ if (err) {
+ dev_warn(&tegra_fb->ndev->dev, "could not set dc mode %d\n", err);
+ return -EINVAL;
+ }
- /* Configure DC with new mode */
- if (tegra_dc_set_fb_mode(dc, info->mode, stereo)) {
- /* Error while configuring DC, fallback to old mode */
- dev_warn(&tegra_fb->ndev->dev, "can't configure dc with mode %ux%u\n",
- info->mode->xres, info->mode->yres);
- info->mode = old_mode;
- info->fix.line_length = old_len;
- tegra_fb->win->stride = old_len;
- return -EINVAL;
- }
+ /* Reflect changes on HW */
+ if (dc->enabled)
+ tegra_dc_disable(dc);
+ tegra_dc_enable(dc);
- /* Reflect mode chnage on DC HW */
- if (dc->enabled)
- tegra_dc_disable(dc);
- tegra_dc_enable(dc);
+ return err;
- tegra_fb->win->w.full = dfixed_const(info->mode->xres);
- tegra_fb->win->h.full = dfixed_const(info->mode->yres);
- tegra_fb->win->out_w = info->mode->xres;
- tegra_fb->win->out_h = info->mode->yres;
- }
- return 0;
}
static int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -600,6 +577,9 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
unsigned long fb_phys = 0;
int ret = 0;
unsigned stride;
+ char *param_option = NULL;
+ const char *option = NULL;
+ char driver[10];
win = tegra_dc_get_window(dc, fb_data->win);
if (!win) {
@@ -618,8 +598,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_fb->win = win;
tegra_fb->ndev = ndev;
tegra_fb->fb_mem = fb_mem;
- tegra_fb->xres = fb_data->xres;
- tegra_fb->yres = fb_data->yres;
if (fb_mem) {
fb_size = resource_size(fb_mem);
@@ -656,6 +634,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->var.xres_virtual = fb_data->xres;
info->var.yres_virtual = fb_data->yres * 2;
info->var.bits_per_pixel = fb_data->bits_per_pixel;
+
info->var.activate = FB_ACTIVATE_VBL;
info->var.height = tegra_dc_get_out_height(dc);
info->var.width = tegra_dc_get_out_width(dc);
@@ -668,11 +647,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->var.vsync_len = 0;
info->var.vmode = FB_VMODE_NONINTERLACED;
+ /* window settings */
win->x.full = dfixed_const(0);
win->y.full = dfixed_const(0);
win->w.full = dfixed_const(fb_data->xres);
win->h.full = dfixed_const(fb_data->yres);
- /* TODO: set to output res dc */
win->out_x = 0;
win->out_y = 0;
win->out_w = fb_data->xres;
@@ -686,6 +665,40 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
win->stride_uv = 0;
win->flags = TEGRA_WIN_FLAG_ENABLED;
+ /* try to use kernel cmd line specified mode */
+ sprintf(driver, "tegrafb%d", ndev->id);
+ fb_get_options(driver, &param_option);
+ if (param_option != NULL) {
+ option = param_option;
+ dev_info(&ndev->dev, "parse cmd options for %s: %s\n",
+ driver, option);
+ } else {
+ option = dc->out->default_mode;
+ dev_info(&ndev->dev, "use default mode for %s: %s\n",
+ driver, option);
+ }
+
+ if (option != NULL)
+ {
+ if (!strcmp(option, "off")) {
+ /* This off option works perfectly for framebuffer
+ * device, however the tegra binary driver somehow
+ * has troubles to handle a missing fb0 when there
+ * (then, dc1 gets remapped to fb0, which seems
+ * to be an issue for the binary driver)...
+ */
+ ret = -ENODEV;
+ goto err_iounmap_fb;
+ }
+ if (!tegra_fb_find_mode(&info->var, info, option, 16)) {
+ ret = -EINVAL;
+ goto err_iounmap_fb;
+ }
+ }
+
+ /* Activate current settings (tegra_fb_find_mode has call
+ * tegra_fb_check_var already)
+ */
if (fb_mem)
tegra_fb_set_par(info);
@@ -704,26 +717,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_dc_sync_windows(&tegra_fb->win, 1);
}
- if (dc->mode.pclk > 1000) {
- struct tegra_dc_mode *mode = &dc->mode;
- struct fb_videomode vmode;
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- info->var.pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
- else
- info->var.pixclock = KHZ2PICOS(mode->pclk / 1000);
- info->var.left_margin = mode->h_back_porch;
- info->var.right_margin = mode->h_front_porch;
- info->var.upper_margin = mode->v_back_porch;
- info->var.lower_margin = mode->v_front_porch;
- info->var.hsync_len = mode->h_sync_width;
- info->var.vsync_len = mode->v_sync_width;
-
- /* Keep info->var consistent with info->modelist. */
- fb_var_to_videomode(&vmode, &info->var);
- fb_add_videomode(&vmode, &info->modelist);
- }
-
return tegra_fb;
err_iounmap_fb: