From 09fe75f6f934597f765748342ca6fb378ee7ecdb Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Tue, 16 Oct 2007 01:28:56 -0700 Subject: [PATCH] s3c2410fb: multi-display support This patch adds a new structure to describe and handle more than one panel (display mode) for the s3c2410 framebuffer. This structure is added after the pxafb driver. Signed-off-by: Krzysztof Helt Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-s3c2410/mach-amlm5900.c | 49 +++---- arch/arm/mach-s3c2410/mach-bast.c | 177 ++++++++++++++++++++---- arch/arm/mach-s3c2410/mach-h1940.c | 26 ++-- arch/arm/mach-s3c2410/mach-qt2410.c | 252 ++++++++++++++-------------------- arch/arm/mach-s3c2440/mach-rx3715.c | 38 +++-- arch/arm/mach-s3c2440/mach-smdk2440.c | 41 +++--- drivers/video/s3c2410fb.c | 83 ++++++----- drivers/video/s3c2410fb.h | 2 + include/asm-arm/arch-s3c2410/fb.h | 33 ++--- 9 files changed, 396 insertions(+), 305 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index 43bb5e1..1946934 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -168,13 +168,32 @@ static void __init amlm5900_map_io(void) } #ifdef CONFIG_FB_S3C2410 -static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = { +static struct s3c2410fb_display __initdata amlm5900_lcd_info = { .width = 160, .height = 160, /* commented out until stn patch is submitted * .type = S3C2410_LCDCON1_STN4, */ + .xres = 160, + .yres = 160, + .bpp = 4, + + .regs = { + .lcdcon1 = 0x00008225, + .lcdcon2 = 0x0027c000, + .lcdcon3 = 0x00182708, + .lcdcon4 = 0x00000002, + .lcdcon5 = 0x00000001, + } +}; + +static struct s3c2410fb_mach_info __initdata amlm5900_fb_info = { + + .displays = &amlm5900_lcd_info, + .num_displays = 1, + .default_display = 0, + .gpccon = 0xaaaaaaaa, .gpccon_mask = 0xffffffff, .gpcup = 0x0000ffff, @@ -184,32 +203,6 @@ static struct s3c2410fb_mach_info __initdata amlm5900_lcd_info = { .gpdcon_mask = 0xffffffff, .gpdup = 0x0000ffff, .gpdup_mask = 0xffffffff, - - .xres = { - .min = 160, - .max = 160, - .defval = 160, - }, - - .yres = { - .min = 160, - .max = 160, - .defval = 160, - }, - - .bpp = { - .min = 4, - .max = 4, - .defval = 4, - }, - - .regs = { - .lcdcon1 = 0x00008225, - .lcdcon2 = 0x0027c000, - .lcdcon3 = 0x00182708, - .lcdcon4 = 0x00000002, - .lcdcon5 = 0x00000001, - } }; #endif @@ -239,7 +232,7 @@ static void __init amlm5900_init(void) { amlm5900_init_pm(); #ifdef CONFIG_FB_S3C2410 - s3c24xx_fb_set_platdata(&amlm5900_lcd_info); + s3c24xx_fb_set_platdata(&amlm5900_fb_info); #endif platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index bc92699..be50201 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -467,35 +467,160 @@ static struct platform_device bast_device_axpp = { /* LCD/VGA controller */ -static struct s3c2410fb_mach_info __initdata bast_lcd_info = { - .width = 640, - .height = 480, - - .xres = { - .min = 320, - .max = 1024, - .defval = 640, +static struct s3c2410fb_display __initdata bast_lcd_info[] = { + { + .width = 640, + .height = 480, + .xres = 320, + .yres = 240, + + .bpp = 4, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } }, - - .yres = { - .min = 240, - .max = 600, - .defval = 480, + { + .width = 640, + .height = 480, + + .xres = 640, + .yres = 480, + .bpp = 4, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } }, - - .bpp = { - .min = 4, - .max = 16, - .defval = 8, + { + .width = 640, + .height = 480, + + .xres = 800, + .yres = 600, + .bpp = 4, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, + { + .width = 640, + .height = 480, + + .xres = 320, + .yres = 240, + .bpp = 8, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, + { + .width = 640, + .height = 480, + + .xres = 640, + .yres = 480, + .bpp = 8, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, + { + .width = 640, + .height = 480, + + .xres = 800, + .yres = 600, + .bpp = 8, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, + { + .width = 640, + .height = 480, + + .xres = 320, + .yres = 240, + .bpp = 16, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, + { + .width = 640, + .height = 480, + + .xres = 640, + .yres = 480, + .bpp = 16, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } }, + { + .width = 640, + .height = 480, + + .xres = 800, + .yres = 600, + .bpp = 16, + + .regs = { + .lcdcon1 = 0x00000176, + .lcdcon2 = 0x1d77c7c2, + .lcdcon3 = 0x013a7f13, + .lcdcon4 = 0x00000057, + .lcdcon5 = 0x00014b02, + } + }, +}; - .regs = { - .lcdcon1 = 0x00000176, - .lcdcon2 = 0x1d77c7c2, - .lcdcon3 = 0x013a7f13, - .lcdcon4 = 0x00000057, - .lcdcon5 = 0x00014b02, - } +/* LCD/VGA controller */ + +static struct s3c2410fb_mach_info __initdata bast_fb_info = { + + .displays = bast_lcd_info, + .num_displays = ARRAY_SIZE(bast_lcd_info), + .default_display = 4, }; /* Standard BAST devices */ @@ -552,7 +677,7 @@ static void __init bast_map_io(void) static void __init bast_init(void) { - s3c24xx_fb_set_platdata(&bast_lcd_info); + s3c24xx_fb_set_platdata(&bast_fb_info); platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices)); } diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 9a172b4..ab04b29 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -133,8 +133,7 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = { /** * Set lcd on or off **/ -static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { - .fixed_syncs= 1, +static struct s3c2410fb_display h1940_lcd __initdata = { .regs={ .lcdcon1= S3C2410_LCDCON1_TFT16BPP | \ S3C2410_LCDCON1_TFT | \ @@ -156,6 +155,21 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { S3C2410_LCDCON5_INVVLINE | \ S3C2410_LCDCON5_HWSWP, }, + + .width = 240, + .height = 320, + .xres = 240, + .yres = 320, + .bpp = 16, +}; + +static struct s3c2410fb_mach_info h1940_fb_info __initdata = { + .fixed_syncs = 1, + + .displays = &h1940_lcd, + .num_displays = 1, + .default_display = 0, + .lpcsel= 0x02, .gpccon= 0xaa940659, .gpccon_mask= 0xffffffff, @@ -165,12 +179,6 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = { .gpdcon_mask= 0xffffffff, .gpdup= 0x0000faff, .gpdup_mask= 0xffffffff, - - .width= 240, - .height= 320, - .xres= {240,240,240}, - .yres= {320,320,320}, - .bpp= {16,16,16}, }; static struct platform_device s3c_device_leds = { @@ -217,7 +225,7 @@ static void __init h1940_init(void) { u32 tmp; - s3c24xx_fb_set_platdata(&h1940_lcdcfg); + s3c24xx_fb_set_platdata(&h1940_fb_info); s3c24xx_udc_set_platdata(&h1940_udc_cfg); /* Turn off suspend on both USB ports, and switch the diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c index e670b1e..03ea5d7 100644 --- a/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/arch/arm/mach-s3c2410/mach-qt2410.c @@ -95,157 +95,116 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { /* LCD driver info */ -/* Configuration for 640x480 SHARP LQ080V3DG01 */ -static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ - - .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */ - S3C2410_LCDCON2_LINEVAL(479) | - S3C2410_LCDCON2_VFPD(10) | /* 11 */ - S3C2410_LCDCON2_VSPW(14), /* 15 */ - - .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */ - S3C2410_LCDCON3_HOZVAL(639) | /* 640 */ - S3C2410_LCDCON3_HFPD(115), /* 116 */ - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(95), /* 96 */ - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, +static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = { + { + /* Configuration for 640x480 SHARP LQ080V3DG01 */ + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ + + .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */ + S3C2410_LCDCON2_LINEVAL(479) | + S3C2410_LCDCON2_VFPD(10) | /* 11 */ + S3C2410_LCDCON2_VSPW(14), /* 15 */ + + .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */ + S3C2410_LCDCON3_HOZVAL(639) | /* 640 */ + S3C2410_LCDCON3_HFPD(115), /* 116 */ + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(95), /* 96 */ + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + + .width = 640, + .height = 480, + + .xres = 640, + .yres = 480, + .bpp = 16, }, - - .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 640, - .height = 480, - - .xres = { - .min = 640, - .max = 640, - .defval = 640, - }, - - .yres = { - .min = 480, - .max = 480, - .defval = 480, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, -}; - -/* Configuration for 480x640 toppoly TD028TTEC1 */ -static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ - - .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */ - S3C2410_LCDCON2_LINEVAL(639) |/* 640 */ - S3C2410_LCDCON2_VFPD(3) | /* 4 */ - S3C2410_LCDCON2_VSPW(1), /* 2 */ - - .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */ - S3C2410_LCDCON3_HOZVAL(479) | /* 479 */ - S3C2410_LCDCON3_HFPD(23), /* 24 */ - - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(7), /* 8 */ - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - }, - - .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 480, - .height = 640, - - .xres = { - .min = 480, - .max = 480, - .defval = 480, + { + /* Configuration for 480x640 toppoly TD028TTEC1 */ + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */ + + .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */ + S3C2410_LCDCON2_LINEVAL(639) |/* 640 */ + S3C2410_LCDCON2_VFPD(3) | /* 4 */ + S3C2410_LCDCON2_VSPW(1), /* 2 */ + + .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */ + S3C2410_LCDCON3_HOZVAL(479) | /* 479 */ + S3C2410_LCDCON3_HFPD(23), /* 24 */ + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(7), /* 8 */ + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + + .width = 480, + .height = 640, + .xres = 480, + .yres = 640, + .bpp = 16, }, - - .yres = { - .min = 640, - .max = 640, - .defval = 640, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, + { + /* Config for 240x320 LCD */ + .regs = { + + .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | + S3C2410_LCDCON1_TFT | + S3C2410_LCDCON1_CLKVAL(0x04), + + .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | + S3C2410_LCDCON2_LINEVAL(319) | + S3C2410_LCDCON2_VFPD(6) | + S3C2410_LCDCON2_VSPW(3), + + .lcdcon3 = S3C2410_LCDCON3_HBPD(12) | + S3C2410_LCDCON3_HOZVAL(239) | + S3C2410_LCDCON3_HFPD(7), + + .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | + S3C2410_LCDCON4_HSPW(3), + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_PWREN | + S3C2410_LCDCON5_HWSWP, + }, + + .width = 240, + .height = 320, + .xres = 240, + .yres = 320, + .bpp = 16, }, }; -/* Config for 240x320 LCD */ -static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = { - .regs = { - - .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | - S3C2410_LCDCON1_TFT | - S3C2410_LCDCON1_CLKVAL(0x04), - - .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | - S3C2410_LCDCON2_LINEVAL(319) | - S3C2410_LCDCON2_VFPD(6) | - S3C2410_LCDCON2_VSPW(3), - - .lcdcon3 = S3C2410_LCDCON3_HBPD(12) | - S3C2410_LCDCON3_HOZVAL(239) | - S3C2410_LCDCON3_HFPD(7), - .lcdcon4 = S3C2410_LCDCON4_MVAL(0) | - S3C2410_LCDCON4_HSPW(3), - - .lcdcon5 = S3C2410_LCDCON5_FRM565 | - S3C2410_LCDCON5_INVVLINE | - S3C2410_LCDCON5_INVVFRAME | - S3C2410_LCDCON5_PWREN | - S3C2410_LCDCON5_HWSWP, - }, +static struct s3c2410fb_mach_info qt2410_fb_info __initdata = { + .displays = qt2410_lcd_cfg, + .num_displays = ARRAY_SIZE(qt2410_lcd_cfg), + .default_display = 0, .lpcsel = ((0xCE6) & ~7) | 1<<4, - - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .min = 320, - .max = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; /* CS8900 */ @@ -408,16 +367,17 @@ static void __init qt2410_machine_init(void) switch (tft_type) { case 'p': /* production */ - s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg); + qt2410_fb_info.default_display = 1; break; case 'b': /* big */ - s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg); + qt2410_fb_info.default_display = 0; break; case 's': /* small */ default: - s3c24xx_fb_set_platdata(&qt2410_lcd_cfg); + qt2410_fb_info.default_display = 2; break; } + s3c24xx_fb_set_platdata(&qt2410_fb_info); s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPB0, 1); diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index b59e6d3..c830788 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -110,7 +110,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { /* framebuffer lcd controller information */ -static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { +static struct s3c2410fb_display rx3715_lcdcfg __initdata = { .regs = { .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \ S3C2410_LCDCON1_TFT | \ @@ -133,6 +133,20 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { S3C2410_LCDCON5_HWSWP, }, + .width = 240, + .height = 320, + + .xres = 240, + .yres = 320, + .bpp = 16, +}; + +static struct s3c2410fb_mach_info rx3715_fb_info __initdata = { + + .displays = &rx3715_lcdcfg, + .num_displays = 1, + .default_display = 0, + .lpcsel = 0xf82, .gpccon = 0xaa955699, @@ -146,26 +160,6 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = { .gpdup_mask = 0xffffffff, .fixed_syncs = 1, - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .max = 320, - .min = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; static struct mtd_partition rx3715_nand_part[] = { @@ -224,7 +218,7 @@ static void __init rx3715_init_machine(void) #endif s3c2410_pm_init(); - s3c24xx_fb_set_platdata(&rx3715_lcdcfg); + s3c24xx_fb_set_platdata(&rx3715_fb_info); platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices)); } diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c index 670115b..f7dac7d 100644 --- a/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -103,7 +103,7 @@ static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = { /* LCD driver info */ -static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { +static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = { .regs = { .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | @@ -129,6 +129,21 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { S3C2410_LCDCON5_HWSWP, }, + .type = S3C2410_LCDCON1_TFT16BPP, + + .width = 240, + .height = 320, + + .xres = 240, + .yres = 320, + .bpp = 16, +}; + +static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = { + .displays = &smdk2440_lcd_cfg, + .num_displays = 1, + .default_display = 0, + #if 0 /* currently setup by downloader */ .gpccon = 0xaa940659, @@ -142,28 +157,6 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { #endif .lpcsel = ((0xCE6) & ~7) | 1<<4, - .type = S3C2410_LCDCON1_TFT16BPP, - - .width = 240, - .height = 320, - - .xres = { - .min = 240, - .max = 240, - .defval = 240, - }, - - .yres = { - .min = 320, - .max = 320, - .defval = 320, - }, - - .bpp = { - .min = 16, - .max = 16, - .defval = 16, - }, }; static struct platform_device *smdk2440_devices[] __initdata = { @@ -183,7 +176,7 @@ static void __init smdk2440_map_io(void) static void __init smdk2440_machine_init(void) { - s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); + s3c24xx_fb_set_platdata(&smdk2440_fb_info); platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index f7a026f..e52ec22 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -174,27 +174,28 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct s3c2410fb_info *fbi = info->par; + struct s3c2410fb_mach_info *mach_info = fbi->mach_info; + struct s3c2410fb_display *display = NULL; + unsigned i; dprintk("check_var(var=%p, info=%p)\n", var, info); /* validate x/y resolution */ - if (var->yres > fbi->mach_info->yres.max) - var->yres = fbi->mach_info->yres.max; - else if (var->yres < fbi->mach_info->yres.min) - var->yres = fbi->mach_info->yres.min; - - if (var->xres > fbi->mach_info->xres.max) - var->yres = fbi->mach_info->xres.max; - else if (var->xres < fbi->mach_info->xres.min) - var->xres = fbi->mach_info->xres.min; - - /* validate bpp */ + for (i = 0; i < mach_info->num_displays; i++) + if (var->yres == mach_info->displays[i].yres && + var->xres == mach_info->displays[i].xres && + var->bits_per_pixel == mach_info->displays[i].bpp) { + display = mach_info->displays + i; + fbi->current_display = i; + break; + } - if (var->bits_per_pixel > fbi->mach_info->bpp.max) - var->bits_per_pixel = fbi->mach_info->bpp.max; - else if (var->bits_per_pixel < fbi->mach_info->bpp.min) - var->bits_per_pixel = fbi->mach_info->bpp.min; + if (!display) { + dprintk("wrong resolution or depth %dx%d at %d bpp\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } var->transp.offset = 0; var->transp.length = 0; @@ -209,7 +210,7 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, var->blue = var->red; break; case 8: - if (fbi->mach_info->type != S3C2410_LCDCON1_TFT) { + if (display->type != S3C2410_LCDCON1_TFT) { /* 8 bpp 332 */ var->red.length = 3; var->red.offset = 5; @@ -236,7 +237,7 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, default: case 16: - if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565) { + if (display->regs.lcdcon5 & S3C2410_LCDCON5_FRM565) { /* 16 bpp, 565 format */ var->red.offset = 11; var->green.offset = 5; @@ -278,6 +279,9 @@ static void s3c2410fb_activate_var(struct fb_info *info, struct fb_var_screeninfo *var) { struct s3c2410fb_info *fbi = info->par; + struct s3c2410fb_mach_info *mach_info = fbi->mach_info; + struct s3c2410fb_display *display = mach_info->displays + + fbi->current_display; int hs; fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; @@ -287,9 +291,9 @@ static void s3c2410fb_activate_var(struct fb_info *info, dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres); dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel); - fbi->regs.lcdcon1 |= fbi->mach_info->type; + fbi->regs.lcdcon1 |= display->type; - if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) + if (display->type == S3C2410_LCDCON1_TFT) switch (var->bits_per_pixel) { case 1: fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; @@ -338,7 +342,7 @@ static void s3c2410fb_activate_var(struct fb_info *info, /* check to see if we need to update sync/borders */ - if (!fbi->mach_info->fixed_syncs) { + if (!mach_info->fixed_syncs) { dprintk("setting vert: up=%d, low=%d, sync=%d\n", var->upper_margin, var->lower_margin, var->vsync_len); @@ -363,7 +367,7 @@ static void s3c2410fb_activate_var(struct fb_info *info, fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff); fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1); - switch (fbi->mach_info->type) { + switch (display->type) { case S3C2410_LCDCON1_DSCAN4: case S3C2410_LCDCON1_STN8: hs = var->xres / 8; @@ -388,7 +392,7 @@ static void s3c2410fb_activate_var(struct fb_info *info, if (var->pixclock > 0) { int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); - if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) { + if (display->type == S3C2410_LCDCON1_TFT) { clkdiv = (clkdiv / 2) - 1; if (clkdiv < 0) clkdiv = 0; @@ -750,6 +754,7 @@ static char driver_name[] = "s3c2410fb"; static int __init s3c2410fb_probe(struct platform_device *pdev) { struct s3c2410fb_info *info; + struct s3c2410fb_display *display; struct fb_info *fbinfo; struct s3c2410fb_hw *mregs; struct resource *res; @@ -766,7 +771,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) return -EINVAL; } - mregs = &mach_info->regs; + display = mach_info->displays + mach_info->default_display; + mregs = &display->regs; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -809,7 +815,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) strcpy(fbinfo->fix.id, driver_name); - memcpy(&info->regs, &mach_info->regs, sizeof(info->regs)); + memcpy(&info->regs, &display->regs, sizeof(info->regs)); /* Stop the video and unset ENVID if set */ info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; @@ -817,6 +823,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); info->mach_info = pdev->dev.platform_data; + info->current_display = mach_info->default_display; fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; fbinfo->fix.type_aux = 0; @@ -827,8 +834,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) fbinfo->var.nonstd = 0; fbinfo->var.activate = FB_ACTIVATE_NOW; - fbinfo->var.height = mach_info->height; - fbinfo->var.width = mach_info->width; + fbinfo->var.height = display->height; + fbinfo->var.width = display->width; fbinfo->var.accel_flags = 0; fbinfo->var.vmode = FB_VMODE_NONINTERLACED; @@ -836,11 +843,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) fbinfo->flags = FBINFO_FLAG_DEFAULT; fbinfo->pseudo_palette = &info->pseudo_pal; - fbinfo->var.xres = mach_info->xres.defval; - fbinfo->var.xres_virtual = mach_info->xres.defval; - fbinfo->var.yres = mach_info->yres.defval; - fbinfo->var.yres_virtual = mach_info->yres.defval; - fbinfo->var.bits_per_pixel = mach_info->bpp.defval; + fbinfo->var.xres = display->xres; + fbinfo->var.xres_virtual = display->xres; + fbinfo->var.yres = display->yres; + fbinfo->var.yres_virtual = display->yres; + fbinfo->var.bits_per_pixel = display->bpp; fbinfo->var.upper_margin = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1; @@ -864,9 +871,17 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) fbinfo->var.green.length = 6; fbinfo->var.blue.length = 5; fbinfo->var.transp.length = 0; - fbinfo->fix.smem_len = mach_info->xres.max * - mach_info->yres.max * - mach_info->bpp.max / 8; + + /* find maximum required memory size for display */ + for (i = 0; i < mach_info->num_displays; i++) { + unsigned long smem_len = mach_info->displays[i].xres; + + smem_len *= mach_info->displays[i].yres; + smem_len *= mach_info->displays[i].bpp; + smem_len >>= 3; + if (fbinfo->fix.smem_len < smem_len) + fbinfo->fix.smem_len = smem_len; + } for (i = 0; i < 256; i++) info->palette_buffer[i] = PALETTE_BUFF_CLEAR; diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index eec7708..9e86fff 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -34,6 +34,8 @@ struct s3c2410fb_info { struct s3c2410fb_mach_info *mach_info; + unsigned current_display; + /* raw memory addresses */ dma_addr_t map_dma; /* physical */ u_char * map_cpu; /* virtual */ diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h index 93a58e7..c0e18b2 100644 --- a/include/asm-arm/arch-s3c2410/fb.h +++ b/include/asm-arm/arch-s3c2410/fb.h @@ -14,12 +14,6 @@ #include -struct s3c2410fb_val { - unsigned int defval; - unsigned int min; - unsigned int max; -}; - struct s3c2410fb_hw { unsigned long lcdcon1; unsigned long lcdcon2; @@ -28,23 +22,30 @@ struct s3c2410fb_hw { unsigned long lcdcon5; }; -struct s3c2410fb_mach_info { - unsigned char fixed_syncs; /* do not update sync/border */ - - /* LCD types */ - int type; +/* LCD description */ +struct s3c2410fb_display { + /* LCD type */ + unsigned type; /* Screen size */ - int width; - int height; + unsigned short width; + unsigned short height; /* Screen info */ - struct s3c2410fb_val xres; - struct s3c2410fb_val yres; - struct s3c2410fb_val bpp; + unsigned short xres; + unsigned short yres; + unsigned short bpp; /* lcd configuration registers */ struct s3c2410fb_hw regs; +}; + +struct s3c2410fb_mach_info { + unsigned char fixed_syncs; /* do not update sync/border */ + + struct s3c2410fb_display *displays; /* attached diplays info */ + unsigned num_displays; /* number of defined displays */ + unsigned default_display; /* GPIOs */ -- 2.7.4