You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
(1) |
Apr
(104) |
May
(81) |
Jun
(248) |
Jul
(133) |
Aug
(33) |
Sep
(53) |
Oct
(82) |
Nov
(166) |
Dec
(71) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(121) |
Feb
(42) |
Mar
(39) |
Apr
(84) |
May
(87) |
Jun
(58) |
Jul
(97) |
Aug
(130) |
Sep
(32) |
Oct
(139) |
Nov
(108) |
Dec
(216) |
2003 |
Jan
(299) |
Feb
(136) |
Mar
(392) |
Apr
(141) |
May
(137) |
Jun
(107) |
Jul
(94) |
Aug
(262) |
Sep
(300) |
Oct
(216) |
Nov
(72) |
Dec
(94) |
2004 |
Jan
(174) |
Feb
(192) |
Mar
(215) |
Apr
(314) |
May
(319) |
Jun
(293) |
Jul
(205) |
Aug
(161) |
Sep
(192) |
Oct
(226) |
Nov
(308) |
Dec
(89) |
2005 |
Jan
(127) |
Feb
(269) |
Mar
(588) |
Apr
(106) |
May
(77) |
Jun
(77) |
Jul
(161) |
Aug
(239) |
Sep
(86) |
Oct
(112) |
Nov
(153) |
Dec
(145) |
2006 |
Jan
(87) |
Feb
(57) |
Mar
(129) |
Apr
(109) |
May
(102) |
Jun
(232) |
Jul
(97) |
Aug
(69) |
Sep
(67) |
Oct
(69) |
Nov
(214) |
Dec
(82) |
2007 |
Jan
(133) |
Feb
(307) |
Mar
(121) |
Apr
(171) |
May
(229) |
Jun
(156) |
Jul
(185) |
Aug
(160) |
Sep
(122) |
Oct
(130) |
Nov
(78) |
Dec
(27) |
2008 |
Jan
(105) |
Feb
(137) |
Mar
(146) |
Apr
(148) |
May
(239) |
Jun
(208) |
Jul
(157) |
Aug
(244) |
Sep
(119) |
Oct
(125) |
Nov
(189) |
Dec
(225) |
2009 |
Jan
(157) |
Feb
(139) |
Mar
(106) |
Apr
(130) |
May
(246) |
Jun
(189) |
Jul
(128) |
Aug
(127) |
Sep
(88) |
Oct
(86) |
Nov
(216) |
Dec
(9) |
2010 |
Jan
(5) |
Feb
|
Mar
(11) |
Apr
(31) |
May
(3) |
Jun
|
Jul
(7) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Florian T. S. <Flo...@gm...> - 2009-08-17 11:56:08
|
viafb: cleanup duoview This patch cleans the duoview handling up by replacing the varible with the funtion in the only place where it is used. This is a code cleanup only, no runtime change expected. Signed-off-by: Florian Tobias Schandinat <Flo...@gm...> --- viafbdev.c | 18 ++---------------- viafbdev.h | 1 - 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 7eff26e..e48e493 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1009,7 +1009,8 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) return -ENODEV; /* When duoview and using lcd , use soft cursor */ - if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview) + if (viafb_LCD_ON || (!viafb_SAMM_ON && + viafb_LCD2_ON + viafb_DVI_ON + viafb_CRT_ON == 2)) return -ENODEV; viafb_show_hw_cursor(info, HW_Cursor_OFF); @@ -1376,18 +1377,6 @@ static int get_primary_device(void) return primary_device; } -static u8 is_duoview(void) -{ - if (0 == viafb_SAMM_ON) { - if (viafb_LCD_ON + viafb_LCD2_ON + - viafb_DVI_ON + viafb_CRT_ON == 2) - return true; - return false; - } else { - return false; - } -} - static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var) { @@ -1496,8 +1485,6 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info, need_set_mode = 1; } - viaparinfo->duoview = is_duoview(); - if (!need_set_mode) { ; } else { @@ -1618,7 +1605,6 @@ static void parse_active_dev(void) viafb_CRT_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; } - viaparinfo->duoview = is_duoview(); } static void parse_video_dev(void) diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index cd3dff7..9231877 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -52,7 +52,6 @@ struct viafb_par { u32 VQ_end; /* Virtual Queue End Address */ u32 iga_path; struct proc_dir_entry *proc_entry; /*viafb proc entry */ - u8 duoview; /*Is working in duoview mode? */ /* I2C stuff */ struct via_i2c_stuff i2c_stuff; -- 1.6.3.2 |
From: Florian T. S. <Flo...@gm...> - 2009-08-17 11:56:06
|
viafb: remove duplicated mode information This patch removes the mode information from viafbdev.c and uses the one of viamode.c instead. This is possible because horizontal and vertical address are the same as horizontal and vertical resolution. The reduced blanking modes in the table are no problem because they have a higher index than the normal modes and therefore always the normal modes are selected just as the old behaviour. Signed-off-by: Florian Tobias Schandinat <Flo...@gm...> --- viafbdev.c | 54 +++++------------------------------------------------- viafbdev.h | 6 +----- 2 files changed, 6 insertions(+), 54 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 72759b6..7eff26e 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -53,51 +53,6 @@ static void retrieve_device_setting(struct viafb_ioctl_setting static void viafb_set_video_device(u32 video_dev_info); static void viafb_get_video_device(u32 *video_dev_info); -/* Mode information */ -static const struct viafb_modeinfo viafb_modentry[] = { - {480, 640, VIA_RES_480X640}, - {640, 480, VIA_RES_640X480}, - {800, 480, VIA_RES_800X480}, - {800, 600, VIA_RES_800X600}, - {1024, 768, VIA_RES_1024X768}, - {1152, 864, VIA_RES_1152X864}, - {1280, 1024, VIA_RES_1280X1024}, - {1600, 1200, VIA_RES_1600X1200}, - {1440, 1050, VIA_RES_1440X1050}, - {1280, 768, VIA_RES_1280X768,}, - {1280, 800, VIA_RES_1280X800}, - {1280, 960, VIA_RES_1280X960}, - {1920, 1440, VIA_RES_1920X1440}, - {848, 480, VIA_RES_848X480}, - {1400, 1050, VIA_RES_1400X1050}, - {720, 480, VIA_RES_720X480}, - {720, 576, VIA_RES_720X576}, - {1024, 512, VIA_RES_1024X512}, - {1024, 576, VIA_RES_1024X576}, - {1024, 600, VIA_RES_1024X600}, - {1280, 720, VIA_RES_1280X720}, - {1920, 1080, VIA_RES_1920X1080}, - {1366, 768, VIA_RES_1368X768}, - {1680, 1050, VIA_RES_1680X1050}, - {960, 600, VIA_RES_960X600}, - {1000, 600, VIA_RES_1000X600}, - {1024, 576, VIA_RES_1024X576}, - {1024, 600, VIA_RES_1024X600}, - {1088, 612, VIA_RES_1088X612}, - {1152, 720, VIA_RES_1152X720}, - {1200, 720, VIA_RES_1200X720}, - {1280, 600, VIA_RES_1280X600}, - {1360, 768, VIA_RES_1360X768}, - {1440, 900, VIA_RES_1440X900}, - {1600, 900, VIA_RES_1600X900}, - {1600, 1024, VIA_RES_1600X1024}, - {1792, 1344, VIA_RES_1792X1344}, - {1856, 1392, VIA_RES_1856X1392}, - {1920, 1200, VIA_RES_1920X1200}, - {2048, 1536, VIA_RES_2048X1536}, - {0, 0, VIA_RES_INVALID} -}; - static struct fb_ops viafb_ops; @@ -1239,12 +1194,13 @@ int viafb_get_mode_index(int hres, int vres) u32 i; DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); - for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++) - if (viafb_modentry[i].xres == hres && - viafb_modentry[i].yres == vres) + for (i = 0; i < NUM_TOTAL_MODETABLE; i++) + if (CLE266Modes[i].mode_array && + CLE266Modes[i].crtc[0].crtc.hor_addr == hres && + CLE266Modes[i].crtc[0].crtc.ver_addr == vres) break; - return viafb_modentry[i].mode_index; + return CLE266Modes[i].ModeIndex; } static void check_available_device_to_enable(int device_id) diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index ea0df4f..cd3dff7 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -70,11 +70,7 @@ struct viafb_par { int video_on_lcd; }; -struct viafb_modeinfo { - u32 xres; - u32 yres; - int mode_index; -}; + extern unsigned int viafb_second_virtual_yres; extern unsigned int viafb_second_virtual_xres; extern unsigned int viafb_second_offset; -- 1.6.3.2 |
From: Florian T. S. <Flo...@gm...> - 2009-08-17 11:56:03
|
viafb: cleanup viamode.h This patch removes unneeeded declarations from the header and makes it more maintainable by evaluating the array size in the file the array exist in and exporting it via variables. This removes the need to keep the array size in the header in sync with the real array size. Signed-off-by: Florian Tobias Schandinat <Flo...@gm...> --- viamode.c | 10 ++++ viamode.h | 138 ++++++++++--------------------------------------------------- 2 files changed, 32 insertions(+), 116 deletions(-) diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 1a850c3..464903c 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -1011,3 +1011,13 @@ struct VideoModeTable CEA_HDMI_Modes[] = { {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} }; + +int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); +int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes); +int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs); +int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs); +int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs); +int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs); +int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); +int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); +int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 2ec8bfe..504e16a 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -50,127 +50,33 @@ struct res_map_refresh { int vmode_refresh; }; -#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl) -#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes) -#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs) -#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs) -#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs) -#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs) -#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs) -#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table) -#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes) +extern int NUM_TOTAL_RES_MAP_REFRESH; +extern int NUM_TOTAL_CEA_MODES; +extern int NUM_TOTAL_CN400_ModeXregs; +extern int NUM_TOTAL_CN700_ModeXregs; +extern int NUM_TOTAL_KM400_ModeXregs; +extern int NUM_TOTAL_CX700_ModeXregs; +extern int NUM_TOTAL_CLE266_ModeXregs; +extern int NUM_TOTAL_PATCH_MODE; +extern int NUM_TOTAL_MODETABLE; /********************/ /* Mode Table */ /********************/ -/* 480x640 */ -extern struct crt_mode_table CRTM480x640[1]; -/* 640x480*/ -extern struct crt_mode_table CRTM640x480[5]; -/*720x480 (GTF)*/ -extern struct crt_mode_table CRTM720x480[1]; -/*720x576 (GTF)*/ -extern struct crt_mode_table CRTM720x576[1]; -/* 800x480 (CVT) */ -extern struct crt_mode_table CRTM800x480[1]; -/* 800x600*/ -extern struct crt_mode_table CRTM800x600[5]; -/* 848x480 (CVT) */ -extern struct crt_mode_table CRTM848x480[1]; -/*856x480 (GTF) convert to 852x480*/ -extern struct crt_mode_table CRTM852x480[1]; -/*1024x512 (GTF)*/ -extern struct crt_mode_table CRTM1024x512[1]; -/* 1024x600*/ -extern struct crt_mode_table CRTM1024x600[1]; -/* 1024x768*/ -extern struct crt_mode_table CRTM1024x768[4]; -/* 1152x864*/ -extern struct crt_mode_table CRTM1152x864[1]; -/* 1280x720 (HDMI 720P)*/ -extern struct crt_mode_table CRTM1280x720[2]; -/*1280x768 (GTF)*/ -extern struct crt_mode_table CRTM1280x768[2]; -/* 1280x800 (CVT) */ -extern struct crt_mode_table CRTM1280x800[1]; -/*1280x960*/ -extern struct crt_mode_table CRTM1280x960[1]; -/* 1280x1024*/ -extern struct crt_mode_table CRTM1280x1024[3]; -/* 1368x768 (GTF) */ -extern struct crt_mode_table CRTM1368x768[1]; -/*1440x1050 (GTF)*/ -extern struct crt_mode_table CRTM1440x1050[1]; -/* 1600x1200*/ -extern struct crt_mode_table CRTM1600x1200[2]; -/* 1680x1050 (CVT) */ -extern struct crt_mode_table CRTM1680x1050[2]; -/* 1680x1050 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1680x1050_RB[1]; -/* 1920x1080 (CVT)*/ -extern struct crt_mode_table CRTM1920x1080[1]; -/* 1920x1080 (CVT with Reduce Blanking) */ -extern struct crt_mode_table CRTM1920x1080_RB[1]; -/* 1920x1440*/ -extern struct crt_mode_table CRTM1920x1440[2]; -/* 1400x1050 (CVT) */ -extern struct crt_mode_table CRTM1400x1050[2]; -/* 1400x1050 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1400x1050_RB[1]; -/* 960x600 (CVT) */ -extern struct crt_mode_table CRTM960x600[1]; -/* 1000x600 (GTF) */ -extern struct crt_mode_table CRTM1000x600[1]; -/* 1024x576 (GTF) */ -extern struct crt_mode_table CRTM1024x576[1]; -/* 1088x612 (CVT) */ -extern struct crt_mode_table CRTM1088x612[1]; -/* 1152x720 (CVT) */ -extern struct crt_mode_table CRTM1152x720[1]; -/* 1200x720 (GTF) */ -extern struct crt_mode_table CRTM1200x720[1]; -/* 1280x600 (GTF) */ -extern struct crt_mode_table CRTM1280x600[1]; -/* 1360x768 (CVT) */ -extern struct crt_mode_table CRTM1360x768[1]; -/* 1360x768 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1360x768_RB[1]; -/* 1366x768 (GTF) */ -extern struct crt_mode_table CRTM1366x768[2]; -/* 1440x900 (CVT) */ -extern struct crt_mode_table CRTM1440x900[2]; -/* 1440x900 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1440x900_RB[1]; -/* 1600x900 (CVT) */ -extern struct crt_mode_table CRTM1600x900[1]; -/* 1600x900 (CVT Reduce Blanking) */ -extern struct crt_mode_table CRTM1600x900_RB[1]; -/* 1600x1024 (GTF) */ -extern struct crt_mode_table CRTM1600x1024[1]; -/* 1792x1344 (DMT) */ -extern struct crt_mode_table CRTM1792x1344[1]; -/* 1856x1392 (DMT) */ -extern struct crt_mode_table CRTM1856x1392[1]; -/* 1920x1200 (CVT) */ -extern struct crt_mode_table CRTM1920x1200[1]; -/* 1920x1200 (CVT with Reduce Blanking) */ -extern struct crt_mode_table CRTM1920x1200_RB[1]; -/* 2048x1536 (CVT) */ -extern struct crt_mode_table CRTM2048x1536[1]; -extern struct VideoModeTable CLE266Modes[47]; -extern struct crt_mode_table CEAM1280x720[1]; -extern struct crt_mode_table CEAM1920x1080[1]; -extern struct VideoModeTable CEA_HDMI_Modes[2]; +extern struct VideoModeTable CLE266Modes[]; +extern struct crt_mode_table CEAM1280x720[]; +extern struct crt_mode_table CEAM1920x1080[]; +extern struct VideoModeTable CEA_HDMI_Modes[]; -extern struct res_map_refresh res_map_refresh_tbl[61]; -extern struct io_reg CN400_ModeXregs[52]; -extern struct io_reg CN700_ModeXregs[66]; -extern struct io_reg KM400_ModeXregs[55]; -extern struct io_reg CX700_ModeXregs[58]; -extern struct io_reg VX800_ModeXregs[58]; -extern struct io_reg CLE266_ModeXregs[32]; -extern struct io_reg PM1024x768[2]; -extern struct patch_table res_patch_table[1]; +extern struct res_map_refresh res_map_refresh_tbl[]; +extern struct io_reg CN400_ModeXregs[]; +extern struct io_reg CN700_ModeXregs[]; +extern struct io_reg KM400_ModeXregs[]; +extern struct io_reg CX700_ModeXregs[]; +extern struct io_reg VX800_ModeXregs[]; +extern struct io_reg CLE266_ModeXregs[]; +extern struct io_reg PM1024x768[]; +extern struct patch_table res_patch_table[]; extern struct VPITTable VPIT; #endif /* __VIAMODE_H__ */ -- 1.6.3.2 |
From: Tomi V. <tom...@no...> - 2009-08-17 11:25:27
|
Hi, As I'm new to sending patches upstream, I'm not sure how to go forward with DSS2 now. Should I send it to linux-arm-kernel mailing list, or directly to main linux kernel mailing list? Or is there a route through fbdev-devel list for DSS2 to go forward? Tomi |
From: Florian T. S. <Flo...@gm...> - 2009-08-14 19:46:33
|
viafb: fix ioremap_nocache error handling Correct the returned error code for remapping the video framebuffer. Introduce error handling for remapping MMIO register address space to avoid a NULL pointer dereference. Disable hardware acceleration if remapping MMIO register address space failed as those registers are only used for hardware acceleration. Signed-off-by: Florian Tobias Schandinat <Flo...@gm...> --- viafbdev.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 743eed4..72759b6 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2134,12 +2134,16 @@ static int __devinit via_pci_probe(void) if (!viaparinfo->fbmem_virt) { printk(KERN_INFO "ioremap failed\n"); - return -1; + return -ENOMEM; } viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base, viaparinfo->mmio_len); + if (!viaparinfo->io_virt) { + printk(KERN_WARNING "ioremap failed: hardware acceleration disabled\n"); + viafb_accel = 0; + } viafbinfo->node = 0; viafbinfo->fbops = &viafb_ops; -- 1.6.3.2 |
From: Roman S. <sun...@gm...> - 2009-08-14 16:34:01
|
Hi! On 14.08.2009, at 16:44, Florian Tobias Schandinat wrote: > Hi, > > thanks a lot for your testing! > > Roman Sergeev schrieb: >> test # 1 >> * send to kernel "vmalloc=260M" >> # modprobe viafb > > For my patch to fix this bug I would be interested in something like > this: > * send to kernel "vmalloc=260M" > # modprobe viafb viafb_accel=0 > If it is similar to the result of test #2 I could simply disable > hardware acceleration if the second ioremap fails which is IMHO > better than refusing to work as hardware acceleration is a nice to > have but not crucial for device operation. > yes, it's working log: Jun 22 06:15:50 mini2133 [ 59.646904] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 22 06:15:50 mini2133 [ 59.727808] vmap allocation for size 16781312 failed: use vmalloc=<size> to increase size. Jun 22 06:15:50 mini2133 [ 59.732024] Console: switching to colour frame buffer device 80x30 # grep viafb /proc/modules viafb 71840 1 - Live 0xef642000 i2c_algo_bit 4656 1 viafb, Live 0xef624000 >> test # 2 >> * send to kernel "vmalloc=300M" >> * modprobe viafb >> * loaded ok >> status: >> # grep viafb /proc/modules >> viafb 71840 1 - Live 0xece42000 >> i2c_algo_bit 4656 1 viafb, Live 0xece24000 >> log: >> Jun 21 23:52:12 mini2133 [ 47.308459] VIA Graphics Intergration >> Chipset framebuffer 2.4 initializing >> Jun 21 23:52:12 mini2133 [ 47.393518] Console: switching to >> colour frame buffer device 80x30 >> but i see "test color mode" >> ... >> if i loading module with parametrs "modprobe viafb >> viafb_mode=800x600 viafb_refresh=60" >> they still go "test color mode" >> log: >> Jun 22 00:28:11 mini2133 [ 142.994541] VIA Graphics Intergration >> Chipset framebuffer 2.4 initializing >> Jun 22 00:28:11 mini2133 [ 143.079079] Console: switching to >> colour frame buffer device 100x37 > > This looks fine. I'd guess the driver itself is working. > Unfortunately I do not fully understand the term "test color mode". > Can you describe what you see? monocolor, if yes what color or some > strange patterns? even whether it is shown immediately or is somehow > slowly painted might help. > > Perhaps using the module parameter viafb_active_dev= with one of > CRT, DVI or LCD helps? > If it doesn't....well I'm aware of one bug in that code that I hit > on my netbook. Will send you a fix if your observations sound related. # modprobe viafb viafb_accel=0 viafb_active_dev=LCD viafb_mode=1024x768 works.... log: Jun 22 06:30:01 mini2133 [ 40.666874] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 22 06:30:01 mini2133 [ 40.748196] vmap allocation for size 16781312 failed: use vmalloc=<size> to increase size. Jun 22 06:30:01 mini2133 [ 40.752198] Console: switching to colour frame buffer device 128x48 # fbset -i mode "1024x768-60" # D: 64.998 MHz, H: 48.362 kHz, V: 60.002 Hz geometry 1024 768 1024 768 32 timings 15385 160 24 29 3 136 6 rgba 8/16,8/8,8/0,0/0 endmode Frame buffer device information: Name : Via Address : 0xc0000000 Size : 268435456 Type : PACKED PIXELS Visual : TRUECOLOR XPanStep : 0 YPanStep : 1 YWrapStep : 0 LineLength : 4096 MMIO Address: 0xfc000000 MMIO Size : 16777216 Accelerator : Unknown (50) "test color mode" - it's like lcd test : red-green-blue-grey- gradient-...etc |
From: Thierry R. <thi...@av...> - 2009-08-14 14:13:09
|
This patch adds support for the Avionic Design Xanthos framebuffer. Signed-off-by: Thierry Reding <thi...@av...> Acked-by: Krzysztof Helt <krz...@wp...> --- drivers/video/Kconfig | 12 ++ drivers/video/Makefile | 1 + drivers/video/adxfb/Makefile | 1 + drivers/video/adxfb/adxfb.h | 131 +++++++++++++ drivers/video/adxfb/fb.c | 405 +++++++++++++++++++++++++++++++++++++++++ drivers/video/adxfb/overlay.c | 190 +++++++++++++++++++ drivers/video/adxfb/scaler.c | 231 +++++++++++++++++++++++ include/video/Kbuild | 1 + include/video/adxfb.h | 79 ++++++++ 9 files changed, 1051 insertions(+), 0 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3b54b39..7f1a94d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1668,6 +1668,18 @@ config CARMINE_DRAM_CUSTOM Use custom board timings. endchoice +config FB_ADX + tristate "Avionic Design Xanthos framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Framebuffer driver for the LCD controller in Avionic Design + Xanthos boards. + + If in doubt, say N. + config FB_AU1100 bool "Au1100 LCD Driver" depends on (FB = y) && MIPS && SOC_AU1100 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 01a819f..c648e23 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -126,6 +126,7 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ +obj-$(CONFIG_FB_ADX) += adxfb/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/adxfb/Makefile b/drivers/video/adxfb/Makefile new file mode 100644 index 0000000..389d65c --- /dev/null +++ b/drivers/video/adxfb/Makefile @@ -0,0 +1 @@ +obj-y += fb.o overlay.o scaler.o diff --git a/drivers/video/adxfb/adxfb.h b/drivers/video/adxfb/adxfb.h new file mode 100644 index 0000000..3be8727 --- /dev/null +++ b/drivers/video/adxfb/adxfb.h @@ -0,0 +1,131 @@ +/* + * linux/drivers/video/adxfb/adxfb.h + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#ifndef _DRIVERS_VIDEO_ADXFB_ADXFB_H +#define _DRIVERS_VIDEO_ADXFB_ADXFB_H 1 + +#include <linux/spinlock.h> +#include <video/adxfb.h> + +struct adxfb_mode_info { + /* mode resolution */ + u_short xres; + u_short yres; + u_short bpp; + + /* color packing specification */ + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield alpha; +}; + +/** + * struct adxfb_info - Avionic Design Xanthos framebuffer info structure + * @palette: VGA palette storage + * @io_base: memory-mapped base address for graphics controller + * @scaler_base: memory-mapped base address for scaler + * @ioctl: machine-specific I/O control handler + */ +struct adxfb_info { + u32 palette[16]; + + void __iomem *io_base; + void __iomem *scaler_base; + spinlock_t lock; + + int (*ioctl)(struct fb_info *info, unsigned int command, + unsigned long arg); +}; + +/* register definitions */ +#define ADXFB_CONTROL 0x000 +#define ADXFB_CONTROL_ENABLE (1 << 0) +#define ADXFB_CONTROL_SYNC (1 << 1) +#define ADXFB_CONTROL_DOUBLE_Y (1 << 2) +#define ADXFB_CONTROL_HALVE_X (1 << 3) +#define ADXFB_CONTROL_TRIPLE_Y (1 << 4) +#define ADXFB_CONTROL_LOCK (1 << 31) +#define ADXFB_OVERLAY_CONTROL 0x008 +#define ADXFB_OVERLAY_CONTROL_OVERLAY (1 << 0) +#define ADXFB_OVERLAY_CONTROL_ALPHA (1 << 1) +#define ADXFB_OVERLAY_START 0x010 +#define ADXFB_OVERLAY_END 0x018 +#define ADXFB_OVERLAY_PAGE0_START 0x020 +#define ADXFB_OVERLAY_PAGE0_END 0x028 +#define ADXFB_OVERLAY_PAGE0_SIZE 0x030 +#define ADXFB_OVERLAY_PAGE1_START 0x038 +#define ADXFB_OVERLAY_PAGE1_END 0x040 +#define ADXFB_OVERLAY_PAGE1_SIZE 0x048 +#define ADXFB_OVERLAY_LEVEL 0x050 +#define ADXFB_ALPHA_START 0x058 +#define ADXFB_ALPHA_END 0x060 +#define ADXFB_ALPHA_PAGE1_START 0x068 +#define ADXFB_ALPHA_PAGE1_END 0x070 +#define ADXFB_ALPHA_PAGE1_SIZE 0x078 +#define ADXFB_PAGE0_BASE 0x080 +#define ADXFB_PAGE0_FORMAT 0x088 +#define ADXFB_PAGE0_RESOLUTION 0x090 +#define ADXFB_PAGE0_RESOLUTION_BYTE 0x098 +#define ADXFB_PAGE0_SIZE 0x0a0 +#define ADXFB_PAGE1_BASE 0x0b0 +#define ADXFB_PAGE1_FORMAT 0x0b8 +#define ADXFB_PAGE1_RESOLUTION 0x0c0 +#define ADXFB_PAGE1_RESOLUTION_PHYSICAL 0x0c8 +#define ADXFB_PAGE1_RESOLUTION_VIRTUAL 0x0d0 +#define ADXFB_PAGE1_SIZE_PHYSICAL 0x0d8 +#define ADXFB_PAGE1_SIZE_VIRTUAL 0x0e0 +#define ADXFB_PAGE1_OFFSET 0x0e8 +#define ADXFB_PAGE1_SECONDARY_BASE 0x0f0 +#define ADXFB_COLOR_OFFSET 0x100 +#define ADXFB_COLOR_MUL 0x108 + +/* page format (ADXFB_PAGE0_FORMAT, ADXFB_PAGE1_FORMAT) */ +#define ADXFB_FMT_NONE 0 +#define ADXFB_FMT_GRAYSCALE_8 1 +#define ADXFB_FMT_RGB_565 2 +#define ADXFB_FMT_RGB_888 3 +#define ADXFB_FMT_RGBA_8888 4 + +/** + * adxfb_r32() - read 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + */ +static inline u32 adxfb_r32(struct adxfb_info *fb, unsigned long offset) +{ + return readl(fb->io_base + offset); +} + +/** + * adxfb_w32() - write 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + * @value: value to write to register + */ +static inline void adxfb_w32(struct adxfb_info *fb, unsigned long offset, + u32 value) +{ + writel(value, fb->io_base + offset); +} + +extern int adxfb_scaler_set_mode(struct fb_info *info, + struct adxfb_scaler_mode *mode); +extern int adxfb_scaler_get_mode(struct fb_info *info, + struct adxfb_scaler_mode *mode); + +extern int adxfb_overlay_enable(struct fb_info *info, unsigned long flags); +extern int adxfb_overlay_set_viewport(struct fb_info *info, + struct adxfb_viewport *viewport); + +#endif /* !_DRIVERS_VIDEO_ADXFB_ADXFB_H */ diff --git a/drivers/video/adxfb/fb.c b/drivers/video/adxfb/fb.c new file mode 100644 index 0000000..935042b --- /dev/null +++ b/drivers/video/adxfb/fb.c @@ -0,0 +1,405 @@ +/* + * linux/drivers/video/adxfb/fb.c + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include <linux/io.h> +#include <linux/mm.h> +#include <linux/platform_device.h> +#include <linux/uaccess.h> + +#include "adxfb.h" + +/** + * adxfb_setcolreg() - set color register + * @regno: register number to set + * @red: red color component + * @green: green color component + * @blue: blue color component + * @transp: transparency component + * @info: framebuffer context + */ +static int adxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info) +{ + if ((regno >= info->cmap.len) || (regno > 255)) + return 1; + +#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + ((struct adxfb_info *)info->par)->palette[regno] = + (CNVT_TOHW(red, info->var.red.length) + << info->var.red.offset) | + (CNVT_TOHW(green, info->var.green.length) + << info->var.green.offset) | + (CNVT_TOHW(blue, info->var.blue.length) + << info->var.blue.offset) | + (CNVT_TOHW(transp, info->var.transp.length) + << info->var.transp.offset); + } + break; + + default: + dev_err(info->dev, "bad depth: %u\n", info->var.bits_per_pixel); + break; + } +#undef CNVT_TOHW + + return 0; +} + +/** + * adxfb_ioctl() - handle I/O controls + * @info: framebuffer context + * @command: I/O control code + * @arg: I/O control argument + */ +static int adxfb_ioctl(struct fb_info *info, unsigned int command, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + struct adxfb_scaler_mode mode; + struct adxfb_viewport viewport; + int err = 0; + + switch (command) { + case ADXFB_IOCTL_SCALER_SET_MODE: + if (copy_from_user(&mode, argp, sizeof(mode))) + return -EFAULT; + + err = adxfb_scaler_set_mode(info, &mode); + if (err < 0) + return err; + + break; + + case ADXFB_IOCTL_SCALER_GET_MODE: + err = adxfb_scaler_get_mode(info, &mode); + if (err < 0) + return err; + + if (copy_to_user(argp, &mode, sizeof(mode))) + return -EFAULT; + + break; + + case ADXFB_IOCTL_OVERLAY_ENABLE: + err = adxfb_overlay_enable(info, arg); + if (err < 0) + return err; + + break; + + case ADXFB_IOCTL_OVERLAY_SET_VIEWPORT: + if (copy_from_user(&viewport, argp, sizeof(viewport))) + return -EFAULT; + + err = adxfb_overlay_set_viewport(info, &viewport); + if (err < 0) + return err; + + break; + + default: + return -ENOTTY; + } + + return 0; +} + +/* framebuffer operations */ +static struct fb_ops adxfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = adxfb_setcolreg, + .fb_ioctl = adxfb_ioctl, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/** + * adxfb_set_bitfield() - initialize a bitfield structure + * @bf: bitfield structure to fill + * @offset: value for offset field + * @length: value for length field + * @msb_right: value for msb_right field + */ +static void adxfb_set_bitfield(struct fb_bitfield *bf, u32 offset, u32 length, + u32 msb_right) +{ + bf->offset = offset; + bf->length = length; + bf->msb_right = msb_right; +} + +/** + * adxfb_fmt_to_mode() - convert format type to video mode parameters + * @fmt: ADXFB format type + * @mode: video mode + */ +static int adxfb_fmt_to_mode(u8 fmt, struct adxfb_mode_info *mode) +{ + switch (fmt) { + case ADXFB_FMT_GRAYSCALE_8: + /* FIXME: use correct values here */ + adxfb_set_bitfield(&mode->red, 5, 3, 0); + adxfb_set_bitfield(&mode->green, 3, 2, 0); + adxfb_set_bitfield(&mode->blue, 0, 3, 0); + mode->bpp = 8; + break; + + case ADXFB_FMT_RGB_565: + adxfb_set_bitfield(&mode->red, 11, 5, 0); + adxfb_set_bitfield(&mode->green, 5, 6, 0); + adxfb_set_bitfield(&mode->blue, 0, 5, 0); + mode->bpp = 16; + break; + + case ADXFB_FMT_RGB_888: + /* FIXME: verify that these are correct values */ + adxfb_set_bitfield(&mode->red, 16, 8, 0); + adxfb_set_bitfield(&mode->green, 8, 8, 0); + adxfb_set_bitfield(&mode->blue, 0, 8, 0); + mode->bpp = 24; + break; + + case ADXFB_FMT_RGBA_8888: + /* FIXME: verify that these are correct values */ + adxfb_set_bitfield(&mode->alpha, 24, 8, 0); + adxfb_set_bitfield(&mode->red, 16, 8, 0); + adxfb_set_bitfield(&mode->green, 8, 8, 0); + adxfb_set_bitfield(&mode->blue, 0, 8, 0); + mode->bpp = 32; + break; + + default: + return -EINVAL; + } + + return 0; +} + +/** + * adxfb_get_mach_mode() - obtain the current video mode + * @fb: framebuffer context + * @mode: structure to return the video mode in + */ +static int adxfb_get_mach_mode(struct adxfb_info *fb, + struct adxfb_mode_info *mode) +{ + u32 size; + u16 resx; + u16 resy; + u8 fmt; + + size = adxfb_r32(fb, ADXFB_PAGE0_RESOLUTION); + resx = (size >> 16) & 0x7ff; + resy = (size >> 0) & 0x7ff; + + fmt = adxfb_r32(fb, ADXFB_PAGE0_FORMAT) & 0xff; + + mode->xres = resx; + mode->yres = resy; + + return adxfb_fmt_to_mode(fmt, mode); +} + +/** + * adxfb_probe() - initialize the framebuffer device + * @pdev: platform device + */ +static int __init adxfb_probe(struct platform_device *pdev) +{ + struct adxfb_mode_info mode; + struct adxfb_info *fb; + struct fb_info *info; + struct resource *res; + int err = 0; + + info = framebuffer_alloc(sizeof(struct adxfb_info), &pdev->dev); + if (!info) { + dev_err(&pdev->dev, "failed to allocate framebuffer device\n"); + return -ENOMEM; + } + + fb = info->par; + spin_lock_init(&fb->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get graphics controller I/O " + "memory resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request graphics controller " + "I/O memory region\n"); + err = -ENXIO; + goto free; + } + + fb->io_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!fb->io_base) { + err = -ENXIO; + goto free; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "failed to get scaler I/O memory " + "resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request scaler I/O memory " + "region\n"); + err = -ENXIO; + goto free; + } + + fb->scaler_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!fb->scaler_base) { + err = -ENXIO; + goto free; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!res) { + dev_err(&pdev->dev, "failed to get framebuffer I/O memory " + "resource\n"); + err = -ENXIO; + goto free; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "failed to request framebuffer I/O " + "memory region\n"); + err = -ENXIO; + goto free; + } + + info->screen_base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!info->screen_base) { + err = -ENXIO; + goto free; + } + + /* TODO: add some checking for these parameters */ + memset(&mode, 0, sizeof(mode)); + adxfb_get_mach_mode(fb, &mode); + + snprintf(info->fix.id, sizeof(info->fix.id), "adxfb"); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.accel = FB_ACCEL_NONE; + info->fix.line_length = mode.xres * (mode.bpp / 8); + info->fix.smem_start = res->start; + info->fix.smem_len = res->end - res->start + 1; + + info->var.activate = FB_ACTIVATE_NOW; + info->var.vmode = FB_VMODE_NONINTERLACED; + info->var.xres = mode.xres; + info->var.yres = mode.yres; + info->var.xres_virtual = mode.xres; + info->var.yres_virtual = mode.yres; + info->var.bits_per_pixel = mode.bpp; + info->var.red = mode.red; + info->var.green = mode.green; + info->var.blue = mode.blue; + info->var.transp = mode.alpha; + info->var.width = mode.xres; + info->var.height = mode.yres; + + info->fbops = &adxfb_ops; + info->flags = FBINFO_DEFAULT; + info->pseudo_palette = fb->palette; + + err = fb_alloc_cmap(&info->cmap, 256, 0); + if (err < 0) { + err = -ENOMEM; + goto free; + } + + err = register_framebuffer(info); + if (err < 0) { + dev_err(&pdev->dev, "failed to register framebuffer\n"); + goto cmap; + } + + dev_info(info->dev, "ADX framebuffer initialized\n"); + platform_set_drvdata(pdev, info); + return 0; + +cmap: + fb_dealloc_cmap(&info->cmap); +free: + framebuffer_release(info); + return err; +} + +/** + * adxfb_remove() - shutdown the framebuffer device + * @pdev: platform device + */ +static int adxfb_remove(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + unregister_framebuffer(info); + return 0; +} + +/* ADXFB platform driver */ +static struct platform_driver adxfb_driver = { + .probe = adxfb_probe, + .remove = adxfb_remove, + .driver = { + .name = "adxfb", + }, +}; + +/** + * adxfb_init() - module initialization + */ +int __init adxfb_init(void) +{ + return platform_driver_register(&adxfb_driver); +} + +/** + * adxfb_exit() - module cleanup + */ +void __exit adxfb_exit(void) +{ + platform_driver_unregister(&adxfb_driver); +} + +module_init(adxfb_init); +module_exit(adxfb_exit); + +MODULE_AUTHOR("Thierry Reding <thi...@av...>"); +MODULE_DESCRIPTION("Avionic Design Xanthos framebuffer driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/adxfb/overlay.c b/drivers/video/adxfb/overlay.c new file mode 100644 index 0000000..f114a54 --- /dev/null +++ b/drivers/video/adxfb/overlay.c @@ -0,0 +1,190 @@ +/* + * linux/drivers/video/adxfb/overlay.c + * + * Copyright (C) 2008 Avionic Design Development GmbH + * Copyright (C) 2008 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include "adxfb.h" + +/* format to bit-depth table */ +struct fmt_bpp { + u8 fmt; + int bpp; +}; + +static struct fmt_bpp formats[] = { + { ADXFB_FMT_GRAYSCALE_8, 8 }, + { ADXFB_FMT_RGB_565, 16 }, + { ADXFB_FMT_RGB_888, 24 }, + { ADXFB_FMT_RGBA_8888, 32 }, +}; + +/** + * fmt_to_bpp() - obtain the bit-depth for a given page format + * @fmt: format of which to retrieve the bit-depth + */ +static int fmt_to_bpp(u8 fmt) +{ + int bpp = 0, i; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (fmt == formats[i].fmt) { + bpp = formats[i].bpp; + break; + } + } + + return bpp; +} + +/** + * adxfb_disable() - disable the graphics controller + * @fb: framebuffer context + */ +static inline void adxfb_disable(struct adxfb_info *fb) +{ + u32 ctrl; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_CONTROL); + ctrl &= ~ADXFB_CONTROL_ENABLE; + ctrl |= ADXFB_CONTROL_LOCK; + adxfb_w32(fb, ADXFB_CONTROL, ctrl); + + spin_unlock(&fb->lock); +} + +/** + * adxfb_enable() - enable the graphics controller + * @fb: framebuffer context + */ +static inline void adxfb_enable(struct adxfb_info *fb) +{ + u32 ctrl; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_CONTROL); + ctrl &= ~ADXFB_CONTROL_LOCK; + ctrl |= ADXFB_CONTROL_ENABLE; + adxfb_w32(fb, ADXFB_CONTROL, ctrl); + + spin_unlock(&fb->lock); +} + +/** + * adxfb_overlay_enable() - enable the overlay window + * @info: framebuffer context + * @flags: flags for enabling/disabling + */ +int adxfb_overlay_enable(struct fb_info *info, unsigned long flags) +{ + struct adxfb_info *fb = info->par; + u32 ctrl; + + if (!info) + return -EINVAL; + + spin_lock(&fb->lock); + + ctrl = adxfb_r32(fb, ADXFB_OVERLAY_CONTROL); + + if (flags & ADXFB_OVERLAY_ENABLE) + ctrl |= ADXFB_OVERLAY_CONTROL_OVERLAY; + else + ctrl &= ~ADXFB_OVERLAY_CONTROL_OVERLAY; + + adxfb_w32(fb, ADXFB_OVERLAY_CONTROL, ctrl); + + spin_unlock(&fb->lock); + return 0; +} + +/** + * adxfb_overlay_set_viewport() - set the region for the overlay window + * @info: framebuffer context + * @viewport: new screen region for the overlay window + */ +int adxfb_overlay_set_viewport(struct fb_info *info, + struct adxfb_viewport *viewport) +{ + struct adxfb_info *fb = info->par; + int sx, sy, dx, dy, ex, ey; + int p0dx, p0dy; + int p0ps, p1ps; + u32 size; + + if (!info || !viewport) + return -EINVAL; + + sx = viewport->x & ~0x3; + sy = viewport->y & ~0x3; + dx = viewport->width & ~0x3; + dy = viewport->height & ~0x3; + ex = sx + dx - 1; + ey = sy + dy - 1; + + size = adxfb_r32(fb, ADXFB_PAGE0_RESOLUTION); + p0dx = (size >> 16) & 0x7ff; + p0dy = (size >> 0) & 0x7ff; + + size = adxfb_r32(fb, ADXFB_PAGE0_FORMAT) & 0xff; + p0ps = fmt_to_bpp(size) / 8; + + size = adxfb_r32(fb, ADXFB_PAGE1_FORMAT) & 0xff; + p1ps = fmt_to_bpp(size) / 8; + + adxfb_disable(fb); + spin_lock(&fb->lock); + + size = (((dx + 0) & 0x7ff) << 16) | (dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION, size); + + /* FIXME: (dx + 4) is a hack! */ + size = ((((dx + 4) * p1ps) & 0x1fff) << 16) | (dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION_PHYSICAL, size); + + size = ((((p0dx + 0) * p1ps) & 0x1fff) << 16) | (p0dy & 0x7ff); + adxfb_w32(fb, ADXFB_PAGE1_RESOLUTION_VIRTUAL, size); + + adxfb_w32(fb, ADXFB_PAGE1_SIZE_PHYSICAL, dx * dy * p1ps); + adxfb_w32(fb, ADXFB_PAGE1_SIZE_VIRTUAL, p0dx * p0dy * p1ps); + + size = ((sx & 0x7ff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_START, size); + + size = ((ex & 0x7ff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_END, size); + + size = (((sx * p0ps) & 0x1fff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_START, size); + adxfb_w32(fb, ADXFB_PAGE1_OFFSET, size); + + size = (((ex * p0ps) & 0x1fff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_END, size); + + size = (((sx * p1ps) & 0x1fff) << 16) | (sy & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_START, size); + + size = (((ex * p1ps) & 0x1fff) << 16) | (ey & 0x7ff); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_END, size); + + adxfb_w32(fb, ADXFB_OVERLAY_PAGE0_SIZE, dx * dy * p0ps); + adxfb_w32(fb, ADXFB_OVERLAY_PAGE1_SIZE, dx * dy * p1ps); + + adxfb_w32(fb, ADXFB_OVERLAY_LEVEL, 0xff); + + spin_unlock(&fb->lock); + adxfb_enable(fb); + + return 0; +} diff --git a/drivers/video/adxfb/scaler.c b/drivers/video/adxfb/scaler.c new file mode 100644 index 0000000..96e5796 --- /dev/null +++ b/drivers/video/adxfb/scaler.c @@ -0,0 +1,231 @@ +/* + * linux/drivers/video/adxfb/fb.c + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Written by Thierry Reding <thi...@av...> + */ + +#include <linux/fb.h> +#include "adxfb.h" + +/** + * struct scaler_mode - scaler mode values + * @uh: horizontal up scaling factor + * @dh: horizontal down scaling factor + * @uv: vertical up scaling factor + * @dv: vertical down scaling factor + * @ox: original horizontal resolution + * @oy: original vertical resolution + * @tx: target horizontal resolution + * @ty: target vertical resolution + */ +struct scaler_mode { + u16 uh, dh; + u16 uv, dv; + u16 ox, oy; + u16 tx, ty; +}; + +/* register definitions */ +#define SCALER_MODE 0x000 +#define SCALER_MODE_ENABLE_X (1 << 0) +#define SCALER_MODE_ENABLE_Y (1 << 1) +#define SCALER_MODE_BYPASS_X (1 << 2) +#define SCALER_MODE_BYPASS_Y (1 << 3) +#define SCALER_MODE_RGB_888 (1 << 4) +#define SCALER_MODE_LOWPASS (1 << 7) +#define SCALER_MODE_SYNC (1 << 8) +#define SCALER_MODE_RESET (1 << 15) +#define SCALER_MODE_LOCK (1 << 31) +#define SCALER_UH 0x008 +#define SCALER_DH 0x010 +#define SCALER_UV 0x030 +#define SCALER_DV 0x038 +#define SCALER_ORIGIN_X 0x040 +#define SCALER_ORIGIN_Y 0x048 +#define SCALER_OFFSET_X 0x050 +#define SCALER_OFFSET_Y 0x058 +#define SCALER_TARGET_X 0x060 +#define SCALER_TARGET_Y 0x068 +#define SCALER_ORIGIN_STRIDE 0x070 +#define SCALER_TARGET_STRIDE 0x078 +#define SCALER_ORIGIN_SIZE 0x080 +#define SCALER_TARGET_SIZE 0x088 +#define SCALER_PRIMARY_PRE_TARGET_ADDR 0x090 +#define SCALER_PRIMARY_TARGET_ADDR 0x098 +#define SCALER_SECONDARY_PRE_TARGET_ADDR 0x0a0 +#define SCALER_SECONDARY_TARGET_ADDR 0x0a8 + +/** + * scaler_r32() - read a 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + */ +static inline u32 scaler_r32(struct adxfb_info *fb, unsigned long offset) +{ + return readl(fb->scaler_base + offset); +} + +/** + * scaler_w32() - write a 32-bit register + * @fb: framebuffer context + * @offset: relative register offset + * @value: value to write to the register + */ +static inline void scaler_w32(struct adxfb_info *fb, unsigned long offset, + u32 value) +{ + writel(value, fb->scaler_base + offset); +} + +/** + * scaler_enable() - enable the scaling unit + * @fb: framebuffer context + */ +static inline void scaler_enable(struct adxfb_info *fb) +{ + u32 mode; + + spin_lock(&fb->lock); + + mode = scaler_r32(fb, SCALER_MODE); + mode |= SCALER_MODE_ENABLE_X; + mode |= SCALER_MODE_ENABLE_Y; + mode &= ~SCALER_MODE_LOCK; + scaler_w32(fb, SCALER_MODE, mode); + + spin_unlock(&fb->lock); +} + +/** + * scaler_disable() - disable the scaling unit + * @fb: framebuffer context + */ +static inline void scaler_disable(struct adxfb_info *fb) +{ + u32 mode; + + spin_lock(&fb->lock); + + mode = scaler_r32(fb, SCALER_MODE); + mode |= SCALER_MODE_LOCK; + mode &= ~SCALER_MODE_ENABLE_Y; + mode &= ~SCALER_MODE_ENABLE_X; + scaler_w32(fb, SCALER_MODE, mode); + + spin_unlock(&fb->lock); +} + +/** + * find_mode() - match a request to the best mode that can be achieved + * @fb: framebuffer context + * @mode: requested mode + */ +static int find_mode(struct adxfb_info *fb, struct scaler_mode *mode) +{ + if (!fb || !mode) + return -EINVAL; + + if ((mode->tx == 0) || (mode->ty == 0)) + return 0; + + mode->uh = scaler_r32(fb, SCALER_UH) & 0x7ff; + mode->uh = 128; /* FIXME: don't hardcode */ + mode->uv = scaler_r32(fb, SCALER_UV) & 0x7ff; + mode->uv = 128; /* FIXME: don't hardcode */ + + mode->dh = (mode->ox * mode->uh) / mode->tx; + mode->dv = (mode->oy * mode->uv) / mode->ty; + + mode->tx = (mode->ox * mode->uh) / mode->dh; + mode->ty = (mode->oy * mode->uv) / mode->dv; + + /* TODO: check the parameters */ + + return 0; +} + +/** + * adxfb_scaler_set_mode() - set a given scaler mode + * @info: framebuffer context + * @modep: scaler mode + */ +int adxfb_scaler_set_mode(struct fb_info *info, + struct adxfb_scaler_mode *modep) +{ + struct adxfb_info *fb = info->par; + struct scaler_mode mode; + int err, bpp; + u32 ctrl; + + memset(&mode, 0, sizeof(mode)); + mode.ox = modep->origin_x; + mode.oy = modep->origin_y; + mode.tx = modep->target_x; + mode.ty = modep->target_y; + + scaler_disable(fb); + spin_lock(&fb->lock); + + err = find_mode(fb, &mode); + if (err < 0) { + spin_unlock(&fb->lock); + scaler_enable(fb); + return err; + } + + ctrl = scaler_r32(fb, SCALER_MODE); + if (ctrl & SCALER_MODE_RGB_888) + bpp = 24; + else + bpp = 16; + + scaler_w32(fb, SCALER_UH, mode.uh); + scaler_w32(fb, SCALER_DH, mode.dh); + scaler_w32(fb, SCALER_UV, mode.uv); + scaler_w32(fb, SCALER_DV, mode.dv); + + scaler_w32(fb, SCALER_OFFSET_X, 0); + scaler_w32(fb, SCALER_OFFSET_Y, 0); + + scaler_w32(fb, SCALER_ORIGIN_X, mode.ox); + scaler_w32(fb, SCALER_ORIGIN_Y, mode.oy); + scaler_w32(fb, SCALER_TARGET_X, mode.tx); + scaler_w32(fb, SCALER_TARGET_Y, mode.ty); + + scaler_w32(fb, SCALER_ORIGIN_STRIDE, mode.ox * (bpp / 8)); + scaler_w32(fb, SCALER_TARGET_STRIDE, mode.tx * (bpp / 8)); + + scaler_w32(fb, SCALER_ORIGIN_SIZE, mode.ox * mode.oy * (bpp / 8)); + scaler_w32(fb, SCALER_TARGET_SIZE, mode.tx * mode.ty * (bpp / 8)); + + spin_unlock(&fb->lock); + scaler_enable(fb); + return 0; +} + +/** + * adxfb_scaler_mode() - obtain the current scaler mode + * @info: framebuffer context + * @modep: structure to return the mode in + */ +int adxfb_scaler_get_mode(struct fb_info *info, struct adxfb_scaler_mode *modep) +{ + struct adxfb_info *fb = info->par; + + spin_lock(&fb->lock); + + modep->origin_x = scaler_r32(fb, SCALER_ORIGIN_X) & 0x7ff; + modep->origin_y = scaler_r32(fb, SCALER_ORIGIN_Y) & 0x7ff; + modep->target_x = scaler_r32(fb, SCALER_TARGET_X) & 0x7ff; + modep->target_y = scaler_r32(fb, SCALER_TARGET_Y) & 0x7ff; + + spin_unlock(&fb->lock); + return 0; +} diff --git a/include/video/Kbuild b/include/video/Kbuild index 0e406f7..72fc9b0 100644 --- a/include/video/Kbuild +++ b/include/video/Kbuild @@ -1,2 +1,3 @@ unifdef-y += sisfb.h uvesafb.h unifdef-y += edid.h +unifdef-y += adxfb.h diff --git a/include/video/adxfb.h b/include/video/adxfb.h new file mode 100644 index 0000000..534b9e7 --- /dev/null +++ b/include/video/adxfb.h @@ -0,0 +1,79 @@ +/* + * linux/include/video/adxfb.h + * + * Copyright (C) 2007-2008 Avionic Design Development GmbH + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Written by Thierry Reding <thi...@av...> + */ + +#ifndef _VIDEO_ADXFB_H +#define _VIDEO_ADXFB_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +/** + * struct adxfb_scaler_mode - scaler mode definition structure + * @origin_x: original horizontal resolution + * @origin_y: original vertical resolution + * @target_x: targetted horizontal resolution + * @target_y: targetted vertical resolution + */ +struct adxfb_scaler_mode { + /* original resolution */ + __u16 origin_x; + __u16 origin_y; + /* target resolution */ + __u16 target_x; + __u16 target_y; +}; + +/** + * struct adxfb_viewport - overlay viewport structure + * @x: horizontal start position of the overlay window + * @y: vertical start position of the overlay window + * @width: width of the overlay window + * @height: height of the overlay window + */ +struct adxfb_viewport { + /* viewport position */ + __u16 x; + __u16 y; + /* viewport resolution */ + __u16 width; + __u16 height; +}; + +/* I/O control codes */ +#define ADXFB_IOC_MAGIC 'a' + +/* set a new scaler mode */ +#define ADXFB_IOCTL_SCALER_SET_MODE \ + _IOW(ADXFB_IOC_MAGIC, 0, struct adxfb_scaler_mode) +/* obtain the current scaler mode */ +#define ADXFB_IOCTL_SCALER_GET_MODE \ + _IOR(ADXFB_IOC_MAGIC, 1, struct adxfb_scaler_mode) +/* enable/disable the overlay window */ +#define ADXFB_IOCTL_OVERLAY_ENABLE \ + _IOW(ADXFB_IOC_MAGIC, 2, unsigned long) +/* set a new region for the overlay window */ +#define ADXFB_IOCTL_OVERLAY_SET_VIEWPORT \ + _IOW(ADXFB_IOC_MAGIC, 3, struct adxfb_viewport) +/* set a new input video standard */ +#define ADXFB_IOCTL_SET_INPUT \ + _IOW(ADXFB_IOC_MAGIC, 4, unsigned long) + +/* ADXFB_IOCTL_OVERLAY_ENABLE flags */ +#define ADXFB_OVERLAY_ENABLE (1 << 0) /* enable/disable overlay */ + +/* ADXFB_IOCTL_SET_INPUT parameters */ +#define ADXFB_INPUT_PAL (0x00) /* input is PAL standard */ +#define ADXFB_INPUT_NTSC (0x01) /* input is NTSC stardard */ +#define ADXFB_INPUT_MASK (0xff) /* mask to extract input */ + +#endif /* !_VIDEO_ADXFB_H */ -- tg: (c98059f..) adx/fb (depends on: adx/master) |
From: Florian T. S. <Flo...@gm...> - 2009-08-14 12:44:09
|
Hi, thanks a lot for your testing! Roman Sergeev schrieb: > test # 1 > * send to kernel "vmalloc=260M" > > # modprobe viafb For my patch to fix this bug I would be interested in something like this: * send to kernel "vmalloc=260M" # modprobe viafb viafb_accel=0 If it is similar to the result of test #2 I could simply disable hardware acceleration if the second ioremap fails which is IMHO better than refusing to work as hardware acceleration is a nice to have but not crucial for device operation. > test # 2 > * send to kernel "vmalloc=300M" > * modprobe viafb > * loaded ok > > status: > # grep viafb /proc/modules > viafb 71840 1 - Live 0xece42000 > i2c_algo_bit 4656 1 viafb, Live 0xece24000 > > log: > Jun 21 23:52:12 mini2133 [ 47.308459] VIA Graphics Intergration > Chipset framebuffer 2.4 initializing > Jun 21 23:52:12 mini2133 [ 47.393518] Console: switching to colour > frame buffer device 80x30 > > but i see "test color mode" > > fbset -i > > mode "640x480-60" > # D: 25.175 MHz, H: 31.469 kHz, V: 59.940 Hz > geometry 640 480 640 480 32 > timings 39722 48 16 33 10 96 2 > accel true > rgba 8/16,8/8,8/0,0/0 > endmode > > Frame buffer device information: > Name : Via > Address : 0xc0000000 > Size : 268156928 > Type : PACKED PIXELS > Visual : TRUECOLOR > XPanStep : 0 > YPanStep : 1 > YWrapStep : 0 > LineLength : 2560 > MMIO Address: 0xfc000000 > MMIO Size : 16777216 > Accelerator : Unknown (50) > > if i loading module with parametrs "modprobe viafb viafb_mode=800x600 > viafb_refresh=60" > they still go "test color mode" > log: > Jun 22 00:28:11 mini2133 [ 142.994541] VIA Graphics Intergration > Chipset framebuffer 2.4 initializing > Jun 22 00:28:11 mini2133 [ 143.079079] Console: switching to colour > frame buffer device 100x37 This looks fine. I'd guess the driver itself is working. Unfortunately I do not fully understand the term "test color mode". Can you describe what you see? monocolor, if yes what color or some strange patterns? even whether it is shown immediately or is somehow slowly painted might help. Perhaps using the module parameter viafb_active_dev= with one of CRT, DVI or LCD helps? If it doesn't....well I'm aware of one bug in that code that I hit on my netbook. Will send you a fix if your observations sound related. > ps: other \ standart kernel framebuffer module on this card works well Yeah, the problem we now hit is some monitor misconfiguration but as the standard vga/vesa driver does not really know about those device specific things that's expected. Thanks, Florian Tobias Schandinat |
From: Roman S. <sun...@gm...> - 2009-08-14 10:46:21
|
Hi! On 14.08.2009, at 12:49, Florian Tobias Schandinat wrote: > Roman Sergeev schrieb: >> 01:00.0 VGA compatible controller: VIA Technologies, Inc. P4M900 >> [Chrome 9 HC] (rev 01) >> with shadow ram (total 2Gb, but system see 1768Mb... maybe 280Mb) > > This makes sense: > 2 GB physical RAM > - 256 MB used as shared memory video RAM > = 1792 MB available > I don't know where the other memory is lost but the video memory > size seems to be detected correctly. > >> after modprobe viafb don't die, they going to new state >> viafb 75212 1 - Loading 0xef642000 > > I don't know if I get you right here: > After "modprobe viafb viafb_accel=0" the module does no longer > crash? But I don't know what state you are talking about. Is the > module usable? (i.e. does "modprobe fbcon" give you a working > framebuffer console?) Or can you otherwise post a new log? > > i make some "test" test # 0 # modprobe viafb FATAL: Error inserting viafb (/lib/modules/2.6.30-gentoo-r4/kernel/ drivers/video/via/viafb.ko): Operation not permitted log: Jun 22 00:34:48 mini2133 [ 89.952746] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 22 00:34:48 mini2133 [ 90.031236] vmap allocation for size 268439552 failed: use vmalloc=<size> to increase size. Jun 22 00:34:48 mini2133 [ 90.031244] ioremap failed test # 1 * send to kernel "vmalloc=260M" # modprobe viafb Killed log: Jun 22 00:41:50 mini2133 [ 46.690400] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 22 00:41:50 mini2133 [ 46.770663] vmap allocation for size 16781312 failed: use vmalloc=<size> to increase size. Jun 22 00:41:50 mini2133 [ 46.770684] BUG: unable to handle kernel NULL pointer dereference at 00000004 Jun 22 00:41:50 mini2133 [ 46.770885] IP: [<ef64a798>] viafb_init_2d_engine+0x16/0x583 [viafb] Jun 22 00:41:50 mini2133 [ 46.771005] *pde = 00000000 Jun 22 00:41:50 mini2133 [ 46.771005] Oops: 0002 [#1] SMP Jun 22 00:41:50 mini2133 [ 46.771005] last sysfs file: /sys/devices/ pci0000:00/0000:00:0f.0/host0/target0:0:0/0:0:0:0/block/sda/uevent Jun 22 00:41:50 mini2133 [ 46.771005] Modules linked in: viafb(+) i2c_algo_bit via drm via_agp agpgart Jun 22 00:41:50 mini2133 [ 46.771005] Jun 22 00:41:50 mini2133 [ 46.771005] Pid: 4094, comm: modprobe Not tainted (2.6.30-gentoo-r4 #13) Jun 22 00:41:50 mini2133 [ 46.771005] EIP: 0060:[<ef64a798>] EFLAGS: 00010202 CPU: 0 Jun 22 00:41:50 mini2133 [ 46.771005] EIP is at viafb_init_2d_engine +0x16/0x583 [viafb] Jun 22 00:41:50 mini2133 [ 46.771005] EAX: 00000004 EBX: ed8bd280 ECX: c256d700 EDX: 00000000 Jun 22 00:41:50 mini2133 [ 46.771005] ESI: fffffffc EDI: 00000000 EBP: ed8c1f18 ESP: ed8c1f08 Jun 22 00:41:50 mini2133 [ 46.771005] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Jun 22 00:41:50 mini2133 [ 46.771005] Process modprobe (pid: 4094, ti=ed8c0000 task=ee7d84e0 task.ti=ed8c0000) Jun 22 00:41:50 mini2133 [ 46.771005] Stack: Jun 22 00:41:50 mini2133 [ 46.771005] 00000000 ed8bd280 fffffffc 00000000 ed8c1f40 ef656505 00000000 ed8c1f40 Jun 22 00:41:50 mini2133 [ 46.771005] c1062132 00000000 00000000 ef6535e4 fffffffc 00000000 ed8c1f9c c1001137 Jun 22 00:41:50 mini2133 [ 46.771005] ef656000 00000000 ef6535e4 00000001 00000000 c15dec24 00000000 c15dec34 Jun 22 00:41:50 mini2133 [ 46.771005] Call Trace: Jun 22 00:41:50 mini2133 [ 46.771005] [<ef656505>] ? viafb_init +0x505/0xd2c [viafb] Jun 22 00:41:50 mini2133 [ 46.771005] [<c1062132>] ? marker_update_probe_range+0x1cf/0x1de Jun 22 00:41:50 mini2133 [ 46.771005] [<c1001137>] ? do_one_initcall +0x4a/0x10c Jun 22 00:41:50 mini2133 [ 46.771005] [<ef656000>] ? viafb_init +0x0/0xd2c [viafb] Jun 22 00:41:50 mini2133 [ 46.771005] [<c103ae2d>] ? __blocking_notifier_call_chain+0x40/0x4c Jun 22 00:41:50 mini2133 [ 46.771005] [<c10481f6>] ? sys_init_module +0x87/0x18b Jun 22 00:41:50 mini2133 [ 46.771005] [<c1002a44>] ? sysenter_do_call+0x12/0x22 Jun 22 00:41:50 mini2133 [ 46.771005] Code: ff ff 03 00 89 42 44 a1 44 38 65 ef 81 40 38 00 20 04 00 5d c3 55 31 d2 89 e5 57 56 53 83 ec 04 a1 44 38 65 ef 8b 40 1c 83 c0 04 <89> 10 a1 44 38 65 ef 8b 40 1c 83 c0 08 89 10 a1 44 38 65 ef 8b Jun 22 00:41:50 mini2133 [ 46.771005] EIP: [<ef64a798>] viafb_init_2d_engine+0x16/0x583 [viafb] SS:ESP 0068:ed8c1f08 Jun 22 00:41:50 mini2133 [ 46.771005] CR2: 0000000000000004 Jun 22 00:41:50 mini2133 [ 46.777862] ---[ end trace e41091c450ca8ab2 ]--- status: # grep viafb /proc/modules viafb 75212 1 - Loading 0xef642000 i2c_algo_bit 4656 1 viafb, Live 0xef624000 test # 2 * send to kernel "vmalloc=300M" * modprobe viafb * loaded ok status: # grep viafb /proc/modules viafb 71840 1 - Live 0xece42000 i2c_algo_bit 4656 1 viafb, Live 0xece24000 log: Jun 21 23:52:12 mini2133 [ 47.308459] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 21 23:52:12 mini2133 [ 47.393518] Console: switching to colour frame buffer device 80x30 but i see "test color mode" fbset -i mode "640x480-60" # D: 25.175 MHz, H: 31.469 kHz, V: 59.940 Hz geometry 640 480 640 480 32 timings 39722 48 16 33 10 96 2 accel true rgba 8/16,8/8,8/0,0/0 endmode Frame buffer device information: Name : Via Address : 0xc0000000 Size : 268156928 Type : PACKED PIXELS Visual : TRUECOLOR XPanStep : 0 YPanStep : 1 YWrapStep : 0 LineLength : 2560 MMIO Address: 0xfc000000 MMIO Size : 16777216 Accelerator : Unknown (50) if i loading module with parametrs "modprobe viafb viafb_mode=800x600 viafb_refresh=60" they still go "test color mode" log: Jun 22 00:28:11 mini2133 [ 142.994541] VIA Graphics Intergration Chipset framebuffer 2.4 initializing Jun 22 00:28:11 mini2133 [ 143.079079] Console: switching to colour frame buffer device 100x37 ps: other \ standart kernel framebuffer module on this card works well |
From: Florian T. S. <Flo...@gm...> - 2009-08-14 08:49:49
|
Roman Sergeev schrieb: > 01:00.0 VGA compatible controller: VIA Technologies, Inc. P4M900 [Chrome > 9 HC] (rev 01) > with shadow ram (total 2Gb, but system see 1768Mb... maybe 280Mb) This makes sense: 2 GB physical RAM - 256 MB used as shared memory video RAM = 1792 MB available I don't know where the other memory is lost but the video memory size seems to be detected correctly. > after modprobe viafb don't die, they going to new state > viafb 75212 1 - Loading 0xef642000 I don't know if I get you right here: After "modprobe viafb viafb_accel=0" the module does no longer crash? But I don't know what state you are talking about. Is the module usable? (i.e. does "modprobe fbcon" give you a working framebuffer console?) Or can you otherwise post a new log? An alternative to disabling the hardware acceleration might be to increase vmalloc=260M to a value greater than 256+16 MB, like vmalloc=300MB or so. Okay, I think I have a deeper understanding now: - the driver tries to remap 256 MB (video framebuffer) and 16 MB (MMIO registers) - the free region is per default only 128 MB and is only on systems with significant less physical RAM than kernel virtual memory space bigger So in addition to handle the second ioremap failure (for which I have already a patch prepared) one of the following might be nice - add/reuse module/boot parameter to limit the available video memory size - automatically try to remap smaller parts of the video memory if the first ioremap fails - after having checked the code again I think it uses very rarely the remapped video memory. If I didn't miss a big thing after having my recent patches applied there might be 2-3 places left that use a few kilobytes of it. Nothing that justifies permanently remapping the whole bunch. If no one speaks against it I'll try to replace this big remap with one or two small ones. Though this might take a while. Any comments? Regards, Florian Tobias Schandinat |
From: Roman S. <sun...@gm...> - 2009-08-14 06:39:16
|
On 14.08.2009, at 1:24, Florian Tobias Schandinat wrote: >>> >>> ps: viafb build as a module >>> >> a) The driver appears to be ioremapping more virtual address space >> than the machine can provide. >> Is that expected? > > I don't know. > Is the video memory size detection of (I think) 256 MB correct? > What is the graphic chip? (CLE266, CN400, CN700, KM400, CX700 or > VX800?) > 01:00.0 VGA compatible controller: VIA Technologies, Inc. P4M900 [Chrome 9 HC] (rev 01) with shadow ram (total 2Gb, but system see 1768Mb... maybe 280Mb) after modprobe viafb don't die, they going to new state viafb 75212 1 - Loading 0xef642000 |
From: Florian T. S. <Flo...@gm...> - 2009-08-13 21:24:41
|
Hi, excuse me to interfere although I don't know the memory subsystem/functions very well. Andrew Morton schrieb: > (switched to email. Please respond via emailed reply-to-all, not via the > bugzilla web interface). > > On Thu, 13 Aug 2009 15:22:41 GMT > bug...@bu... wrote: > >> http://bugzilla.kernel.org/show_bug.cgi?id=13976 >> >> Summary: viafb + vmalloc >> Product: Drivers >> Version: 2.5 >> Kernel Version: 2.6.30.4 >> Platform: All >> OS/Version: Linux >> Tree: Mainline >> Status: NEW >> Severity: normal >> Priority: P1 >> Component: Video(Other) >> AssignedTo: dri...@ke... >> ReportedBy: sun...@gm... >> Regression: No > > OK, this is bad. > >> #modprobe viafb >> Jun 21 05:17:53 mini2133 [ 50.504357] VIA Graphics Intergration Chipset >> framebuffer 2.4 initializing >> Jun 21 05:17:53 mini2133 [ 50.583434] vmap allocation for size 268439552 >> failed: use vmalloc=<size> to increase size. >> Jun 21 05:17:53 mini2133 [ 50.583443] ioremap failed >> >> if add parametr vmalloc=260M to kernel >> >> #modprobe viafb >> Jun 21 05:11:17 mini2133 [ 60.692317] VIA Graphics Intergration Chipset >> framebuffer 2.4 initializing >> Jun 21 05:11:17 mini2133 [ 60.772731] vmap allocation for size 16781312 >> failed: use vmalloc=<size> to increase size. >> Jun 21 05:11:17 mini2133 [ 60.772750] BUG: unable to handle kernel NULL >> pointer dereference at 00000004 >> Jun 21 05:11:17 mini2133 [ 60.772921] IP: [<ef64a798>] >> viafb_init_2d_engine+0x16/0x583 [viafb] >> Jun 21 05:11:17 mini2133 [ 60.773005] *pde = 00000000 >> Jun 21 05:11:17 mini2133 [ 60.773005] Oops: 0002 [#1] SMP >> Jun 21 05:11:17 mini2133 [ 60.773005] last sysfs file: >> /sys/devices/pci0000:00/0000:00:0f.0/host0/target0:0:0/0:0:0:0/block/sda/uevent >> Jun 21 05:11:17 mini2133 [ 60.773005] Modules linked in: viafb(+) >> i2c_algo_bit via drm via_agp agpgart >> Jun 21 05:11:17 mini2133 [ 60.773005] >> Jun 21 05:11:17 mini2133 [ 60.773005] Pid: 4084, comm: modprobe Not tainted >> (2.6.30-gentoo-r4 #13) >> Jun 21 05:11:17 mini2133 [ 60.773005] EIP: 0060:[<ef64a798>] EFLAGS: 00010202 >> CPU: 0 >> Jun 21 05:11:17 mini2133 [ 60.773005] EIP is at >> viafb_init_2d_engine+0x16/0x583 [viafb] >> Jun 21 05:11:17 mini2133 [ 60.773005] EAX: 00000004 EBX: ed8a5280 ECX: >> c256d700 EDX: 00000000 >> Jun 21 05:11:17 mini2133 [ 60.773005] ESI: fffffffc EDI: 00000000 EBP: >> ed8b3f18 ESP: ed8b3f08 >> Jun 21 05:11:17 mini2133 [ 60.773005] DS: 007b ES: 007b FS: 00d8 GS: 0033 >> SS: 0068 >> Jun 21 05:11:17 mini2133 [ 60.773005] Process modprobe (pid: 4084, >> ti=ed8b2000 task=ee7da220 task.ti=ed8b2000) >> Jun 21 05:11:17 mini2133 [ 60.773005] Stack: >> Jun 21 05:11:17 mini2133 [ 60.773005] 00000000 ed8a5280 fffffffc 00000000 >> ed8b3f40 ef656505 00000000 ed8b3f40 >> Jun 21 05:11:17 mini2133 [ 60.773005] c1062132 00000000 00000000 ef6535e4 >> fffffffc 00000000 ed8b3f9c c1001137 >> Jun 21 05:11:17 mini2133 [ 60.773005] ef656000 00000000 ef6535e4 00000001 >> 00000000 c15dec24 00000000 c15dec34 >> Jun 21 05:11:17 mini2133 [ 60.773005] Call Trace: >> Jun 21 05:11:17 mini2133 [ 60.773005] [<ef656505>] ? viafb_init+0x505/0xd2c >> [viafb] >> Jun 21 05:11:17 mini2133 [ 60.773005] [<c1062132>] ? >> marker_update_probe_range+0x1cf/0x1de >> Jun 21 05:11:17 mini2133 [ 60.773005] [<c1001137>] ? >> do_one_initcall+0x4a/0x10c >> Jun 21 05:11:17 mini2133 [ 60.773005] [<ef656000>] ? viafb_init+0x0/0xd2c >> [viafb] >> Jun 21 05:11:17 mini2133 [ 60.773005] [<c103ae2d>] ? >> __blocking_notifier_call_chain+0x40/0x4c >> Jun 21 05:11:17 mini2133 [ 60.773005] [<c10481f6>] ? >> sys_init_module+0x87/0x18b >> Jun 21 05:11:17 mini2133 [ 60.773005] [<c1002a44>] ? >> sysenter_do_call+0x12/0x22 >> Jun 21 05:11:17 mini2133 [ 60.773005] Code: ff ff 03 00 89 42 44 a1 44 38 65 >> ef 81 40 38 00 20 04 00 5d c3 55 31 d2 89 e5 57 56 53 83 ec 04 a1 44 38 65 ef >> 8b 40 1c 83 c0 04 <89> 10 a1 44 38 65 ef 8b 40 1c 83 c0 08 89 10 a1 44 38 65 ef >> 8b >> Jun 21 05:11:17 mini2133 [ 60.773005] EIP: [<ef64a798>] >> viafb_init_2d_engine+0x16/0x583 [viafb] SS:ESP 0068:ed8b3f08 >> Jun 21 05:11:17 mini2133 [ 60.773005] CR2: 0000000000000004 >> Jun 21 05:11:17 mini2133 [ 60.779905] ---[ end trace c390d80983a29e06 ]--- >> >> ps: viafb build as a module >> > > a) The driver appears to be ioremapping more virtual address space > than the machine can provide. > > Is that expected? I don't know. Is the video memory size detection of (I think) 256 MB correct? What is the graphic chip? (CLE266, CN400, CN700, KM400, CX700 or VX800?) > b) When ioremap_nocache() failed, the driver went and crashed the > machine. I don't see how this can happen - via_pci_probe() seems to > handle this correctly. > > It should return -ENOMEM rather than -1, but that's minor. If an ioremap_nocache() can cause this, I don't see why it can't be the later one: viaparinfo->io_virt = ioremap_nocache() As far as I know this is only used for acceleration so a quick test can be done with viafb_accel=0 module parameter. Regards, Florian Tobias Schandinat |
From: Andrew M. <ak...@li...> - 2009-08-13 19:36:58
|
(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface). On Thu, 13 Aug 2009 15:22:41 GMT bug...@bu... wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=13976 > > Summary: viafb + vmalloc > Product: Drivers > Version: 2.5 > Kernel Version: 2.6.30.4 > Platform: All > OS/Version: Linux > Tree: Mainline > Status: NEW > Severity: normal > Priority: P1 > Component: Video(Other) > AssignedTo: dri...@ke... > ReportedBy: sun...@gm... > Regression: No OK, this is bad. > > #modprobe viafb > Jun 21 05:17:53 mini2133 [ 50.504357] VIA Graphics Intergration Chipset > framebuffer 2.4 initializing > Jun 21 05:17:53 mini2133 [ 50.583434] vmap allocation for size 268439552 > failed: use vmalloc=<size> to increase size. > Jun 21 05:17:53 mini2133 [ 50.583443] ioremap failed > > if add parametr vmalloc=260M to kernel > > #modprobe viafb > Jun 21 05:11:17 mini2133 [ 60.692317] VIA Graphics Intergration Chipset > framebuffer 2.4 initializing > Jun 21 05:11:17 mini2133 [ 60.772731] vmap allocation for size 16781312 > failed: use vmalloc=<size> to increase size. > Jun 21 05:11:17 mini2133 [ 60.772750] BUG: unable to handle kernel NULL > pointer dereference at 00000004 > Jun 21 05:11:17 mini2133 [ 60.772921] IP: [<ef64a798>] > viafb_init_2d_engine+0x16/0x583 [viafb] > Jun 21 05:11:17 mini2133 [ 60.773005] *pde = 00000000 > Jun 21 05:11:17 mini2133 [ 60.773005] Oops: 0002 [#1] SMP > Jun 21 05:11:17 mini2133 [ 60.773005] last sysfs file: > /sys/devices/pci0000:00/0000:00:0f.0/host0/target0:0:0/0:0:0:0/block/sda/uevent > Jun 21 05:11:17 mini2133 [ 60.773005] Modules linked in: viafb(+) > i2c_algo_bit via drm via_agp agpgart > Jun 21 05:11:17 mini2133 [ 60.773005] > Jun 21 05:11:17 mini2133 [ 60.773005] Pid: 4084, comm: modprobe Not tainted > (2.6.30-gentoo-r4 #13) > Jun 21 05:11:17 mini2133 [ 60.773005] EIP: 0060:[<ef64a798>] EFLAGS: 00010202 > CPU: 0 > Jun 21 05:11:17 mini2133 [ 60.773005] EIP is at > viafb_init_2d_engine+0x16/0x583 [viafb] > Jun 21 05:11:17 mini2133 [ 60.773005] EAX: 00000004 EBX: ed8a5280 ECX: > c256d700 EDX: 00000000 > Jun 21 05:11:17 mini2133 [ 60.773005] ESI: fffffffc EDI: 00000000 EBP: > ed8b3f18 ESP: ed8b3f08 > Jun 21 05:11:17 mini2133 [ 60.773005] DS: 007b ES: 007b FS: 00d8 GS: 0033 > SS: 0068 > Jun 21 05:11:17 mini2133 [ 60.773005] Process modprobe (pid: 4084, > ti=ed8b2000 task=ee7da220 task.ti=ed8b2000) > Jun 21 05:11:17 mini2133 [ 60.773005] Stack: > Jun 21 05:11:17 mini2133 [ 60.773005] 00000000 ed8a5280 fffffffc 00000000 > ed8b3f40 ef656505 00000000 ed8b3f40 > Jun 21 05:11:17 mini2133 [ 60.773005] c1062132 00000000 00000000 ef6535e4 > fffffffc 00000000 ed8b3f9c c1001137 > Jun 21 05:11:17 mini2133 [ 60.773005] ef656000 00000000 ef6535e4 00000001 > 00000000 c15dec24 00000000 c15dec34 > Jun 21 05:11:17 mini2133 [ 60.773005] Call Trace: > Jun 21 05:11:17 mini2133 [ 60.773005] [<ef656505>] ? viafb_init+0x505/0xd2c > [viafb] > Jun 21 05:11:17 mini2133 [ 60.773005] [<c1062132>] ? > marker_update_probe_range+0x1cf/0x1de > Jun 21 05:11:17 mini2133 [ 60.773005] [<c1001137>] ? > do_one_initcall+0x4a/0x10c > Jun 21 05:11:17 mini2133 [ 60.773005] [<ef656000>] ? viafb_init+0x0/0xd2c > [viafb] > Jun 21 05:11:17 mini2133 [ 60.773005] [<c103ae2d>] ? > __blocking_notifier_call_chain+0x40/0x4c > Jun 21 05:11:17 mini2133 [ 60.773005] [<c10481f6>] ? > sys_init_module+0x87/0x18b > Jun 21 05:11:17 mini2133 [ 60.773005] [<c1002a44>] ? > sysenter_do_call+0x12/0x22 > Jun 21 05:11:17 mini2133 [ 60.773005] Code: ff ff 03 00 89 42 44 a1 44 38 65 > ef 81 40 38 00 20 04 00 5d c3 55 31 d2 89 e5 57 56 53 83 ec 04 a1 44 38 65 ef > 8b 40 1c 83 c0 04 <89> 10 a1 44 38 65 ef 8b 40 1c 83 c0 08 89 10 a1 44 38 65 ef > 8b > Jun 21 05:11:17 mini2133 [ 60.773005] EIP: [<ef64a798>] > viafb_init_2d_engine+0x16/0x583 [viafb] SS:ESP 0068:ed8b3f08 > Jun 21 05:11:17 mini2133 [ 60.773005] CR2: 0000000000000004 > Jun 21 05:11:17 mini2133 [ 60.779905] ---[ end trace c390d80983a29e06 ]--- > > ps: viafb build as a module > a) The driver appears to be ioremapping more virtual address space than the machine can provide. Is that expected? b) When ioremap_nocache() failed, the driver went and crashed the machine. I don't see how this can happen - via_pci_probe() seems to handle this correctly. It should return -ENOMEM rather than -1, but that's minor. |
From: Mark J. <mpf...@mi...> - 2009-08-12 09:16:37
|
At the moment you can set fbmem from the kernel bootargs, and xres / yres are usually setup in the board init files. However, there doesn;t seem to be any simple way to specify the virtual size of the display (eg. for double buffering). I have "hacked" the Atmel display driver in a quick and dirty way to fulfil my needs, but I guess it needs a more formal approach. Anyone care to comment on how this "issue" might be resolved ? Regards Mark --- drivers/video/atmel_lcdfb.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 2864e05..54df737 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -353,6 +353,11 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, return -EINVAL; } + /* Calculate virtual yres based on fbmem size */ + var->yres_virtual = info->fix.smem_len / + (var->xres * var->yres * (var->bits_per_pixel / 8)); + var->yres_virtual *= var->yres; + /* Do not allow to have real resoulution larger than virtual */ if (var->xres > var->xres_virtual) var->xres_virtual = var->xres; |
From: <hva...@ti...> - 2009-08-11 10:41:06
|
From: Vaibhav Hiremath <hva...@ti...> Tested - - Validated all three outut interfaces (LCD, DVI and TV) TODO: - Support for Backlight control range (0 - 100) - Enable selection for both S-Video and Composite TV out - DVI color (VPLL2_DEV_GRP should be equal to 0x7) Signed-off-by: Vaibhav Hiremath <hva...@ti...> --- arch/arm/configs/omap3_evm_defconfig | 51 +++++++- arch/arm/mach-omap2/board-omap3evm.c | 234 ++++++++++++++++++++++++++++++++-- 2 files changed, 273 insertions(+), 12 deletions(-) diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig index 28be17f..c9cc935 100644 --- a/arch/arm/configs/omap3_evm_defconfig +++ b/arch/arm/configs/omap3_evm_defconfig @@ -903,7 +903,56 @@ CONFIG_DAB=y # # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=4 +# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_FB_OMAP2=y +# CONFIG_FB_OMAP2_DEBUG_SUPPORT is not set +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set +CONFIG_PANEL_SHARP_LS037V7DW01=y # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 595beac..d488e29 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -22,6 +22,7 @@ #include <linux/input.h> #include <linux/leds.h> +#include <linux/regulator/machine.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> #include <linux/i2c/twl4030.h> @@ -37,6 +38,7 @@ #include <mach/common.h> #include <mach/mcspi.h> #include <mach/keypad.h> +#include <mach/display.h> #include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" @@ -90,6 +92,174 @@ static inline void __init omap3evm_init_smc911x(void) gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ); } +/* + * OMAP3EVM LCD Panel control signals + */ +#define OMAP3EVM_LCD_PANEL_LR 2 +#define OMAP3EVM_LCD_PANEL_UD 3 +#define OMAP3EVM_LCD_PANEL_INI 152 +#define OMAP3EVM_LCD_PANEL_ENVDD 153 +#define OMAP3EVM_LCD_PANEL_QVGA 154 +#define OMAP3EVM_LCD_PANEL_RESB 155 +#define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210 +#define OMAP3EVM_DVI_PANEL_EN_GPIO 199 + +static int lcd_enabled; +static int dvi_enabled; + +static void __init omap3_evm_display_init(void) +{ + int r; + r = gpio_request(OMAP3EVM_LCD_PANEL_RESB, "lcd_panel_resb"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_resb\n"); + return; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_RESB, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_INI, "lcd_panel_ini"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_ini\n"); + goto err_1; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_INI, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_QVGA, "lcd_panel_qvga"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_qvga\n"); + goto err_2; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_QVGA, 0); + + r = gpio_request(OMAP3EVM_LCD_PANEL_LR, "lcd_panel_lr"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_lr\n"); + goto err_3; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_LR, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_UD, "lcd_panel_ud"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_ud\n"); + goto err_4; + } + gpio_direction_output(OMAP3EVM_LCD_PANEL_UD, 1); + + r = gpio_request(OMAP3EVM_LCD_PANEL_ENVDD, "lcd_panel_envdd"); + if (r) { + printk(KERN_ERR "failed to get lcd_panel_envdd\n"); + goto err_5; + } + + return; + +err_5: + gpio_free(OMAP3EVM_LCD_PANEL_UD); +err_4: + gpio_free(OMAP3EVM_LCD_PANEL_LR); +err_3: + gpio_free(OMAP3EVM_LCD_PANEL_QVGA); +err_2: + gpio_free(OMAP3EVM_LCD_PANEL_INI); +err_1: + gpio_free(OMAP3EVM_LCD_PANEL_RESB); + +} + +static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0); + gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); + lcd_enabled = 1; + return 0; +} + +static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1); + gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); + lcd_enabled = 0; +} + +static struct omap_dss_device omap3_evm_lcd_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd", + .driver_name = "sharp_ls_panel", + .phy.dpi.data_lines = 18, + .platform_enable = omap3_evm_enable_lcd, + .platform_disable = omap3_evm_disable_lcd, +}; + +static int omap3_evm_enable_tv(struct omap_dss_device *dssdev) +{ + return 0; +} + +static void omap3_evm_disable_tv(struct omap_dss_device *dssdev) +{ +} + +static struct omap_dss_device omap3_evm_tv_device = { + .type = OMAP_DISPLAY_TYPE_VENC, + .name = "tv", + .driver_name = "venc", + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .platform_enable = omap3_evm_enable_tv, + .platform_disable = omap3_evm_disable_tv, +}; + +static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + + gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1); + dvi_enabled = 1; + + return 0; +} + +static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0); + dvi_enabled = 0; +} + +static struct omap_dss_device omap3_evm_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_panel", + .phy.dpi.data_lines = 24, + .platform_enable = omap3_evm_enable_dvi, + .platform_disable = omap3_evm_disable_dvi, +}; + +static struct omap_dss_device *omap3_evm_dss_devices[] = { + &omap3_evm_lcd_device, + &omap3_evm_tv_device, + &omap3_evm_dvi_device, +}; + +static struct omap_dss_board_info omap3_evm_dss_data = { + .num_devices = ARRAY_SIZE(omap3_evm_dss_devices), + .devices = omap3_evm_dss_devices, + .default_device = &omap3_evm_lcd_device, +}; + +static struct platform_device omap3_evm_dss_device = { + .name = "omapdss", + .id = -1, + .dev = { + .platform_data = &omap3_evm_dss_data, + }, +}; static struct omap_uart_config omap3_evm_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), @@ -142,6 +312,14 @@ static int omap3evm_twl_gpio_setup(struct device *dev, * the P2 connector; notably LEDA for the LCD backlight. */ + /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */ + gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + + /* gpio + 7 == DVI Enable */ + gpio_request(gpio + 7, "EN_DVI"); + gpio_direction_output(gpio + 7, 0); + /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; @@ -193,6 +371,47 @@ static struct twl4030_madc_platform_data omap3evm_madc_data = { .irq_line = 1, }; +static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = { + .supply = "vdda_dac", + .dev = &omap3_evm_dss_device.dev, +}; + +/* VDAC for DSS driving S-Video */ +static struct regulator_init_data omap3_evm_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &omap3_evm_vdda_dac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_consumer_supply omap3_evm_vpll2_supply = { + .supply = "vdvi", + .dev = &omap3_evm_lcd_device.dev, +}; + +static struct regulator_init_data omap3_evm_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &omap3_evm_vpll2_supply, +}; + static struct twl4030_platform_data omap3evm_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, @@ -202,6 +421,8 @@ static struct twl4030_platform_data omap3evm_twldata = { .madc = &omap3evm_madc_data, .usb = &omap3evm_usb_data, .gpio = &omap3evm_gpio_data, + .vdac = &omap3_evm_vdac, + .vpll2 = &omap3_evm_vpll2, }; static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { @@ -222,15 +443,6 @@ static int __init omap3_evm_i2c_init(void) return 0; } -static struct platform_device omap3_evm_lcd_device = { - .name = "omap3evm_lcd", - .id = -1, -}; - -static struct omap_lcd_config omap3_evm_lcd_config __initdata = { - .ctrl_name = "internal", -}; - static void ads7846_dev_init(void) { if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0) @@ -287,11 +499,10 @@ static void __init omap3_evm_init_irq(void) static struct omap_board_config_kernel omap3_evm_config[] __initdata = { { OMAP_TAG_UART, &omap3_evm_uart_config }, - { OMAP_TAG_LCD, &omap3_evm_lcd_config }, }; static struct platform_device *omap3_evm_devices[] __initdata = { - &omap3_evm_lcd_device, + &omap3_evm_dss_device, &omap3evm_smc911x_device, }; @@ -310,6 +521,7 @@ static void __init omap3_evm_init(void) usb_musb_init(); usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); ads7846_dev_init(); + omap3_evm_display_init(); } static void __init omap3_evm_map_io(void) -- 1.6.2.4 |
From: Julia L. <ju...@di...> - 2009-08-09 09:48:53
|
From: Julia Lawall <ju...@di...> request_region should be used with release_region, not request_mem_region. Geert Uytterhoeven pointed out that in the case of drivers/video/gbefb.c, the problem is actually the other way around; request_mem_region should be used instead of request_region. The semantic patch that finds/fixes this problem is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r1@ expression start; @@ request_region(start,...) @b1@ expression r1.start; @@ request_mem_region(start,...) @depends on !b1@ expression r1.start; expression E; @@ - release_mem_region + release_region (start,E) // </smpl> Signed-off-by: Julia Lawall <ju...@di...> --- drivers/video/gbefb.c | 2 +- drivers/video/tdfxfb.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff -u -p a/drivers/video/gbefb.c b/drivers/video/gbefb.c --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1147,7 +1147,7 @@ static int __init gbefb_probe(struct pla gbefb_setup(options); #endif - if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { + if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { printk(KERN_ERR "gbefb: couldn't reserve mmio region\n"); ret = -EBUSY; goto out_release_framebuffer; diff -u -p a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1571,8 +1571,8 @@ out_err_iobase: if (default_par->mtrr_handle >= 0) mtrr_del(default_par->mtrr_handle, info->fix.smem_start, info->fix.smem_len); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); out_err_screenbase: if (info->screen_base) iounmap(info->screen_base); |
From: Julia L. <ju...@di...> - 2009-08-09 09:37:34
|
Thanks forthe information. I will fix the occurrences in gbefb.c and then submit a revised vesion of the complete patch. julia On Sun, 9 Aug 2009, Geert Uytterhoeven wrote: > On Sun, Aug 9, 2009 at 09:44, Julia Lawall<ju...@di...> wrote: > > From: Julia Lawall <ju...@di...> > > > > request_region should be used with release_region, not request_mem_region. > > > > The semantic patch that fixes this problem is as follows: > > (http://coccinelle.lip6.fr/) > > > > // <smpl> > > @r1@ > > expression start; > > @@ > > > > request_region(start,...) > > > > @b1@ > > expression r1.start; > > @@ > > > > request_mem_region(start,...) > > > > @depends on !b1@ > > expression r1.start; > > expression E; > > @@ > > > > - release_mem_region > > + release_region > > (start,E) > > // </smpl> > > > > Signed-off-by: Julia Lawall <ju...@di...> > > > > --- > > drivers/video/gbefb.c | 4 ++-- > > drivers/video/tdfxfb.c | 4 ++-- > > 2 files changed, 4 insertions(+), 4 deletions(-) > > > > diff -u -p a/drivers/video/gbefb.c b/drivers/video/gbefb.c > > --- a/drivers/video/gbefb.c > > +++ b/drivers/video/gbefb.c > > @@ -1246,7 +1246,7 @@ out_tiles_free: > > out_unmap: > > iounmap(gbe); > > out_release_mem_region: > > - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); > > + release_region(GBE_BASE, sizeof(struct sgi_gbe)); > > GBE_BASE seems to be MMIO (it's mapped using ioremap()), so it looks like the > release_mem_region() is actually correct, while the request_region() should be > request_mem_region() instead > > > out_release_framebuffer: > > framebuffer_release(info); > > > > @@ -1265,7 +1265,7 @@ static int __devexit gbefb_remove(struct > > iounmap(gbe_mem); > > dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), > > (void *)gbe_tiles.cpu, gbe_tiles.dma); > > - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); > > + release_region(GBE_BASE, sizeof(struct sgi_gbe)); > > Ditto. > > > diff -u -p a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c > > --- a/drivers/video/tdfxfb.c > > +++ b/drivers/video/tdfxfb.c > > @@ -1571,8 +1571,8 @@ out_err_iobase: > > if (default_par->mtrr_handle >= 0) > > mtrr_del(default_par->mtrr_handle, info->fix.smem_start, > > info->fix.smem_len); > > - release_mem_region(pci_resource_start(pdev, 2), > > - pci_resource_len(pdev, 2)); > > + release_region(pci_resource_start(pdev, 2), > > + pci_resource_len(pdev, 2)); > > out_err_screenbase: > > if (info->screen_base) > > iounmap(info->screen_base); > > This one looks OK. > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@li... > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like that. > -- Linus Torvalds > -- > To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in > the body of a message to maj...@vg... > More majordomo info at http://vger.kernel.org/majordomo-info.html > |
From: Geert U. <gee...@gm...> - 2009-08-09 09:24:33
|
On Sun, Aug 9, 2009 at 09:44, Julia Lawall<ju...@di...> wrote: > From: Julia Lawall <ju...@di...> > > request_region should be used with release_region, not request_mem_region. > > The semantic patch that fixes this problem is as follows: > (http://coccinelle.lip6.fr/) > > // <smpl> > @r1@ > expression start; > @@ > > request_region(start,...) > > @b1@ > expression r1.start; > @@ > > request_mem_region(start,...) > > @depends on !b1@ > expression r1.start; > expression E; > @@ > > - release_mem_region > + release_region > (start,E) > // </smpl> > > Signed-off-by: Julia Lawall <ju...@di...> > > --- > drivers/video/gbefb.c | 4 ++-- > drivers/video/tdfxfb.c | 4 ++-- > 2 files changed, 4 insertions(+), 4 deletions(-) > > diff -u -p a/drivers/video/gbefb.c b/drivers/video/gbefb.c > --- a/drivers/video/gbefb.c > +++ b/drivers/video/gbefb.c > @@ -1246,7 +1246,7 @@ out_tiles_free: > out_unmap: > iounmap(gbe); > out_release_mem_region: > - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); > + release_region(GBE_BASE, sizeof(struct sgi_gbe)); GBE_BASE seems to be MMIO (it's mapped using ioremap()), so it looks like the release_mem_region() is actually correct, while the request_region() should be request_mem_region() instead > out_release_framebuffer: > framebuffer_release(info); > > @@ -1265,7 +1265,7 @@ static int __devexit gbefb_remove(struct > iounmap(gbe_mem); > dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), > (void *)gbe_tiles.cpu, gbe_tiles.dma); > - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); > + release_region(GBE_BASE, sizeof(struct sgi_gbe)); Ditto. > diff -u -p a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c > --- a/drivers/video/tdfxfb.c > +++ b/drivers/video/tdfxfb.c > @@ -1571,8 +1571,8 @@ out_err_iobase: > if (default_par->mtrr_handle >= 0) > mtrr_del(default_par->mtrr_handle, info->fix.smem_start, > info->fix.smem_len); > - release_mem_region(pci_resource_start(pdev, 2), > - pci_resource_len(pdev, 2)); > + release_region(pci_resource_start(pdev, 2), > + pci_resource_len(pdev, 2)); > out_err_screenbase: > if (info->screen_base) > iounmap(info->screen_base); This one looks OK. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@li... In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds |
From: Julia L. <ju...@di...> - 2009-08-09 07:44:40
|
From: Julia Lawall <ju...@di...> request_region should be used with release_region, not request_mem_region. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // <smpl> @r1@ expression start; @@ request_region(start,...) @b1@ expression r1.start; @@ request_mem_region(start,...) @depends on !b1@ expression r1.start; expression E; @@ - release_mem_region + release_region (start,E) // </smpl> Signed-off-by: Julia Lawall <ju...@di...> --- drivers/video/gbefb.c | 4 ++-- drivers/video/tdfxfb.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff -u -p a/drivers/video/gbefb.c b/drivers/video/gbefb.c --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1246,7 +1246,7 @@ out_tiles_free: out_unmap: iounmap(gbe); out_release_mem_region: - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); + release_region(GBE_BASE, sizeof(struct sgi_gbe)); out_release_framebuffer: framebuffer_release(info); @@ -1265,7 +1265,7 @@ static int __devexit gbefb_remove(struct iounmap(gbe_mem); dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), (void *)gbe_tiles.cpu, gbe_tiles.dma); - release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); + release_region(GBE_BASE, sizeof(struct sgi_gbe)); iounmap(gbe); gbefb_remove_sysfs(&p_dev->dev); framebuffer_release(info); diff -u -p a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1571,8 +1571,8 @@ out_err_iobase: if (default_par->mtrr_handle >= 0) mtrr_del(default_par->mtrr_handle, info->fix.smem_start, info->fix.smem_len); - release_mem_region(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); + release_region(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); out_err_screenbase: if (info->screen_base) iounmap(info->screen_base); |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:19
|
Signed-off-by: Tomi Valkeinen <tom...@no...> Acked-by: Tony Lindgren <to...@at...> --- arch/arm/configs/omap_3430sdp_defconfig | 31 +++++- arch/arm/mach-omap2/board-3430sdp.c | 171 +++++++++++++++++++++++++++---- 2 files changed, 181 insertions(+), 21 deletions(-) diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig index 73e0128..a0dce8f 100644 --- a/arch/arm/configs/omap_3430sdp_defconfig +++ b/arch/arm/configs/omap_3430sdp_defconfig @@ -1336,10 +1336,35 @@ CONFIG_FB_CFB_IMAGEBLIT=y # # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set -CONFIG_FB_OMAP=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +# CONFIG_FB_OMAP_031M3R is not set +# CONFIG_FB_OMAP_048M3R is not set +# CONFIG_FB_OMAP_079M3R is not set +# CONFIG_FB_OMAP_092M9R is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=6 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set +CONFIG_PANEL_SHARP_LS037V7DW01=y +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 21b4a52..0bb83f5 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -36,6 +36,7 @@ #include <mach/common.h> #include <mach/dma.h> #include <mach/gpmc.h> +#include <mach/display.h> #include <mach/control.h> #include <mach/keypad.h> @@ -148,23 +149,149 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { }, }; -static struct platform_device sdp3430_lcd_device = { - .name = "sdp2430_lcd", - .id = -1, + +#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 +#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 + +static unsigned backlight_gpio; +static unsigned enable_gpio; +static int lcd_enabled; +static int dvi_enabled; + +static void __init sdp3430_display_init(void) +{ + int r; + + enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; + backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; + + r = gpio_request(enable_gpio, "LCD reset"); + if (r) { + printk(KERN_ERR "failed to get LCD reset GPIO\n"); + goto err0; + } + + r = gpio_request(backlight_gpio, "LCD Backlight"); + if (r) { + printk(KERN_ERR "failed to get LCD backlight GPIO\n"); + goto err1; + } + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); + + return; +err1: + gpio_free(enable_gpio); +err0: + return; +} + +static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_direction_output(enable_gpio, 1); + gpio_direction_output(backlight_gpio, 1); + + lcd_enabled = 1; + + return 0; +} + +static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) +{ + lcd_enabled = 0; + + gpio_direction_output(enable_gpio, 0); + gpio_direction_output(backlight_gpio, 0); +} + +static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + + dvi_enabled = 1; + + return 0; +} + +static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev) +{ + dvi_enabled = 0; +} + +static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) +{ + return 0; +} + +static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) +{ +} + + +static struct omap_dss_device sdp3430_lcd_device = { + .name = "lcd", + .driver_name = "sharp_ls_panel", + .type = OMAP_DISPLAY_TYPE_DPI, + .phy.dpi.data_lines = 16, + .platform_enable = sdp3430_panel_enable_lcd, + .platform_disable = sdp3430_panel_disable_lcd, }; -static struct regulator_consumer_supply sdp3430_vdac_supply = { - .supply = "vdac", - .dev = &sdp3430_lcd_device.dev, +static struct omap_dss_device sdp3430_dvi_device = { + .name = "dvi", + .driver_name = "generic_panel", + .type = OMAP_DISPLAY_TYPE_DPI, + .phy.dpi.data_lines = 24, + .platform_enable = sdp3430_panel_enable_dvi, + .platform_disable = sdp3430_panel_disable_dvi, }; -static struct regulator_consumer_supply sdp3430_vdvi_supply = { - .supply = "vdvi", - .dev = &sdp3430_lcd_device.dev, +static struct omap_dss_device sdp3430_tv_device = { + .name = "tv", + .driver_name = "venc", + .type = OMAP_DISPLAY_TYPE_VENC, + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .platform_enable = sdp3430_panel_enable_tv, + .platform_disable = sdp3430_panel_disable_tv, }; -static struct platform_device *sdp3430_devices[] __initdata = { + +static struct omap_dss_device *sdp3430_dss_devices[] = { &sdp3430_lcd_device, + &sdp3430_dvi_device, + &sdp3430_tv_device, +}; + +static struct omap_dss_board_info sdp3430_dss_data = { + .num_devices = ARRAY_SIZE(sdp3430_dss_devices), + .devices = sdp3430_dss_devices, + .default_device = &sdp3430_lcd_device, +}; + +static struct platform_device sdp3430_dss_device = { + .name = "omapdss", + .id = -1, + .dev = { + .platform_data = &sdp3430_dss_data, + }, +}; + +static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { + .supply = "vdda_dac", + .dev = &sdp3430_dss_device.dev, +}; + +static struct platform_device *sdp3430_devices[] __initdata = { + &sdp3430_dss_device, }; static void __init omap_3430sdp_init_irq(void) @@ -178,13 +305,8 @@ static struct omap_uart_config sdp3430_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_lcd_config sdp3430_lcd_config __initdata = { - .ctrl_name = "internal", -}; - static struct omap_board_config_kernel sdp3430_config[] __initdata = { { OMAP_TAG_UART, &sdp3430_uart_config }, - { OMAP_TAG_LCD, &sdp3430_lcd_config }, }; static int sdp3430_batt_table[] = { @@ -391,22 +513,34 @@ static struct regulator_init_data sdp3430_vdac = { | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vdac_supply, + .consumer_supplies = &sdp3430_vdda_dac_supply, }; /* VPLL2 for digital video outputs */ +static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { + { + .supply = "vdvi", + .dev = &sdp3430_lcd_device.dev, + }, + { + .supply = "vdds_dsi", + .dev = &sdp3430_dss_device.dev, + } +}; + static struct regulator_init_data sdp3430_vpll2 = { .constraints = { .name = "VDVI", .min_uV = 1800000, .max_uV = 1800000, + .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vdvi_supply, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies), + .consumer_supplies = sdp3430_vpll2_supplies, }; static struct twl4030_platform_data sdp3430_twldata = { @@ -496,6 +630,7 @@ static void __init omap_3430sdp_init(void) usb_musb_init(); board_smc91x_init(); usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); + sdp3430_display_init(); } static void __init omap_3430sdp_map_io(void) -- 1.6.4 |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:18
|
Signed-off-by: Tomi Valkeinen <tom...@no...> Acked-by: Tony Lindgren <to...@at...> --- arch/arm/configs/omap3_beagle_defconfig | 26 ++++++- arch/arm/mach-omap2/board-omap3beagle.c | 119 ++++++++++++++++++++++++------- 2 files changed, 116 insertions(+), 29 deletions(-) diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig index c4726f0..1740be3 100644 --- a/arch/arm/configs/omap3_beagle_defconfig +++ b/arch/arm/configs/omap3_beagle_defconfig @@ -792,10 +792,30 @@ CONFIG_FB_CFB_IMAGEBLIT=y # # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set -CONFIG_FB_OMAP=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=6 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set +# CONFIG_PANEL_SHARP_LS037V7DW01 is not set +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index b6a68d5..c24dc76 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -30,6 +30,7 @@ #include <linux/regulator/machine.h> #include <linux/i2c/twl4030.h> +#include <linux/omapfb.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -44,6 +45,7 @@ #include <mach/mux.h> #include <mach/usb.h> #include <mach/timer-gp.h> +#include <mach/display.h> #include "mmc-twl4030.h" @@ -106,6 +108,92 @@ static struct platform_device omap3beagle_nand_device = { .resource = &omap3beagle_nand_resource, }; +/* DSS */ + +static int beagle_enable_dvi(struct omap_dss_device *dssdev) +{ + if (dssdev->reset_gpio != -1) + gpio_set_value(dssdev->reset_gpio, 1); + + return 0; +} + +static void beagle_disable_dvi(struct omap_dss_device *dssdev) +{ + if (dssdev->reset_gpio != -1) + gpio_set_value(dssdev->reset_gpio, 0); +} + +static struct omap_dss_device beagle_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_panel", + .phy.dpi.data_lines = 24, + .reset_gpio = 170, + .platform_enable = beagle_enable_dvi, + .platform_disable = beagle_disable_dvi, +}; + +static int beagle_panel_enable_tv(struct omap_dss_device *dssdev) +{ + return 0; +} + +static void beagle_panel_disable_tv(struct omap_dss_device *dssdev) +{ +} + +static struct omap_dss_device beagle_tv_device = { + .name = "tv", + .driver_name = "venc", + .type = OMAP_DISPLAY_TYPE_VENC, + .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, + .platform_enable = beagle_panel_enable_tv, + .platform_disable = beagle_panel_disable_tv, +}; + +static struct omap_dss_device *beagle_dss_devices[] = { + &beagle_dvi_device, + &beagle_tv_device, +}; + +static struct omap_dss_board_info beagle_dss_data = { + .num_devices = ARRAY_SIZE(beagle_dss_devices), + .devices = beagle_dss_devices, + .default_device = &beagle_dvi_device, +}; + +static struct platform_device beagle_dss_device = { + .name = "omapdss", + .id = -1, + .dev = { + .platform_data = &beagle_dss_data, + }, +}; + +static struct regulator_consumer_supply beagle_vdda_dac_supply = { + .supply = "vdda_dac", + .dev = &beagle_dss_device.dev, +}; + +static struct regulator_consumer_supply beagle_vdds_dsi_supply = { + .supply = "vdds_dsi", + .dev = &beagle_dss_device.dev, +}; + +static void __init beagle_display_init(void) +{ + int r; + + r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset"); + if (r < 0) { + printk(KERN_ERR "Unable to get DVI reset GPIO\n"); + return; + } + + gpio_direction_output(beagle_dvi_device.reset_gpio, 0); +} + #include "sdram-micron-mt46h32m32lf-6.h" static struct omap_uart_config omap3_beagle_uart_config __initdata = { @@ -121,15 +209,6 @@ static struct twl4030_hsmmc_info mmc[] = { {} /* Terminator */ }; -static struct platform_device omap3_beagle_lcd_device = { - .name = "omap3beagle_lcd", - .id = -1, -}; - -static struct omap_lcd_config omap3_beagle_lcd_config __initdata = { - .ctrl_name = "internal", -}; - static struct regulator_consumer_supply beagle_vmmc1_supply = { .supply = "vmmc", }; @@ -180,16 +259,6 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = { .setup = beagle_twl_gpio_setup, }; -static struct regulator_consumer_supply beagle_vdac_supply = { - .supply = "vdac", - .dev = &omap3_beagle_lcd_device.dev, -}; - -static struct regulator_consumer_supply beagle_vdvi_supply = { - .supply = "vdvi", - .dev = &omap3_beagle_lcd_device.dev, -}; - /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ static struct regulator_init_data beagle_vmmc1 = { .constraints = { @@ -225,13 +294,14 @@ static struct regulator_init_data beagle_vdac = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, + .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdac_supply, + .consumer_supplies = &beagle_vdda_dac_supply, }; /* VPLL2 for digital video outputs */ @@ -246,7 +316,7 @@ static struct regulator_init_data beagle_vpll2 = { | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdvi_supply, + .consumer_supplies = &beagle_vdds_dsi_supply, }; static struct twl4030_platform_data beagle_twldata = { @@ -345,11 +415,10 @@ static struct platform_device keys_gpio = { static struct omap_board_config_kernel omap3_beagle_config[] __initdata = { { OMAP_TAG_UART, &omap3_beagle_uart_config }, - { OMAP_TAG_LCD, &omap3_beagle_lcd_config }, }; static struct platform_device *omap3_beagle_devices[] __initdata = { - &omap3_beagle_lcd_device, + &beagle_dss_device, &leds_gpio, &keys_gpio, }; @@ -402,13 +471,11 @@ static void __init omap3_beagle_init(void) omap_serial_init(); omap_cfg_reg(J25_34XX_GPIO170); - gpio_request(170, "DVI_nPD"); - /* REVISIT leave DVI powered down until it's needed ... */ - gpio_direction_output(170, true); usb_musb_init(); usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); omap3beagle_flash_init(); + beagle_display_init(); } static void __init omap3_beagle_map_io(void) -- 1.6.4 |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:17
|
This implements MIPI DPI interface. Signed-off-by: Tomi Valkeinen <tom...@no...> --- drivers/video/omap2/dss/dpi.c | 388 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 388 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/dss/dpi.c diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c new file mode 100644 index 0000000..b6543c8 --- /dev/null +++ b/drivers/video/omap2/dss/dpi.c @@ -0,0 +1,388 @@ +/* + * linux/drivers/video/omap2/dss/dpi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * Some code and ideas taken from drivers/video/omap/ driver + * by Imre Deak. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "DPI" + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/errno.h> + +#include <mach/board.h> +#include <mach/display.h> +#include <mach/cpu.h> + +#include "dss.h" + +static struct { + int update_enabled; +} dpi; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL +static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, + unsigned long *fck, int *lck_div, int *pck_div) +{ + struct dsi_clock_info cinfo; + int r; + + r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo); + if (r) + return r; + + r = dsi_pll_program(&cinfo); + if (r) + return r; + + dss_select_clk_source(0, 1); + + dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div); + + *fck = cinfo.dsi1_pll_fclk; + *lck_div = cinfo.lck_div; + *pck_div = cinfo.pck_div; + + return 0; +} +#else +static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, + unsigned long *fck, int *lck_div, int *pck_div) +{ + struct dispc_clock_info cinfo; + int r; + + r = dispc_calc_clock_div(is_tft, pck_req, &cinfo); + if (r) + return r; + + r = dispc_set_clock_div(&cinfo); + if (r) + return r; + + *fck = cinfo.fck; + *lck_div = cinfo.lck_div; + *pck_div = cinfo.pck_div; + + return 0; +} +#endif + +static int dpi_set_mode(struct omap_dss_device *dssdev) +{ + struct omap_video_timings *t = &dssdev->panel.timings; + int lck_div, pck_div; + unsigned long fck; + unsigned long pck; + bool is_tft; + int r = 0; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, + dssdev->panel.acb); + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); +#else + r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, + &fck, &lck_div, &pck_div); +#endif + if (r) + goto err0; + + pck = fck / lck_div / pck_div / 1000; + + if (pck != t->pixel_clock) { + DSSWARN("Could not find exact pixel clock. " + "Requested %d kHz, got %lu kHz\n", + t->pixel_clock, pck); + + t->pixel_clock = pck; + } + + dispc_set_lcd_timings(t); + +err0: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + return r; +} + +static int dpi_basic_init(struct omap_dss_device *dssdev) +{ + bool is_tft; + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); + dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : + OMAP_DSS_LCD_DISPLAY_STN); + dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); + + return 0; +} + +static int dpi_display_enable(struct omap_dss_device *dssdev) +{ + int r; + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("display already enabled\n"); + r = -EINVAL; + goto err1; + } + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + r = dpi_basic_init(dssdev); + if (r) + goto err2; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dss_clk_enable(DSS_CLK_FCK2); + r = dsi_pll_init(0, 1); + if (r) + goto err3; +#endif + r = dpi_set_mode(dssdev); + if (r) + goto err4; + + mdelay(2); + + dispc_enable_lcd_out(1); + + r = dssdev->driver->enable(dssdev); + if (r) + goto err5; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; + +err5: + dispc_enable_lcd_out(0); +err4: +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dsi_pll_uninit(); +err3: + dss_clk_disable(DSS_CLK_FCK2); +#endif +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +err1: + omap_dss_stop_device(dssdev); +err0: + return r; +} + +static int dpi_display_resume(struct omap_dss_device *dssdev); + +static void dpi_display_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) + return; + + if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + dpi_display_resume(dssdev); + + dssdev->driver->disable(dssdev); + + dispc_enable_lcd_out(0); + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + dss_select_clk_source(0, 0); + dsi_pll_uninit(); + dss_clk_disable(DSS_CLK_FCK2); +#endif + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + omap_dss_stop_device(dssdev); +} + +static int dpi_display_suspend(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EINVAL; + + DSSDBG("dpi_display_suspend\n"); + + if (dssdev->driver->suspend) + dssdev->driver->suspend(dssdev); + + dispc_enable_lcd_out(0); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + return 0; +} + +static int dpi_display_resume(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) + return -EINVAL; + + DSSDBG("dpi_display_resume\n"); + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dispc_enable_lcd_out(1); + + if (dssdev->driver->resume) + dssdev->driver->resume(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; +} + +static void dpi_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + DSSDBG("dpi_set_timings\n"); + dssdev->panel.timings = *timings; + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + dpi_set_mode(dssdev); + dispc_go(OMAP_DSS_CHANNEL_LCD); + } +} + +static int dpi_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + bool is_tft; + int r; + int lck_div, pck_div; + unsigned long fck; + unsigned long pck; + + if (!dispc_lcd_timings_ok(timings)) + return -EINVAL; + + if (timings->pixel_clock == 0) + return -EINVAL; + + is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; + +#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL + { + struct dsi_clock_info cinfo; + r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000, + &cinfo); + + if (r) + return r; + + fck = cinfo.dsi1_pll_fclk; + lck_div = cinfo.lck_div; + pck_div = cinfo.pck_div; + } +#else + { + struct dispc_clock_info cinfo; + r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000, + &cinfo); + + if (r) + return r; + + fck = cinfo.fck; + lck_div = cinfo.lck_div; + pck_div = cinfo.pck_div; + } +#endif + + pck = fck / lck_div / pck_div / 1000; + + timings->pixel_clock = pck; + + return 0; +} + +static void dpi_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static int dpi_display_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode == OMAP_DSS_UPDATE_MANUAL) + return -EINVAL; + + if (mode == OMAP_DSS_UPDATE_DISABLED) { + dispc_enable_lcd_out(0); + dpi.update_enabled = 0; + } else { + dispc_enable_lcd_out(1); + dpi.update_enabled = 1; + } + + return 0; +} + +static enum omap_dss_update_mode dpi_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO : + OMAP_DSS_UPDATE_DISABLED; +} + +int dpi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("init_display\n"); + + dssdev->enable = dpi_display_enable; + dssdev->disable = dpi_display_disable; + dssdev->suspend = dpi_display_suspend; + dssdev->resume = dpi_display_resume; + dssdev->set_timings = dpi_set_timings; + dssdev->check_timings = dpi_check_timings; + dssdev->get_timings = dpi_get_timings; + dssdev->set_update_mode = dpi_display_set_update_mode; + dssdev->get_update_mode = dpi_display_get_update_mode; + + return 0; +} + +int dpi_init(void) +{ + return 0; +} + +void dpi_exit(void) +{ +} + -- 1.6.4 |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:17
|
Signed-off-by: Tomi Valkeinen <tom...@no...> Acked-by: Tony Lindgren <to...@at...> --- arch/arm/configs/overo_defconfig | 265 ++++++++----------------------------- arch/arm/mach-omap2/board-overo.c | 149 +++++++++++++++++++-- 2 files changed, 196 insertions(+), 218 deletions(-) diff --git a/arch/arm/configs/overo_defconfig b/arch/arm/configs/overo_defconfig index a57f9e4..93d911c 100644 --- a/arch/arm/configs/overo_defconfig +++ b/arch/arm/configs/overo_defconfig @@ -994,225 +994,76 @@ CONFIG_SSB_POSSIBLE=y # # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set -# CONFIG_UCB1400_CORE is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -CONFIG_VIDEO_DEV=m -CONFIG_VIDEO_V4L2_COMMON=m -CONFIG_VIDEO_ALLOW_V4L1=y -CONFIG_VIDEO_V4L1_COMPAT=y -CONFIG_DVB_CORE=m -CONFIG_VIDEO_MEDIA=m - -# -# Multimedia drivers -# -CONFIG_MEDIA_ATTACH=y -CONFIG_MEDIA_TUNER=m -# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set -CONFIG_MEDIA_TUNER_SIMPLE=m -CONFIG_MEDIA_TUNER_TDA8290=m -CONFIG_MEDIA_TUNER_TDA827X=m -CONFIG_MEDIA_TUNER_TDA18271=m -CONFIG_MEDIA_TUNER_TDA9887=m -CONFIG_MEDIA_TUNER_TEA5761=m -CONFIG_MEDIA_TUNER_TEA5767=m -CONFIG_MEDIA_TUNER_MT20XX=m -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=m -CONFIG_MEDIA_TUNER_XC5000=m -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_VIDEO_V4L2=m -CONFIG_VIDEO_V4L1=m -CONFIG_VIDEO_TVEEPROM=m -CONFIG_VIDEO_TUNER=m -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -CONFIG_VIDEO_MSP3400=m -CONFIG_VIDEO_CS53L32A=m -CONFIG_VIDEO_WM8775=m -CONFIG_VIDEO_SAA711X=m -CONFIG_VIDEO_CX25840=m -CONFIG_VIDEO_CX2341X=m -# CONFIG_VIDEO_VIVI is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_CPIA2 is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_AU0828 is not set -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=m -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -# CONFIG_USB_GSPCA is not set -CONFIG_VIDEO_PVRUSB2=m -CONFIG_VIDEO_PVRUSB2_SYSFS=y -CONFIG_VIDEO_PVRUSB2_DVB=y -# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -# CONFIG_VIDEO_EM28XX is not set -CONFIG_VIDEO_USBVISION=m -CONFIG_VIDEO_USBVIDEO=m -CONFIG_USB_VICAM=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_QUICKCAM_MESSENGER=m -# CONFIG_USB_ET61X251 is not set -CONFIG_VIDEO_OVCAMCHIP=m -CONFIG_USB_W9968CF=m -CONFIG_USB_OV511=m -CONFIG_USB_SE401=m -CONFIG_USB_SN9C102=m -CONFIG_USB_STV680=m -# CONFIG_USB_ZC0301 is not set -CONFIG_USB_PWC=m -# CONFIG_USB_PWC_DEBUG is not set -CONFIG_USB_ZR364XX=m -# CONFIG_USB_STKWEBCAM is not set -# CONFIG_USB_S2255 is not set -# CONFIG_SOC_CAMERA is not set -# CONFIG_VIDEO_SH_MOBILE_CEU is not set -CONFIG_RADIO_ADAPTERS=y -# CONFIG_USB_DSBR is not set -# CONFIG_USB_SI470X is not set -CONFIG_DVB_CAPTURE_DRIVERS=y -# CONFIG_TTPCI_EEPROM is not set - -# -# Supported USB Adapters -# -CONFIG_DVB_USB=m -# CONFIG_DVB_USB_DEBUG is not set -CONFIG_DVB_USB_A800=m -CONFIG_DVB_USB_DIBUSB_MB=m -# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set -CONFIG_DVB_USB_DIBUSB_MC=m -CONFIG_DVB_USB_DIB0700=m -CONFIG_DVB_USB_UMT_010=m -CONFIG_DVB_USB_CXUSB=m -CONFIG_DVB_USB_M920X=m -CONFIG_DVB_USB_GL861=m -CONFIG_DVB_USB_AU6610=m -CONFIG_DVB_USB_DIGITV=m -CONFIG_DVB_USB_VP7045=m -CONFIG_DVB_USB_VP702X=m -CONFIG_DVB_USB_GP8PSK=m -CONFIG_DVB_USB_NOVA_T_USB2=m -CONFIG_DVB_USB_TTUSB2=m -CONFIG_DVB_USB_DTT200U=m -CONFIG_DVB_USB_OPERA1=m -CONFIG_DVB_USB_AF9005=m -CONFIG_DVB_USB_AF9005_REMOTE=m -# CONFIG_DVB_USB_DW2102 is not set -# CONFIG_DVB_USB_ANYSEE is not set -CONFIG_DVB_TTUSB_BUDGET=m -CONFIG_DVB_TTUSB_DEC=m -CONFIG_DVB_CINERGYT2=m -# CONFIG_DVB_CINERGYT2_TUNING is not set -# CONFIG_DVB_SIANO_SMS1XXX is not set - -# -# Supported FlexCopII (B2C2) Adapters -# -# CONFIG_DVB_B2C2_FLEXCOP is not set - -# -# Supported DVB Frontends -# - -# -# Customise DVB Frontends -# -# CONFIG_DVB_FE_CUSTOMISE is not set - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_CX24110=m -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -# CONFIG_DVB_DRX397XD is not set -CONFIG_DVB_L64781=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_ZL10353=m -CONFIG_DVB_DIB3000MB=m -CONFIG_DVB_DIB3000MC=m -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -CONFIG_DVB_NXT200X=m -# CONFIG_DVB_OR51211 is not set -# CONFIG_DVB_OR51132 is not set -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_AU8522=m -CONFIG_DVB_S5H1411=m - -# -# Digital terrestrial only tuners/PLL -# -CONFIG_DVB_PLL=m -CONFIG_DVB_TUNER_DIB0070=m - -# -# SEC control devices for DVB-S -# -CONFIG_DVB_LNBP21=m -# CONFIG_DVB_ISL6405 is not set -CONFIG_DVB_ISL6421=m -# CONFIG_DAB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MEDIA_SUPPORT is not set # # Graphics support # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=6 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=y +# CONFIG_PANEL_SHARP_LS037V7DW01 is not set +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set +CONFIG_FB_OMAP2_NUM_FBS=3 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 501d020..e0c6bbf 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -40,6 +40,7 @@ #include <mach/board.h> #include <mach/common.h> +#include <mach/display.h> #include <mach/gpio.h> #include <mach/gpmc.h> #include <mach/hardware.h> @@ -182,6 +183,110 @@ static inline void __init overo_init_smsc911x(void) static inline void __init overo_init_smsc911x(void) { return; } #endif +/* DSS */ +static int lcd_enabled; +static int dvi_enabled; + +#define OVERO_GPIO_LCD_EN 144 + +static void __init overo_display_init(void) +{ + int r; + + r = gpio_request(OVERO_GPIO_LCD_EN, "display enable"); + if (r) + pr_err("Failed to get LCD_EN gpio\n"); + r = gpio_direction_output(OVERO_GPIO_LCD_EN, 1); + if (r) + pr_err("Failed to set LCD_EN gpio direction\n"); + gpio_export(OVERO_GPIO_LCD_EN, 0); +} + +static int overo_panel_enable_dvi(struct omap_dss_device *dssdev) +{ + if (lcd_enabled) { + printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); + return -EINVAL; + } + dvi_enabled = 1; + + gpio_set_value(OVERO_GPIO_LCD_EN, 1); + + return 0; +} + +static void overo_panel_disable_dvi(struct omap_dss_device *dssdev) +{ + gpio_set_value(OVERO_GPIO_LCD_EN, 0); + + dvi_enabled = 0; +} + +static struct omap_dss_device overo_dvi_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "dvi", + .driver_name = "generic_panel", + .phy.dpi.data_lines = 24, + .platform_enable = overo_panel_enable_dvi, + .platform_disable = overo_panel_disable_dvi, +}; + +static int overo_panel_enable_lcd(struct omap_dss_device *dssdev) +{ + if (dvi_enabled) { + printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); + return -EINVAL; + } + + gpio_set_value(OVERO_GPIO_LCD_EN, 1); + lcd_enabled = 1; + return 0; +} + +static void overo_panel_disable_lcd(struct omap_dss_device *dssdev) +{ + gpio_set_value(OVERO_GPIO_LCD_EN, 0); + lcd_enabled = 0; +} + +static struct omap_dss_device overo_lcd_device = { + .type = OMAP_DISPLAY_TYPE_DPI, + .name = "lcd", + .driver_name = "samsung_lte_panel", + .phy.dpi.data_lines = 24, + .platform_enable = overo_panel_enable_lcd, + .platform_disable = overo_panel_disable_lcd, +}; + +static struct omap_dss_device *overo_dss_devices[] = { + &overo_dvi_device, + &overo_lcd_device, +}; + +static struct omap_dss_board_info overo_dss_data = { + .num_devices = ARRAY_SIZE(overo_dss_devices), + .devices = overo_dss_devices, + .default_device = &overo_dvi_device, +}; + +static struct platform_device overo_dss_device = { + .name = "omapdss", + .id = -1, + .dev = { + .platform_data = &overo_dss_data, + }, +}; + +static struct regulator_consumer_supply overo_vdda_dac_supply = { + .supply = "vdda_dac", + .dev = &overo_dss_device.dev, +}; + +static struct regulator_consumer_supply overo_vdds_dsi_supply = { + .supply = "vdds_dsi", + .dev = &overo_dss_device.dev, +}; + static struct mtd_partition overo_nand_partitions[] = { { .name = "xloader", @@ -231,7 +336,6 @@ static struct platform_device overo_nand_device = { .resource = &overo_nand_resource, }; - static void __init overo_flash_init(void) { u8 cs = 0; @@ -330,6 +434,35 @@ static struct regulator_init_data overo_vmmc1 = { .consumer_supplies = &overo_vmmc1_supply, }; +/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ +static struct regulator_init_data overo_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &overo_vdda_dac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data overo_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &overo_vdds_dsi_supply, +}; + /* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ static struct twl4030_platform_data overo_twldata = { @@ -338,6 +471,8 @@ static struct twl4030_platform_data overo_twldata = { .gpio = &overo_gpio_data, .usb = &overo_usb_data, .vmmc1 = &overo_vmmc1, + .vdac = &overo_vdac, + .vpll2 = &overo_vpll2, }; static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { @@ -365,22 +500,13 @@ static void __init overo_init_irq(void) omap_gpio_init(); } -static struct platform_device overo_lcd_device = { - .name = "overo_lcd", - .id = -1, -}; - -static struct omap_lcd_config overo_lcd_config __initdata = { - .ctrl_name = "internal", -}; static struct omap_board_config_kernel overo_config[] __initdata = { { OMAP_TAG_UART, &overo_uart_config }, - { OMAP_TAG_LCD, &overo_lcd_config }, }; static struct platform_device *overo_devices[] __initdata = { - &overo_lcd_device, + &overo_dss_device, }; static void __init overo_init(void) @@ -395,6 +521,7 @@ static void __init overo_init(void) usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, 183, -EINVAL); overo_ads7846_init(); overo_init_smsc911x(); + overo_display_init(); if ((gpio_request(OVERO_GPIO_W2W_NRESET, "OVERO_GPIO_W2W_NRESET") == 0) && -- 1.6.4 |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:15
|
SDI (Serial Display Interface) implements TI Flatlink 3G display interface. Signed-off-by: Tomi Valkeinen <tom...@no...> --- drivers/video/omap2/dss/sdi.c | 261 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 261 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/dss/sdi.c diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c new file mode 100644 index 0000000..a9c727e --- /dev/null +++ b/drivers/video/omap2/dss/sdi.c @@ -0,0 +1,261 @@ +/* + * linux/drivers/video/omap2/dss/sdi.c + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "SDI" + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> + +#include <mach/board.h> +#include <mach/display.h> +#include "dss.h" + +static struct { + bool skip_init; + bool update_enabled; +} sdi; + +static void sdi_basic_init(void) +{ + dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); + + dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); + dispc_set_tft_data_lines(24); + dispc_lcd_enable_signal_polarity(1); +} + +static int sdi_display_enable(struct omap_dss_device *dssdev) +{ + struct omap_video_timings *t = &dssdev->panel.timings; + struct dispc_clock_info cinfo; + u16 lck_div, pck_div; + unsigned long fck; + unsigned long pck; + int r; + + r = omap_dss_start_device(dssdev); + if (r) { + DSSERR("failed to start device\n"); + goto err0; + } + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR("dssdev already enabled\n"); + r = -EINVAL; + goto err1; + } + + /* In case of skip_init sdi_init has already enabled the clocks */ + if (!sdi.skip_init) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + sdi_basic_init(); + + /* 15.5.9.1.2 */ + dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; + + dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, + dssdev->panel.acb); + + if (!sdi.skip_init) + r = dispc_calc_clock_div(1, t->pixel_clock * 1000, + &cinfo); + else + r = dispc_get_clock_div(&cinfo); + + if (r) + goto err2; + + fck = cinfo.fck; + lck_div = cinfo.lck_div; + pck_div = cinfo.pck_div; + + pck = fck / lck_div / pck_div / 1000; + + if (pck != t->pixel_clock) { + DSSWARN("Could not find exact pixel clock. Requested %d kHz, " + "got %lu kHz\n", + t->pixel_clock, pck); + + t->pixel_clock = pck; + } + + + dispc_set_lcd_timings(t); + + r = dispc_set_clock_div(&cinfo); + if (r) + goto err2; + + if (!sdi.skip_init) { + dss_sdi_init(dssdev->phy.sdi.datapairs); + dss_sdi_enable(); + mdelay(2); + } + + dispc_enable_lcd_out(1); + + if (dssdev->driver->enable) { + r = dssdev->driver->enable(dssdev); + if (r) + goto err3; + } + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + sdi.skip_init = 0; + + return 0; +err3: + dispc_enable_lcd_out(0); +err2: + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); +err1: + omap_dss_stop_device(dssdev); +err0: + return r; +} + +static int sdi_display_resume(struct omap_dss_device *dssdev); + +static void sdi_display_disable(struct omap_dss_device *dssdev) +{ + if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) + return; + + if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) + sdi_display_resume(dssdev); + + if (dssdev->driver->disable) + dssdev->driver->disable(dssdev); + + dispc_enable_lcd_out(0); + + dss_sdi_disable(); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + omap_dss_stop_device(dssdev); +} + +static int sdi_display_suspend(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) + return -EINVAL; + + if (dssdev->driver->suspend) + dssdev->driver->suspend(dssdev); + + dispc_enable_lcd_out(0); + + dss_sdi_disable(); + + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + + return 0; +} + +static int sdi_display_resume(struct omap_dss_device *dssdev) +{ + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) + return -EINVAL; + + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + + dss_sdi_enable(); + mdelay(2); + + dispc_enable_lcd_out(1); + + if (dssdev->driver->resume) + dssdev->driver->resume(dssdev); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + return 0; +} + +static int sdi_display_set_update_mode(struct omap_dss_device *dssdev, + enum omap_dss_update_mode mode) +{ + if (mode == OMAP_DSS_UPDATE_MANUAL) + return -EINVAL; + + if (mode == OMAP_DSS_UPDATE_DISABLED) { + dispc_enable_lcd_out(0); + sdi.update_enabled = 0; + } else { + dispc_enable_lcd_out(1); + sdi.update_enabled = 1; + } + + return 0; +} + +static enum omap_dss_update_mode sdi_display_get_update_mode( + struct omap_dss_device *dssdev) +{ + return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO : + OMAP_DSS_UPDATE_DISABLED; +} + +static void sdi_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +int sdi_init_display(struct omap_dss_device *dssdev) +{ + DSSDBG("SDI init\n"); + + dssdev->enable = sdi_display_enable; + dssdev->disable = sdi_display_disable; + dssdev->suspend = sdi_display_suspend; + dssdev->resume = sdi_display_resume; + dssdev->set_update_mode = sdi_display_set_update_mode; + dssdev->get_update_mode = sdi_display_get_update_mode; + dssdev->get_timings = sdi_get_timings; + + return 0; +} + +int sdi_init(bool skip_init) +{ + /* we store this for first display enable, then clear it */ + sdi.skip_init = skip_init; + + /* + * Enable clocks already here, otherwise there would be a toggle + * of them until sdi_display_enable is called. + */ + if (skip_init) + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); + return 0; +} + +void sdi_exit(void) +{ +} -- 1.6.4 |
From: Tomi V. <tom...@no...> - 2009-08-07 12:29:15
|
Signed-off-by: Tomi Valkeinen <tom...@no...> --- drivers/video/omap2/displays/Kconfig | 6 + drivers/video/omap2/displays/Makefile | 2 + drivers/video/omap2/displays/panel-taal.c | 900 +++++++++++++++++++++++++++++ 3 files changed, 908 insertions(+), 0 deletions(-) create mode 100644 drivers/video/omap2/displays/panel-taal.c diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 396905d..79d2861 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -19,4 +19,10 @@ config PANEL_SHARP_LS037V7DW01 help LCD Panel used in TI's SDP3430 and EVM boards +config PANEL_TAAL + tristate "Taal DSI Panel" + depends on OMAP2_DSS_DSI + help + Taal DSI command mode panel from TPO. + endmenu diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index a26bbd2..d44e765 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o + +obj-$(CONFIG_PANEL_TAAL) += panel-taal.o diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c new file mode 100644 index 0000000..84f0d47 --- /dev/null +++ b/drivers/video/omap2/displays/panel-taal.c @@ -0,0 +1,900 @@ +/* + * Taal DSI command mode panel + * + * Copyright (C) 2009 Nokia Corporation + * Author: Tomi Valkeinen <tom...@no...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/*#define DEBUG*/ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/jiffies.h> +#include <linux/sched.h> +#include <linux/backlight.h> +#include <linux/fb.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/completion.h> + +#include <mach/display.h> + +/* DSI Virtual channel. Hardcoded for now. */ +#define TCH 0 + +#define DCS_READ_NUM_ERRORS 0x05 +#define DCS_READ_POWER_MODE 0x0a +#define DCS_READ_MADCTL 0x0b +#define DCS_READ_PIXEL_FORMAT 0x0c +#define DCS_SLEEP_IN 0x10 +#define DCS_SLEEP_OUT 0x11 +#define DCS_DISPLAY_OFF 0x28 +#define DCS_DISPLAY_ON 0x29 +#define DCS_COLUMN_ADDR 0x2a +#define DCS_PAGE_ADDR 0x2b +#define DCS_MEMORY_WRITE 0x2c +#define DCS_TEAR_OFF 0x34 +#define DCS_TEAR_ON 0x35 +#define DCS_MEM_ACC_CTRL 0x36 +#define DCS_PIXEL_FORMAT 0x3a +#define DCS_BRIGHTNESS 0x51 +#define DCS_CTRL_DISPLAY 0x53 +#define DCS_WRITE_CABC 0x55 +#define DCS_READ_CABC 0x56 +#define DCS_GET_ID1 0xda +#define DCS_GET_ID2 0xdb +#define DCS_GET_ID3 0xdc + +struct taal_data { + struct backlight_device *bldev; + + unsigned long hw_guard_end; /* next value of jiffies when we can + * issue the next sleep in/out command + */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + + struct omap_dss_device *dssdev; + + bool enabled; + u8 rotate; + bool mirror; + + bool te_enabled; + bool use_ext_te; + struct completion te_completion; + + bool use_dsi_bl; + + bool cabc_broken; + unsigned cabc_mode; + + bool intro_printed; +}; + +static void hw_guard_start(struct taal_data *td, int guard_msec) +{ + td->hw_guard_wait = msecs_to_jiffies(guard_msec); + td->hw_guard_end = jiffies + td->hw_guard_wait; +} + +static void hw_guard_wait(struct taal_data *td) +{ + unsigned long wait = td->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= td->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) +{ + int r; + u8 buf[1]; + + r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); + + if (r < 0) + return r; + + *data = buf[0]; + + return 0; +} + +static int taal_dcs_write_0(u8 dcs_cmd) +{ + return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); +} + +static int taal_dcs_write_1(u8 dcs_cmd, u8 param) +{ + u8 buf[2]; + buf[0] = dcs_cmd; + buf[1] = param; + return dsi_vc_dcs_write(TCH, buf, 2); +} + +static int taal_sleep_in(struct taal_data *td) + +{ + u8 cmd; + int r; + + hw_guard_wait(td); + + cmd = DCS_SLEEP_IN; + r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); + if (r) + return r; + + hw_guard_start(td, 120); + + msleep(5); + + return 0; +} + +static int taal_sleep_out(struct taal_data *td) +{ + int r; + + hw_guard_wait(td); + + r = taal_dcs_write_0(DCS_SLEEP_OUT); + if (r) + return r; + + hw_guard_start(td, 120); + + msleep(5); + + return 0; +} + +static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) +{ + int r; + + r = taal_dcs_read_1(DCS_GET_ID1, id1); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID2, id2); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID3, id3); + if (r) + return r; + + return 0; +} + +static int taal_set_addr_mode(u8 rotate, bool mirror) +{ + int r; + u8 mode; + int b5, b6, b7; + + r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); + if (r) + return r; + + switch (rotate) { + default: + case 0: + b7 = 0; + b6 = 0; + b5 = 0; + break; + case 1: + b7 = 0; + b6 = 1; + b5 = 1; + break; + case 2: + b7 = 1; + b6 = 1; + b5 = 0; + break; + case 3: + b7 = 1; + b6 = 0; + b5 = 1; + break; + } + + if (mirror) + b6 = !b6; + + mode &= ~((1<<7) | (1<<6) | (1<<5)); + mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); + + return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); +} + +static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) +{ + int r; + u16 x1 = x; + u16 x2 = x + w - 1; + u16 y1 = y; + u16 y2 = y + h - 1; + + u8 buf[5]; + buf[0] = DCS_COLUMN_ADDR; + buf[1] = (x1 >> 8) & 0xff; + buf[2] = (x1 >> 0) & 0xff; + buf[3] = (x2 >> 8) & 0xff; + buf[4] = (x2 >> 0) & 0xff; + + r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + if (r) + return r; + + buf[0] = DCS_PAGE_ADDR; + buf[1] = (y1 >> 8) & 0xff; + buf[2] = (y1 >> 0) & 0xff; + buf[3] = (y2 >> 8) & 0xff; + buf[4] = (y2 >> 0) & 0xff; + + r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); + if (r) + return r; + + dsi_vc_send_bta_sync(TCH); + + return r; +} + +static int taal_bl_update_status(struct backlight_device *dev) +{ + struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + int level; + + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) + level = dev->props.brightness; + else + level = 0; + + dev_dbg(&dssdev->dev, "update brightness to %d\n", level); + + if (td->use_dsi_bl) { + if (td->enabled) { + dsi_bus_lock(); + r = taal_dcs_write_1(DCS_BRIGHTNESS, level); + dsi_bus_unlock(); + if (r) + return r; + } + } else { + if (!dssdev->set_backlight) + return -EINVAL; + + r = dssdev->set_backlight(dssdev, level); + if (r) + return r; + } + + return 0; +} + +static int taal_bl_get_intensity(struct backlight_device *dev) +{ + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) + return dev->props.brightness; + + return 0; +} + +static struct backlight_ops taal_bl_ops = { + .get_brightness = taal_bl_get_intensity, + .update_status = taal_bl_update_status, +}; + +static void taal_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static void taal_get_resolution(struct omap_dss_device *dssdev, + u16 *xres, u16 *yres) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + if (td->rotate == 0 || td->rotate == 2) { + *xres = dssdev->panel.timings.x_res; + *yres = dssdev->panel.timings.y_res; + } else { + *yres = dssdev->panel.timings.x_res; + *xres = dssdev->panel.timings.y_res; + } +} + +static irqreturn_t taal_te_isr(int irq, void *data) +{ + struct omap_dss_device *dssdev = data; + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + complete_all(&td->te_completion); + + return IRQ_HANDLED; +} + +static ssize_t taal_num_errors_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 errors; + int r; + + if (td->enabled) { + dsi_bus_lock(); + r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); + dsi_bus_unlock(); + } else { + r = -ENODEV; + } + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", errors); +} + +static ssize_t taal_hw_revision_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 id1, id2, id3; + int r; + + if (td->enabled) { + dsi_bus_lock(); + r = taal_get_id(&id1, &id2, &id3); + dsi_bus_unlock(); + } else { + r = -ENODEV; + } + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3); +} + +static const char *cabc_modes[] = { + "off", /* used also always when CABC is not supported */ + "ui", + "still-image", + "moving-image", +}; + +static ssize_t show_cabc_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + const char *mode_str; + int mode; + int len; + + mode = td->cabc_mode; + + mode_str = "unknown"; + if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) + mode_str = cabc_modes[mode]; + len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); + + return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; +} + +static ssize_t store_cabc_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct omap_dss_device *dssdev = to_dss_device(dev); + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int i; + + for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { + if (sysfs_streq(cabc_modes[i], buf)) + break; + } + + if (i == ARRAY_SIZE(cabc_modes)) + return -EINVAL; + + if (td->enabled) { + dsi_bus_lock(); + if (!td->cabc_broken) + taal_dcs_write_1(DCS_WRITE_CABC, i); + dsi_bus_unlock(); + } + + td->cabc_mode = i; + + return count; +} + +static ssize_t show_cabc_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int len; + int i; + + for (i = 0, len = 0; + len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) + len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", + i ? " " : "", cabc_modes[i], + i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); + + return len < PAGE_SIZE ? len : PAGE_SIZE - 1; +} + +static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); +static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); +static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, + show_cabc_mode, store_cabc_mode); +static DEVICE_ATTR(cabc_available_modes, S_IRUGO, + show_cabc_available_modes, NULL); + +static struct attribute *taal_attrs[] = { + &dev_attr_num_dsi_errors.attr, + &dev_attr_hw_revision.attr, + &dev_attr_cabc_mode.attr, + &dev_attr_cabc_available_modes.attr, + NULL, +}; + +static struct attribute_group taal_attr_group = { + .attrs = taal_attrs, +}; + +static int taal_probe(struct omap_dss_device *dssdev) +{ + struct taal_data *td; + struct backlight_device *bldev; + int r; + + const struct omap_video_timings taal_panel_timings = { + .x_res = 864, + .y_res = 480, + }; + + dev_dbg(&dssdev->dev, "probe\n"); + + dssdev->panel.config = OMAP_DSS_LCD_TFT; + dssdev->panel.timings = taal_panel_timings; + dssdev->ctrl.pixel_size = 24; + + td = kzalloc(sizeof(*td), GFP_KERNEL); + if (!td) { + r = -ENOMEM; + goto err0; + } + + dev_set_drvdata(&dssdev->dev, td); + + dssdev->get_timings = taal_get_timings; + dssdev->get_resolution = taal_get_resolution; + + /* if no platform set_backlight() defined, presume DSI backlight + * control */ + if (!dssdev->set_backlight) + td->use_dsi_bl = true; + + bldev = backlight_device_register("taal", &dssdev->dev, dssdev, + &taal_bl_ops); + if (IS_ERR(bldev)) { + r = PTR_ERR(bldev); + goto err1; + } + + td->bldev = bldev; + + bldev->props.fb_blank = FB_BLANK_UNBLANK; + bldev->props.power = FB_BLANK_UNBLANK; + if (td->use_dsi_bl) { + bldev->props.max_brightness = 255; + bldev->props.brightness = 255; + } else { + bldev->props.max_brightness = 127; + bldev->props.brightness = 127; + } + + taal_bl_update_status(bldev); + + if (dssdev->phy.dsi.ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + + r = gpio_request(gpio, "taal irq"); + if (r) { + dev_err(&dssdev->dev, "GPIO request failed\n"); + goto err2; + } + + gpio_direction_input(gpio); + + r = request_irq(gpio_to_irq(gpio), taal_te_isr, + IRQF_DISABLED | IRQF_TRIGGER_RISING, + "taal vsync", dssdev); + + if (r) { + dev_err(&dssdev->dev, "IRQ request failed\n"); + gpio_free(gpio); + goto err2; + } + + init_completion(&td->te_completion); + + td->use_ext_te = true; + } + + r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); + if (r) { + dev_err(&dssdev->dev, "failed to create sysfs files\n"); + goto err3; + } + + return 0; +err3: + if (td->use_ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + free_irq(gpio_to_irq(gpio), dssdev); + gpio_free(gpio); + } +err2: + backlight_device_unregister(bldev); +err1: + kfree(td); +err0: + return r; +} + +static void taal_remove(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev; + + dev_dbg(&dssdev->dev, "remove\n"); + + sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); + + if (td->use_ext_te) { + int gpio = dssdev->phy.dsi.ext_te_gpio; + free_irq(gpio_to_irq(gpio), dssdev); + gpio_free(gpio); + } + + bldev = td->bldev; + bldev->props.power = FB_BLANK_POWERDOWN; + taal_bl_update_status(bldev); + backlight_device_unregister(bldev); + + kfree(td); +} + +static int taal_enable(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + u8 id1, id2, id3; + int r; + + dev_dbg(&dssdev->dev, "enable\n"); + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) + return r; + } + + /* it seems we have to wait a bit until taal is ready */ + msleep(5); + + r = taal_sleep_out(td); + if (r) + return r; + + r = taal_get_id(&id1, &id2, &id3); + if (r) + return r; + + /* on early revisions CABC is broken */ + if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) + td->cabc_broken = true; + + taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); + taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ + + taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ + + taal_set_addr_mode(td->rotate, td->mirror); + if (!td->cabc_broken) + taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); + + taal_dcs_write_0(DCS_DISPLAY_ON); + + td->enabled = 1; + + if (!td->intro_printed) { + dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", + id1, id2, id3); + if (td->cabc_broken) + dev_info(&dssdev->dev, + "old Taal version, CABC disabled\n"); + td->intro_printed = true; + } + + return 0; +} + +static void taal_disable(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + + dev_dbg(&dssdev->dev, "disable\n"); + + taal_dcs_write_0(DCS_DISPLAY_OFF); + taal_sleep_in(td); + + /* wait a bit so that the message goes through */ + msleep(10); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + td->enabled = 0; +} + +static int taal_suspend(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev = td->bldev; + + bldev->props.power = FB_BLANK_POWERDOWN; + taal_bl_update_status(bldev); + + return 0; +} + +static int taal_resume(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bldev = td->bldev; + + bldev->props.power = FB_BLANK_UNBLANK; + taal_bl_update_status(bldev); + + return 0; +} + +static void taal_setup_update(struct omap_dss_device *dssdev, + u16 x, u16 y, u16 w, u16 h) +{ + taal_set_update_window(x, y, w, h); +} + +static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + td->te_enabled = enable; + + if (enable) + r = taal_dcs_write_1(DCS_TEAR_ON, 0); + else + r = taal_dcs_write_0(DCS_TEAR_OFF); + + return r; +} + +static int taal_wait_te(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + long wait = msecs_to_jiffies(500); + + if (!td->use_ext_te || !td->te_enabled) + return 0; + + INIT_COMPLETION(td->te_completion); + wait = wait_for_completion_timeout(&td->te_completion, wait); + if (wait == 0) { + dev_err(&dssdev->dev, "timeout waiting TE\n"); + return -ETIME; + } + + return 0; +} + +static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + dev_dbg(&dssdev->dev, "rotate %d\n", rotate); + + if (td->enabled) { + r = taal_set_addr_mode(rotate, td->mirror); + + if (r) + return r; + } + + td->rotate = rotate; + + return 0; +} + +static u8 taal_get_rotate(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + return td->rotate; +} + +static int taal_mirror(struct omap_dss_device *dssdev, bool enable) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + + dev_dbg(&dssdev->dev, "mirror %d\n", enable); + + if (td->enabled) { + r = taal_set_addr_mode(td->rotate, enable); + + if (r) + return r; + } + + td->mirror = enable; + + return 0; +} + +static bool taal_get_mirror(struct omap_dss_device *dssdev) +{ + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + return td->mirror; +} + +static int taal_run_test(struct omap_dss_device *dssdev, int test_num) +{ + u8 id1, id2, id3; + int r; + + r = taal_dcs_read_1(DCS_GET_ID1, &id1); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID2, &id2); + if (r) + return r; + r = taal_dcs_read_1(DCS_GET_ID3, &id3); + if (r) + return r; + + return 0; +} + +static int taal_memory_read(struct omap_dss_device *dssdev, + void *buf, size_t size, + u16 x, u16 y, u16 w, u16 h) +{ + int r; + int first = 1; + int plen; + unsigned buf_used = 0; + + if (size < w * h * 3) + return -ENOMEM; + + size = min(w * h * 3, + dssdev->panel.timings.x_res * + dssdev->panel.timings.y_res * 3); + + /* plen 1 or 2 goes into short packet. until checksum error is fixed, + * use short packets. plen 32 works, but bigger packets seem to cause + * an error. */ + if (size % 2) + plen = 1; + else + plen = 2; + + taal_setup_update(dssdev, x, y, w, h); + + r = dsi_vc_set_max_rx_packet_size(TCH, plen); + if (r) + return r; + + while (buf_used < size) { + u8 dcs_cmd = first ? 0x2e : 0x3e; + first = 0; + + r = dsi_vc_dcs_read(TCH, dcs_cmd, + buf + buf_used, size - buf_used); + + if (r < 0) { + dev_err(&dssdev->dev, "read error\n"); + goto err; + } + + buf_used += r; + + if (r < plen) { + dev_err(&dssdev->dev, "short read\n"); + break; + } + } + + r = buf_used; + +err: + dsi_vc_set_max_rx_packet_size(TCH, 1); + + return r; +} + +static struct omap_dss_driver taal_driver = { + .probe = taal_probe, + .remove = taal_remove, + + .enable = taal_enable, + .disable = taal_disable, + .suspend = taal_suspend, + .resume = taal_resume, + + .setup_update = taal_setup_update, + .enable_te = taal_enable_te, + .wait_for_te = taal_wait_te, + .set_rotate = taal_rotate, + .get_rotate = taal_get_rotate, + .set_mirror = taal_mirror, + .get_mirror = taal_get_mirror, + .run_test = taal_run_test, + .memory_read = taal_memory_read, + + .driver = { + .name = "taal", + .owner = THIS_MODULE, + }, +}; + +static int __init taal_init(void) +{ + omap_dss_register_driver(&taal_driver); + + return 0; +} + +static void __exit taal_exit(void) +{ + omap_dss_unregister_driver(&taal_driver); +} + +module_init(taal_init); +module_exit(taal_exit); + +MODULE_AUTHOR("Tomi Valkeinen <tom...@no...>"); +MODULE_DESCRIPTION("Taal Driver"); +MODULE_LICENSE("GPL"); -- 1.6.4 |