diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-08-10 07:22:08 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-08-10 07:22:08 -0400 |
commit | fb8231a8b139035476f2a8aaac837d0099b66dad (patch) | |
tree | 2875806beb96ea0cdab292146767a5085721dc6a /drivers/video | |
parent | 426d31071ac476ea62c62656b242930c17b58c00 (diff) | |
parent | f6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff) |
Merge branch 'master' into for-next
Conflicts:
arch/arm/mach-omap1/board-nokia770.c
Diffstat (limited to 'drivers/video')
48 files changed, 2696 insertions, 1752 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3d94a1471724..a9ca72f301bf 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1505,7 +1505,7 @@ config FB_SIS_315 | |||
1505 | 1505 | ||
1506 | config FB_VIA | 1506 | config FB_VIA |
1507 | tristate "VIA UniChrome (Pro) and Chrome9 display support" | 1507 | tristate "VIA UniChrome (Pro) and Chrome9 display support" |
1508 | depends on FB && PCI | 1508 | depends on FB && PCI && X86 |
1509 | select FB_CFB_FILLRECT | 1509 | select FB_CFB_FILLRECT |
1510 | select FB_CFB_COPYAREA | 1510 | select FB_CFB_COPYAREA |
1511 | select FB_CFB_IMAGEBLIT | 1511 | select FB_CFB_IMAGEBLIT |
@@ -1871,6 +1871,7 @@ config FB_MBX_DEBUG | |||
1871 | config FB_FSL_DIU | 1871 | config FB_FSL_DIU |
1872 | tristate "Freescale DIU framebuffer support" | 1872 | tristate "Freescale DIU framebuffer support" |
1873 | depends on FB && FSL_SOC | 1873 | depends on FB && FSL_SOC |
1874 | select FB_MODE_HELPERS | ||
1874 | select FB_CFB_FILLRECT | 1875 | select FB_CFB_FILLRECT |
1875 | select FB_CFB_COPYAREA | 1876 | select FB_CFB_COPYAREA |
1876 | select FB_CFB_IMAGEBLIT | 1877 | select FB_CFB_IMAGEBLIT |
@@ -2229,6 +2230,15 @@ config FB_BROADSHEET | |||
2229 | and could also have been called by other names when coupled with | 2230 | and could also have been called by other names when coupled with |
2230 | a bridge adapter. | 2231 | a bridge adapter. |
2231 | 2232 | ||
2233 | config FB_JZ4740 | ||
2234 | tristate "JZ4740 LCD framebuffer support" | ||
2235 | depends on FB && MACH_JZ4740 | ||
2236 | select FB_SYS_FILLRECT | ||
2237 | select FB_SYS_COPYAREA | ||
2238 | select FB_SYS_IMAGEBLIT | ||
2239 | help | ||
2240 | Framebuffer support for the JZ4740 SoC. | ||
2241 | |||
2232 | source "drivers/video/omap/Kconfig" | 2242 | source "drivers/video/omap/Kconfig" |
2233 | source "drivers/video/omap2/Kconfig" | 2243 | source "drivers/video/omap2/Kconfig" |
2234 | 2244 | ||
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ddc2af2ba45b..f56a9cae2157 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -131,6 +131,7 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o | |||
131 | obj-$(CONFIG_FB_MB862XX) += mb862xx/ | 131 | obj-$(CONFIG_FB_MB862XX) += mb862xx/ |
132 | obj-$(CONFIG_FB_MSM) += msm/ | 132 | obj-$(CONFIG_FB_MSM) += msm/ |
133 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o | 133 | obj-$(CONFIG_FB_NUC900) += nuc900fb.o |
134 | obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o | ||
134 | 135 | ||
135 | # Platform or fallback drivers go here | 136 | # Platform or fallback drivers go here |
136 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 137 | obj-$(CONFIG_FB_UVESA) += uvesafb.o |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 09f1b9b462f4..c7796637bafd 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
@@ -390,12 +390,12 @@ static int __init bw2_init(void) | |||
390 | if (fb_get_options("bw2fb", NULL)) | 390 | if (fb_get_options("bw2fb", NULL)) |
391 | return -ENODEV; | 391 | return -ENODEV; |
392 | 392 | ||
393 | return of_register_driver(&bw2_driver, &of_bus_type); | 393 | return of_register_platform_driver(&bw2_driver); |
394 | } | 394 | } |
395 | 395 | ||
396 | static void __exit bw2_exit(void) | 396 | static void __exit bw2_exit(void) |
397 | { | 397 | { |
398 | of_unregister_driver(&bw2_driver); | 398 | of_unregister_platform_driver(&bw2_driver); |
399 | } | 399 | } |
400 | 400 | ||
401 | module_init(bw2_init); | 401 | module_init(bw2_init); |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index e5dc2241194f..d09fde8beb69 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -610,12 +610,12 @@ static int __init cg14_init(void) | |||
610 | if (fb_get_options("cg14fb", NULL)) | 610 | if (fb_get_options("cg14fb", NULL)) |
611 | return -ENODEV; | 611 | return -ENODEV; |
612 | 612 | ||
613 | return of_register_driver(&cg14_driver, &of_bus_type); | 613 | return of_register_platform_driver(&cg14_driver); |
614 | } | 614 | } |
615 | 615 | ||
616 | static void __exit cg14_exit(void) | 616 | static void __exit cg14_exit(void) |
617 | { | 617 | { |
618 | of_unregister_driver(&cg14_driver); | 618 | of_unregister_platform_driver(&cg14_driver); |
619 | } | 619 | } |
620 | 620 | ||
621 | module_init(cg14_init); | 621 | module_init(cg14_init); |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 558d73a948a0..64aa29809fb9 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
@@ -477,12 +477,12 @@ static int __init cg3_init(void) | |||
477 | if (fb_get_options("cg3fb", NULL)) | 477 | if (fb_get_options("cg3fb", NULL)) |
478 | return -ENODEV; | 478 | return -ENODEV; |
479 | 479 | ||
480 | return of_register_driver(&cg3_driver, &of_bus_type); | 480 | return of_register_platform_driver(&cg3_driver); |
481 | } | 481 | } |
482 | 482 | ||
483 | static void __exit cg3_exit(void) | 483 | static void __exit cg3_exit(void) |
484 | { | 484 | { |
485 | of_unregister_driver(&cg3_driver); | 485 | of_unregister_platform_driver(&cg3_driver); |
486 | } | 486 | } |
487 | 487 | ||
488 | module_init(cg3_init); | 488 | module_init(cg3_init); |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 480d761a27a8..2389a719dcc7 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -870,12 +870,12 @@ static int __init cg6_init(void) | |||
870 | if (fb_get_options("cg6fb", NULL)) | 870 | if (fb_get_options("cg6fb", NULL)) |
871 | return -ENODEV; | 871 | return -ENODEV; |
872 | 872 | ||
873 | return of_register_driver(&cg6_driver, &of_bus_type); | 873 | return of_register_platform_driver(&cg6_driver); |
874 | } | 874 | } |
875 | 875 | ||
876 | static void __exit cg6_exit(void) | 876 | static void __exit cg6_exit(void) |
877 | { | 877 | { |
878 | of_unregister_driver(&cg6_driver); | 878 | of_unregister_platform_driver(&cg6_driver); |
879 | } | 879 | } |
880 | 880 | ||
881 | module_init(cg6_init); | 881 | module_init(cg6_init); |
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 8e8f18d29d7a..5a35f22372b9 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Console display driver support" | |||
6 | 6 | ||
7 | config VGA_CONSOLE | 7 | config VGA_CONSOLE |
8 | bool "VGA text console" if EMBEDDED || !X86 | 8 | bool "VGA text console" if EMBEDDED || !X86 |
9 | depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 | 9 | depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) |
10 | default y | 10 | default y |
11 | help | 11 | help |
12 | Saying Y here will allow you to use Linux in text mode through a | 12 | Saying Y here will allow you to use Linux in text mode through a |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b0a3fa00706d..3b3f5749af92 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -2342,6 +2342,30 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) | |||
2342 | return 0; | 2342 | return 0; |
2343 | } | 2343 | } |
2344 | 2344 | ||
2345 | static int fbcon_debug_enter(struct vc_data *vc) | ||
2346 | { | ||
2347 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | ||
2348 | struct fbcon_ops *ops = info->fbcon_par; | ||
2349 | |||
2350 | ops->save_graphics = ops->graphics; | ||
2351 | ops->graphics = 0; | ||
2352 | if (info->fbops->fb_debug_enter) | ||
2353 | info->fbops->fb_debug_enter(info); | ||
2354 | fbcon_set_palette(vc, color_table); | ||
2355 | return 0; | ||
2356 | } | ||
2357 | |||
2358 | static int fbcon_debug_leave(struct vc_data *vc) | ||
2359 | { | ||
2360 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | ||
2361 | struct fbcon_ops *ops = info->fbcon_par; | ||
2362 | |||
2363 | ops->graphics = ops->save_graphics; | ||
2364 | if (info->fbops->fb_debug_leave) | ||
2365 | info->fbops->fb_debug_leave(info); | ||
2366 | return 0; | ||
2367 | } | ||
2368 | |||
2345 | static int fbcon_get_font(struct vc_data *vc, struct console_font *font) | 2369 | static int fbcon_get_font(struct vc_data *vc, struct console_font *font) |
2346 | { | 2370 | { |
2347 | u8 *fontdata = vc->vc_font.data; | 2371 | u8 *fontdata = vc->vc_font.data; |
@@ -3276,6 +3300,8 @@ static const struct consw fb_con = { | |||
3276 | .con_screen_pos = fbcon_screen_pos, | 3300 | .con_screen_pos = fbcon_screen_pos, |
3277 | .con_getxy = fbcon_getxy, | 3301 | .con_getxy = fbcon_getxy, |
3278 | .con_resize = fbcon_resize, | 3302 | .con_resize = fbcon_resize, |
3303 | .con_debug_enter = fbcon_debug_enter, | ||
3304 | .con_debug_leave = fbcon_debug_leave, | ||
3279 | }; | 3305 | }; |
3280 | 3306 | ||
3281 | static struct notifier_block fbcon_event_notifier = { | 3307 | static struct notifier_block fbcon_event_notifier = { |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 89a346880ec0..6bd2e0c7f209 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -74,6 +74,7 @@ struct fbcon_ops { | |||
74 | int cursor_reset; | 74 | int cursor_reset; |
75 | int blank_state; | 75 | int blank_state; |
76 | int graphics; | 76 | int graphics; |
77 | int save_graphics; /* for debug enter/leave */ | ||
77 | int flags; | 78 | int flags; |
78 | int rotate; | 79 | int rotate; |
79 | int cur_rotate; | 80 | int cur_rotate; |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 49fcbe8f18ac..c225dcce89e7 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include <linux/vmalloc.h> | 40 | #include <linux/vmalloc.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/of.h> | ||
44 | #include <linux/of_address.h> | ||
43 | #include <linux/fb.h> | 45 | #include <linux/fb.h> |
44 | #include <linux/init.h> | 46 | #include <linux/init.h> |
45 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 95c0227f47fc..f6ecfab296d3 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -1067,12 +1067,12 @@ static int __init ffb_init(void) | |||
1067 | if (fb_get_options("ffb", NULL)) | 1067 | if (fb_get_options("ffb", NULL)) |
1068 | return -ENODEV; | 1068 | return -ENODEV; |
1069 | 1069 | ||
1070 | return of_register_driver(&ffb_driver, &of_bus_type); | 1070 | return of_register_platform_driver(&ffb_driver); |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | static void __exit ffb_exit(void) | 1073 | static void __exit ffb_exit(void) |
1074 | { | 1074 | { |
1075 | of_unregister_driver(&ffb_driver); | 1075 | of_unregister_platform_driver(&ffb_driver); |
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | module_init(ffb_init); | 1078 | module_init(ffb_init); |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 27455ce298b7..e38ad2224540 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -34,7 +34,8 @@ | |||
34 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
35 | 35 | ||
36 | #include <sysdev/fsl_soc.h> | 36 | #include <sysdev/fsl_soc.h> |
37 | #include "fsl-diu-fb.h" | 37 | #include <linux/fsl-diu-fb.h> |
38 | #include "edid.h" | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * These parameters give default parameters | 41 | * These parameters give default parameters |
@@ -217,6 +218,7 @@ struct mfb_info { | |||
217 | int x_aoi_d; /* aoi display x offset to physical screen */ | 218 | int x_aoi_d; /* aoi display x offset to physical screen */ |
218 | int y_aoi_d; /* aoi display y offset to physical screen */ | 219 | int y_aoi_d; /* aoi display y offset to physical screen */ |
219 | struct fsl_diu_data *parent; | 220 | struct fsl_diu_data *parent; |
221 | u8 *edid_data; | ||
220 | }; | 222 | }; |
221 | 223 | ||
222 | 224 | ||
@@ -317,6 +319,17 @@ static void fsl_diu_free(void *virt, size_t size) | |||
317 | free_pages_exact(virt, size); | 319 | free_pages_exact(virt, size); |
318 | } | 320 | } |
319 | 321 | ||
322 | /* | ||
323 | * Workaround for failed writing desc register of planes. | ||
324 | * Needed with MPC5121 DIU rev 2.0 silicon. | ||
325 | */ | ||
326 | void wr_reg_wa(u32 *reg, u32 val) | ||
327 | { | ||
328 | do { | ||
329 | out_be32(reg, val); | ||
330 | } while (in_be32(reg) != val); | ||
331 | } | ||
332 | |||
320 | static int fsl_diu_enable_panel(struct fb_info *info) | 333 | static int fsl_diu_enable_panel(struct fb_info *info) |
321 | { | 334 | { |
322 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 335 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
@@ -330,7 +343,7 @@ static int fsl_diu_enable_panel(struct fb_info *info) | |||
330 | switch (mfbi->index) { | 343 | switch (mfbi->index) { |
331 | case 0: /* plane 0 */ | 344 | case 0: /* plane 0 */ |
332 | if (hw->desc[0] != ad->paddr) | 345 | if (hw->desc[0] != ad->paddr) |
333 | out_be32(&hw->desc[0], ad->paddr); | 346 | wr_reg_wa(&hw->desc[0], ad->paddr); |
334 | break; | 347 | break; |
335 | case 1: /* plane 1 AOI 0 */ | 348 | case 1: /* plane 1 AOI 0 */ |
336 | cmfbi = machine_data->fsl_diu_info[2]->par; | 349 | cmfbi = machine_data->fsl_diu_info[2]->par; |
@@ -340,7 +353,7 @@ static int fsl_diu_enable_panel(struct fb_info *info) | |||
340 | cpu_to_le32(cmfbi->ad->paddr); | 353 | cpu_to_le32(cmfbi->ad->paddr); |
341 | else | 354 | else |
342 | ad->next_ad = 0; | 355 | ad->next_ad = 0; |
343 | out_be32(&hw->desc[1], ad->paddr); | 356 | wr_reg_wa(&hw->desc[1], ad->paddr); |
344 | } | 357 | } |
345 | break; | 358 | break; |
346 | case 3: /* plane 2 AOI 0 */ | 359 | case 3: /* plane 2 AOI 0 */ |
@@ -351,14 +364,14 @@ static int fsl_diu_enable_panel(struct fb_info *info) | |||
351 | cpu_to_le32(cmfbi->ad->paddr); | 364 | cpu_to_le32(cmfbi->ad->paddr); |
352 | else | 365 | else |
353 | ad->next_ad = 0; | 366 | ad->next_ad = 0; |
354 | out_be32(&hw->desc[2], ad->paddr); | 367 | wr_reg_wa(&hw->desc[2], ad->paddr); |
355 | } | 368 | } |
356 | break; | 369 | break; |
357 | case 2: /* plane 1 AOI 1 */ | 370 | case 2: /* plane 1 AOI 1 */ |
358 | pmfbi = machine_data->fsl_diu_info[1]->par; | 371 | pmfbi = machine_data->fsl_diu_info[1]->par; |
359 | ad->next_ad = 0; | 372 | ad->next_ad = 0; |
360 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | 373 | if (hw->desc[1] == machine_data->dummy_ad->paddr) |
361 | out_be32(&hw->desc[1], ad->paddr); | 374 | wr_reg_wa(&hw->desc[1], ad->paddr); |
362 | else /* AOI0 open */ | 375 | else /* AOI0 open */ |
363 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | 376 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); |
364 | break; | 377 | break; |
@@ -366,7 +379,7 @@ static int fsl_diu_enable_panel(struct fb_info *info) | |||
366 | pmfbi = machine_data->fsl_diu_info[3]->par; | 379 | pmfbi = machine_data->fsl_diu_info[3]->par; |
367 | ad->next_ad = 0; | 380 | ad->next_ad = 0; |
368 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | 381 | if (hw->desc[2] == machine_data->dummy_ad->paddr) |
369 | out_be32(&hw->desc[2], ad->paddr); | 382 | wr_reg_wa(&hw->desc[2], ad->paddr); |
370 | else /* AOI0 was open */ | 383 | else /* AOI0 was open */ |
371 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | 384 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); |
372 | break; | 385 | break; |
@@ -390,27 +403,24 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
390 | switch (mfbi->index) { | 403 | switch (mfbi->index) { |
391 | case 0: /* plane 0 */ | 404 | case 0: /* plane 0 */ |
392 | if (hw->desc[0] != machine_data->dummy_ad->paddr) | 405 | if (hw->desc[0] != machine_data->dummy_ad->paddr) |
393 | out_be32(&hw->desc[0], | 406 | wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); |
394 | machine_data->dummy_ad->paddr); | ||
395 | break; | 407 | break; |
396 | case 1: /* plane 1 AOI 0 */ | 408 | case 1: /* plane 1 AOI 0 */ |
397 | cmfbi = machine_data->fsl_diu_info[2]->par; | 409 | cmfbi = machine_data->fsl_diu_info[2]->par; |
398 | if (cmfbi->count > 0) /* AOI1 is open */ | 410 | if (cmfbi->count > 0) /* AOI1 is open */ |
399 | out_be32(&hw->desc[1], cmfbi->ad->paddr); | 411 | wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); |
400 | /* move AOI1 to the first */ | 412 | /* move AOI1 to the first */ |
401 | else /* AOI1 was closed */ | 413 | else /* AOI1 was closed */ |
402 | out_be32(&hw->desc[1], | 414 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
403 | machine_data->dummy_ad->paddr); | ||
404 | /* close AOI 0 */ | 415 | /* close AOI 0 */ |
405 | break; | 416 | break; |
406 | case 3: /* plane 2 AOI 0 */ | 417 | case 3: /* plane 2 AOI 0 */ |
407 | cmfbi = machine_data->fsl_diu_info[4]->par; | 418 | cmfbi = machine_data->fsl_diu_info[4]->par; |
408 | if (cmfbi->count > 0) /* AOI1 is open */ | 419 | if (cmfbi->count > 0) /* AOI1 is open */ |
409 | out_be32(&hw->desc[2], cmfbi->ad->paddr); | 420 | wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); |
410 | /* move AOI1 to the first */ | 421 | /* move AOI1 to the first */ |
411 | else /* AOI1 was closed */ | 422 | else /* AOI1 was closed */ |
412 | out_be32(&hw->desc[2], | 423 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
413 | machine_data->dummy_ad->paddr); | ||
414 | /* close AOI 0 */ | 424 | /* close AOI 0 */ |
415 | break; | 425 | break; |
416 | case 2: /* plane 1 AOI 1 */ | 426 | case 2: /* plane 1 AOI 1 */ |
@@ -421,7 +431,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
421 | /* AOI0 is open, must be the first */ | 431 | /* AOI0 is open, must be the first */ |
422 | pmfbi->ad->next_ad = 0; | 432 | pmfbi->ad->next_ad = 0; |
423 | } else /* AOI1 is the first in the chain */ | 433 | } else /* AOI1 is the first in the chain */ |
424 | out_be32(&hw->desc[1], machine_data->dummy_ad->paddr); | 434 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
425 | /* close AOI 1 */ | 435 | /* close AOI 1 */ |
426 | break; | 436 | break; |
427 | case 4: /* plane 2 AOI 1 */ | 437 | case 4: /* plane 2 AOI 1 */ |
@@ -432,7 +442,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
432 | /* AOI0 is open, must be the first */ | 442 | /* AOI0 is open, must be the first */ |
433 | pmfbi->ad->next_ad = 0; | 443 | pmfbi->ad->next_ad = 0; |
434 | } else /* AOI1 is the first in the chain */ | 444 | } else /* AOI1 is the first in the chain */ |
435 | out_be32(&hw->desc[2], machine_data->dummy_ad->paddr); | 445 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
436 | /* close AOI 1 */ | 446 | /* close AOI 1 */ |
437 | break; | 447 | break; |
438 | default: | 448 | default: |
@@ -1100,6 +1110,10 @@ static int fsl_diu_open(struct fb_info *info, int user) | |||
1100 | struct mfb_info *mfbi = info->par; | 1110 | struct mfb_info *mfbi = info->par; |
1101 | int res = 0; | 1111 | int res = 0; |
1102 | 1112 | ||
1113 | /* free boot splash memory on first /dev/fb0 open */ | ||
1114 | if (!mfbi->index && diu_ops.release_bootmem) | ||
1115 | diu_ops.release_bootmem(); | ||
1116 | |||
1103 | spin_lock(&diu_lock); | 1117 | spin_lock(&diu_lock); |
1104 | mfbi->count++; | 1118 | mfbi->count++; |
1105 | if (mfbi->count == 1) { | 1119 | if (mfbi->count == 1) { |
@@ -1173,18 +1187,30 @@ static int __devinit install_fb(struct fb_info *info) | |||
1173 | int rc; | 1187 | int rc; |
1174 | struct mfb_info *mfbi = info->par; | 1188 | struct mfb_info *mfbi = info->par; |
1175 | const char *aoi_mode, *init_aoi_mode = "320x240"; | 1189 | const char *aoi_mode, *init_aoi_mode = "320x240"; |
1190 | struct fb_videomode *db = fsl_diu_mode_db; | ||
1191 | unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); | ||
1192 | int has_default_mode = 1; | ||
1176 | 1193 | ||
1177 | if (init_fbinfo(info)) | 1194 | if (init_fbinfo(info)) |
1178 | return -EINVAL; | 1195 | return -EINVAL; |
1179 | 1196 | ||
1180 | if (mfbi->index == 0) /* plane 0 */ | 1197 | if (mfbi->index == 0) { /* plane 0 */ |
1198 | if (mfbi->edid_data) { | ||
1199 | /* Now build modedb from EDID */ | ||
1200 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); | ||
1201 | fb_videomode_to_modelist(info->monspecs.modedb, | ||
1202 | info->monspecs.modedb_len, | ||
1203 | &info->modelist); | ||
1204 | db = info->monspecs.modedb; | ||
1205 | dbsize = info->monspecs.modedb_len; | ||
1206 | } | ||
1181 | aoi_mode = fb_mode; | 1207 | aoi_mode = fb_mode; |
1182 | else | 1208 | } else { |
1183 | aoi_mode = init_aoi_mode; | 1209 | aoi_mode = init_aoi_mode; |
1210 | } | ||
1184 | pr_debug("mode used = %s\n", aoi_mode); | 1211 | pr_debug("mode used = %s\n", aoi_mode); |
1185 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, | 1212 | rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, |
1186 | ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp); | 1213 | &fsl_diu_default_mode, default_bpp); |
1187 | |||
1188 | switch (rc) { | 1214 | switch (rc) { |
1189 | case 1: | 1215 | case 1: |
1190 | pr_debug("using mode specified in @mode\n"); | 1216 | pr_debug("using mode specified in @mode\n"); |
@@ -1202,10 +1228,50 @@ static int __devinit install_fb(struct fb_info *info) | |||
1202 | default: | 1228 | default: |
1203 | pr_debug("rc = %d\n", rc); | 1229 | pr_debug("rc = %d\n", rc); |
1204 | pr_debug("failed to find mode\n"); | 1230 | pr_debug("failed to find mode\n"); |
1205 | return -EINVAL; | 1231 | /* |
1232 | * For plane 0 we continue and look into | ||
1233 | * driver's internal modedb. | ||
1234 | */ | ||
1235 | if (mfbi->index == 0 && mfbi->edid_data) | ||
1236 | has_default_mode = 0; | ||
1237 | else | ||
1238 | return -EINVAL; | ||
1206 | break; | 1239 | break; |
1207 | } | 1240 | } |
1208 | 1241 | ||
1242 | if (!has_default_mode) { | ||
1243 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, | ||
1244 | ARRAY_SIZE(fsl_diu_mode_db), | ||
1245 | &fsl_diu_default_mode, | ||
1246 | default_bpp); | ||
1247 | if (rc > 0 && rc < 5) | ||
1248 | has_default_mode = 1; | ||
1249 | } | ||
1250 | |||
1251 | /* Still not found, use preferred mode from database if any */ | ||
1252 | if (!has_default_mode && info->monspecs.modedb) { | ||
1253 | struct fb_monspecs *specs = &info->monspecs; | ||
1254 | struct fb_videomode *modedb = &specs->modedb[0]; | ||
1255 | |||
1256 | /* | ||
1257 | * Get preferred timing. If not found, | ||
1258 | * first mode in database will be used. | ||
1259 | */ | ||
1260 | if (specs->misc & FB_MISC_1ST_DETAIL) { | ||
1261 | int i; | ||
1262 | |||
1263 | for (i = 0; i < specs->modedb_len; i++) { | ||
1264 | if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { | ||
1265 | modedb = &specs->modedb[i]; | ||
1266 | break; | ||
1267 | } | ||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | info->var.bits_per_pixel = default_bpp; | ||
1272 | fb_videomode_to_var(&info->var, modedb); | ||
1273 | } | ||
1274 | |||
1209 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); | 1275 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); |
1210 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); | 1276 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); |
1211 | 1277 | ||
@@ -1244,6 +1310,9 @@ static void uninstall_fb(struct fb_info *info) | |||
1244 | if (!mfbi->registered) | 1310 | if (!mfbi->registered) |
1245 | return; | 1311 | return; |
1246 | 1312 | ||
1313 | if (mfbi->index == 0) | ||
1314 | kfree(mfbi->edid_data); | ||
1315 | |||
1247 | unregister_framebuffer(info); | 1316 | unregister_framebuffer(info); |
1248 | unmap_video_memory(info); | 1317 | unmap_video_memory(info); |
1249 | if (&info->cmap) | 1318 | if (&info->cmap) |
@@ -1427,6 +1496,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev, | |||
1427 | int ret, i, error = 0; | 1496 | int ret, i, error = 0; |
1428 | struct resource res; | 1497 | struct resource res; |
1429 | struct fsl_diu_data *machine_data; | 1498 | struct fsl_diu_data *machine_data; |
1499 | int diu_mode; | ||
1430 | 1500 | ||
1431 | machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); | 1501 | machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); |
1432 | if (!machine_data) | 1502 | if (!machine_data) |
@@ -1443,6 +1513,17 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev, | |||
1443 | mfbi = machine_data->fsl_diu_info[i]->par; | 1513 | mfbi = machine_data->fsl_diu_info[i]->par; |
1444 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1514 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
1445 | mfbi->parent = machine_data; | 1515 | mfbi->parent = machine_data; |
1516 | |||
1517 | if (mfbi->index == 0) { | ||
1518 | const u8 *prop; | ||
1519 | int len; | ||
1520 | |||
1521 | /* Get EDID */ | ||
1522 | prop = of_get_property(np, "edid", &len); | ||
1523 | if (prop && len == EDID_LENGTH) | ||
1524 | mfbi->edid_data = kmemdup(prop, EDID_LENGTH, | ||
1525 | GFP_KERNEL); | ||
1526 | } | ||
1446 | } | 1527 | } |
1447 | 1528 | ||
1448 | ret = of_address_to_resource(np, 0, &res); | 1529 | ret = of_address_to_resource(np, 0, &res); |
@@ -1463,7 +1544,9 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev, | |||
1463 | goto error2; | 1544 | goto error2; |
1464 | } | 1545 | } |
1465 | 1546 | ||
1466 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/ | 1547 | diu_mode = in_be32(&dr.diu_reg->diu_mode); |
1548 | if (diu_mode != MFB_MODE1) | ||
1549 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */ | ||
1467 | 1550 | ||
1468 | /* Get the IRQ of the DIU */ | 1551 | /* Get the IRQ of the DIU */ |
1469 | machine_data->irq = irq_of_parse_and_map(np, 0); | 1552 | machine_data->irq = irq_of_parse_and_map(np, 0); |
@@ -1511,7 +1594,13 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev, | |||
1511 | machine_data->dummy_ad->offset_xyd = 0; | 1594 | machine_data->dummy_ad->offset_xyd = 0; |
1512 | machine_data->dummy_ad->next_ad = 0; | 1595 | machine_data->dummy_ad->next_ad = 0; |
1513 | 1596 | ||
1514 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); | 1597 | /* |
1598 | * Let DIU display splash screen if it was pre-initialized | ||
1599 | * by the bootloader, set dummy area descriptor otherwise. | ||
1600 | */ | ||
1601 | if (diu_mode != MFB_MODE1) | ||
1602 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); | ||
1603 | |||
1515 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); | 1604 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); |
1516 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); | 1605 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); |
1517 | 1606 | ||
diff --git a/drivers/video/fsl-diu-fb.h b/drivers/video/fsl-diu-fb.h deleted file mode 100644 index fc295d7ea463..000000000000 --- a/drivers/video/fsl-diu-fb.h +++ /dev/null | |||
@@ -1,223 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * Freescale DIU Frame Buffer device driver | ||
5 | * | ||
6 | * Authors: Hongjun Chen <hong-jun.chen@freescale.com> | ||
7 | * Paul Widmer <paul.widmer@freescale.com> | ||
8 | * Srikanth Srinivasan <srikanth.srinivasan@freescale.com> | ||
9 | * York Sun <yorksun@freescale.com> | ||
10 | * | ||
11 | * Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #ifndef __FSL_DIU_FB_H__ | ||
21 | #define __FSL_DIU_FB_H__ | ||
22 | |||
23 | /* Arbitrary threshold to determine the allocation method | ||
24 | * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory() | ||
25 | */ | ||
26 | #define MEM_ALLOC_THRESHOLD (1024*768*4+32) | ||
27 | /* Minimum value that the pixel clock can be set to in pico seconds | ||
28 | * This is determined by platform clock/3 where the minimum platform | ||
29 | * clock is 533MHz. This gives 5629 pico seconds. | ||
30 | */ | ||
31 | #define MIN_PIX_CLK 5629 | ||
32 | #define MAX_PIX_CLK 96096 | ||
33 | |||
34 | #include <linux/types.h> | ||
35 | |||
36 | struct mfb_alpha { | ||
37 | int enable; | ||
38 | int alpha; | ||
39 | }; | ||
40 | |||
41 | struct mfb_chroma_key { | ||
42 | int enable; | ||
43 | __u8 red_max; | ||
44 | __u8 green_max; | ||
45 | __u8 blue_max; | ||
46 | __u8 red_min; | ||
47 | __u8 green_min; | ||
48 | __u8 blue_min; | ||
49 | }; | ||
50 | |||
51 | struct aoi_display_offset { | ||
52 | int x_aoi_d; | ||
53 | int y_aoi_d; | ||
54 | }; | ||
55 | |||
56 | #define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key) | ||
57 | #define MFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t) | ||
58 | #define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8) | ||
59 | |||
60 | #define MFB_SET_ALPHA 0x80014d00 | ||
61 | #define MFB_GET_ALPHA 0x40014d00 | ||
62 | #define MFB_SET_AOID 0x80084d04 | ||
63 | #define MFB_GET_AOID 0x40084d04 | ||
64 | #define MFB_SET_PIXFMT 0x80014d08 | ||
65 | #define MFB_GET_PIXFMT 0x40014d08 | ||
66 | |||
67 | #define FBIOGET_GWINFO 0x46E0 | ||
68 | #define FBIOPUT_GWINFO 0x46E1 | ||
69 | |||
70 | #ifdef __KERNEL__ | ||
71 | #include <linux/spinlock.h> | ||
72 | |||
73 | /* | ||
74 | * These are the fields of area descriptor(in DDR memory) for every plane | ||
75 | */ | ||
76 | struct diu_ad { | ||
77 | /* Word 0(32-bit) in DDR memory */ | ||
78 | /* __u16 comp; */ | ||
79 | /* __u16 pixel_s:2; */ | ||
80 | /* __u16 pallete:1; */ | ||
81 | /* __u16 red_c:2; */ | ||
82 | /* __u16 green_c:2; */ | ||
83 | /* __u16 blue_c:2; */ | ||
84 | /* __u16 alpha_c:3; */ | ||
85 | /* __u16 byte_f:1; */ | ||
86 | /* __u16 res0:3; */ | ||
87 | |||
88 | __be32 pix_fmt; /* hard coding pixel format */ | ||
89 | |||
90 | /* Word 1(32-bit) in DDR memory */ | ||
91 | __le32 addr; | ||
92 | |||
93 | /* Word 2(32-bit) in DDR memory */ | ||
94 | /* __u32 delta_xs:11; */ | ||
95 | /* __u32 res1:1; */ | ||
96 | /* __u32 delta_ys:11; */ | ||
97 | /* __u32 res2:1; */ | ||
98 | /* __u32 g_alpha:8; */ | ||
99 | __le32 src_size_g_alpha; | ||
100 | |||
101 | /* Word 3(32-bit) in DDR memory */ | ||
102 | /* __u32 delta_xi:11; */ | ||
103 | /* __u32 res3:5; */ | ||
104 | /* __u32 delta_yi:11; */ | ||
105 | /* __u32 res4:3; */ | ||
106 | /* __u32 flip:2; */ | ||
107 | __le32 aoi_size; | ||
108 | |||
109 | /* Word 4(32-bit) in DDR memory */ | ||
110 | /*__u32 offset_xi:11; | ||
111 | __u32 res5:5; | ||
112 | __u32 offset_yi:11; | ||
113 | __u32 res6:5; | ||
114 | */ | ||
115 | __le32 offset_xyi; | ||
116 | |||
117 | /* Word 5(32-bit) in DDR memory */ | ||
118 | /*__u32 offset_xd:11; | ||
119 | __u32 res7:5; | ||
120 | __u32 offset_yd:11; | ||
121 | __u32 res8:5; */ | ||
122 | __le32 offset_xyd; | ||
123 | |||
124 | |||
125 | /* Word 6(32-bit) in DDR memory */ | ||
126 | __u8 ckmax_r; | ||
127 | __u8 ckmax_g; | ||
128 | __u8 ckmax_b; | ||
129 | __u8 res9; | ||
130 | |||
131 | /* Word 7(32-bit) in DDR memory */ | ||
132 | __u8 ckmin_r; | ||
133 | __u8 ckmin_g; | ||
134 | __u8 ckmin_b; | ||
135 | __u8 res10; | ||
136 | /* __u32 res10:8; */ | ||
137 | |||
138 | /* Word 8(32-bit) in DDR memory */ | ||
139 | __le32 next_ad; | ||
140 | |||
141 | /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */ | ||
142 | __u32 paddr; | ||
143 | } __attribute__ ((packed)); | ||
144 | |||
145 | /* DIU register map */ | ||
146 | struct diu { | ||
147 | __be32 desc[3]; | ||
148 | __be32 gamma; | ||
149 | __be32 pallete; | ||
150 | __be32 cursor; | ||
151 | __be32 curs_pos; | ||
152 | __be32 diu_mode; | ||
153 | __be32 bgnd; | ||
154 | __be32 bgnd_wb; | ||
155 | __be32 disp_size; | ||
156 | __be32 wb_size; | ||
157 | __be32 wb_mem_addr; | ||
158 | __be32 hsyn_para; | ||
159 | __be32 vsyn_para; | ||
160 | __be32 syn_pol; | ||
161 | __be32 thresholds; | ||
162 | __be32 int_status; | ||
163 | __be32 int_mask; | ||
164 | __be32 colorbar[8]; | ||
165 | __be32 filling; | ||
166 | __be32 plut; | ||
167 | } __attribute__ ((packed)); | ||
168 | |||
169 | struct diu_hw { | ||
170 | struct diu *diu_reg; | ||
171 | spinlock_t reg_lock; | ||
172 | |||
173 | __u32 mode; /* DIU operation mode */ | ||
174 | }; | ||
175 | |||
176 | struct diu_addr { | ||
177 | __u8 __iomem *vaddr; /* Virtual address */ | ||
178 | dma_addr_t paddr; /* Physical address */ | ||
179 | __u32 offset; | ||
180 | }; | ||
181 | |||
182 | struct diu_pool { | ||
183 | struct diu_addr ad; | ||
184 | struct diu_addr gamma; | ||
185 | struct diu_addr pallete; | ||
186 | struct diu_addr cursor; | ||
187 | }; | ||
188 | |||
189 | #define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of DIU */ | ||
190 | #define INT_LCDC 64 /* DIU interrupt number */ | ||
191 | |||
192 | #define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ | ||
193 | /* 1 for plane 0, 2 for plane 1&2 each */ | ||
194 | |||
195 | /* Minimum X and Y resolutions */ | ||
196 | #define MIN_XRES 64 | ||
197 | #define MIN_YRES 64 | ||
198 | |||
199 | /* HW cursor parameters */ | ||
200 | #define MAX_CURS 32 | ||
201 | |||
202 | /* Modes of operation of DIU */ | ||
203 | #define MFB_MODE0 0 /* DIU off */ | ||
204 | #define MFB_MODE1 1 /* All three planes output to display */ | ||
205 | #define MFB_MODE2 2 /* Plane 1 to display, planes 2+3 written back*/ | ||
206 | #define MFB_MODE3 3 /* All three planes written back to memory */ | ||
207 | #define MFB_MODE4 4 /* Color bar generation */ | ||
208 | |||
209 | /* INT_STATUS/INT_MASK field descriptions */ | ||
210 | #define INT_VSYNC 0x01 /* Vsync interrupt */ | ||
211 | #define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */ | ||
212 | #define INT_UNDRUN 0x04 /* Under run exception interrupt */ | ||
213 | #define INT_PARERR 0x08 /* Display parameters error interrupt */ | ||
214 | #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ | ||
215 | |||
216 | /* Panels'operation modes */ | ||
217 | #define MFB_TYPE_OUTPUT 0 /* Panel output to display */ | ||
218 | #define MFB_TYPE_OFF 1 /* Panel off */ | ||
219 | #define MFB_TYPE_WB 2 /* Panel written back to memory */ | ||
220 | #define MFB_TYPE_TEST 3 /* Panel generate color bar */ | ||
221 | |||
222 | #endif /* __KERNEL__ */ | ||
223 | #endif /* __FSL_DIU_FB_H__ */ | ||
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c new file mode 100644 index 000000000000..670ecaa0385a --- /dev/null +++ b/drivers/video/jz4740_fb.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 SoC LCD framebuffer driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | #include <linux/clk.h> | ||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #include <linux/console.h> | ||
25 | #include <linux/fb.h> | ||
26 | |||
27 | #include <linux/dma-mapping.h> | ||
28 | |||
29 | #include <asm/mach-jz4740/jz4740_fb.h> | ||
30 | #include <asm/mach-jz4740/gpio.h> | ||
31 | |||
32 | #define JZ_REG_LCD_CFG 0x00 | ||
33 | #define JZ_REG_LCD_VSYNC 0x04 | ||
34 | #define JZ_REG_LCD_HSYNC 0x08 | ||
35 | #define JZ_REG_LCD_VAT 0x0C | ||
36 | #define JZ_REG_LCD_DAH 0x10 | ||
37 | #define JZ_REG_LCD_DAV 0x14 | ||
38 | #define JZ_REG_LCD_PS 0x18 | ||
39 | #define JZ_REG_LCD_CLS 0x1C | ||
40 | #define JZ_REG_LCD_SPL 0x20 | ||
41 | #define JZ_REG_LCD_REV 0x24 | ||
42 | #define JZ_REG_LCD_CTRL 0x30 | ||
43 | #define JZ_REG_LCD_STATE 0x34 | ||
44 | #define JZ_REG_LCD_IID 0x38 | ||
45 | #define JZ_REG_LCD_DA0 0x40 | ||
46 | #define JZ_REG_LCD_SA0 0x44 | ||
47 | #define JZ_REG_LCD_FID0 0x48 | ||
48 | #define JZ_REG_LCD_CMD0 0x4C | ||
49 | #define JZ_REG_LCD_DA1 0x50 | ||
50 | #define JZ_REG_LCD_SA1 0x54 | ||
51 | #define JZ_REG_LCD_FID1 0x58 | ||
52 | #define JZ_REG_LCD_CMD1 0x5C | ||
53 | |||
54 | #define JZ_LCD_CFG_SLCD BIT(31) | ||
55 | #define JZ_LCD_CFG_PS_DISABLE BIT(23) | ||
56 | #define JZ_LCD_CFG_CLS_DISABLE BIT(22) | ||
57 | #define JZ_LCD_CFG_SPL_DISABLE BIT(21) | ||
58 | #define JZ_LCD_CFG_REV_DISABLE BIT(20) | ||
59 | #define JZ_LCD_CFG_HSYNCM BIT(19) | ||
60 | #define JZ_LCD_CFG_PCLKM BIT(18) | ||
61 | #define JZ_LCD_CFG_INV BIT(17) | ||
62 | #define JZ_LCD_CFG_SYNC_DIR BIT(16) | ||
63 | #define JZ_LCD_CFG_PS_POLARITY BIT(15) | ||
64 | #define JZ_LCD_CFG_CLS_POLARITY BIT(14) | ||
65 | #define JZ_LCD_CFG_SPL_POLARITY BIT(13) | ||
66 | #define JZ_LCD_CFG_REV_POLARITY BIT(12) | ||
67 | #define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11) | ||
68 | #define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10) | ||
69 | #define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9) | ||
70 | #define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8) | ||
71 | #define JZ_LCD_CFG_18_BIT BIT(7) | ||
72 | #define JZ_LCD_CFG_PDW (BIT(5) | BIT(4)) | ||
73 | #define JZ_LCD_CFG_MODE_MASK 0xf | ||
74 | |||
75 | #define JZ_LCD_CTRL_BURST_4 (0x0 << 28) | ||
76 | #define JZ_LCD_CTRL_BURST_8 (0x1 << 28) | ||
77 | #define JZ_LCD_CTRL_BURST_16 (0x2 << 28) | ||
78 | #define JZ_LCD_CTRL_RGB555 BIT(27) | ||
79 | #define JZ_LCD_CTRL_OFUP BIT(26) | ||
80 | #define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24) | ||
81 | #define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24) | ||
82 | #define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24) | ||
83 | #define JZ_LCD_CTRL_PDD_MASK (0xff << 16) | ||
84 | #define JZ_LCD_CTRL_EOF_IRQ BIT(13) | ||
85 | #define JZ_LCD_CTRL_SOF_IRQ BIT(12) | ||
86 | #define JZ_LCD_CTRL_OFU_IRQ BIT(11) | ||
87 | #define JZ_LCD_CTRL_IFU0_IRQ BIT(10) | ||
88 | #define JZ_LCD_CTRL_IFU1_IRQ BIT(9) | ||
89 | #define JZ_LCD_CTRL_DD_IRQ BIT(8) | ||
90 | #define JZ_LCD_CTRL_QDD_IRQ BIT(7) | ||
91 | #define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6) | ||
92 | #define JZ_LCD_CTRL_LSB_FISRT BIT(5) | ||
93 | #define JZ_LCD_CTRL_DISABLE BIT(4) | ||
94 | #define JZ_LCD_CTRL_ENABLE BIT(3) | ||
95 | #define JZ_LCD_CTRL_BPP_1 0x0 | ||
96 | #define JZ_LCD_CTRL_BPP_2 0x1 | ||
97 | #define JZ_LCD_CTRL_BPP_4 0x2 | ||
98 | #define JZ_LCD_CTRL_BPP_8 0x3 | ||
99 | #define JZ_LCD_CTRL_BPP_15_16 0x4 | ||
100 | #define JZ_LCD_CTRL_BPP_18_24 0x5 | ||
101 | |||
102 | #define JZ_LCD_CMD_SOF_IRQ BIT(15) | ||
103 | #define JZ_LCD_CMD_EOF_IRQ BIT(16) | ||
104 | #define JZ_LCD_CMD_ENABLE_PAL BIT(12) | ||
105 | |||
106 | #define JZ_LCD_SYNC_MASK 0x3ff | ||
107 | |||
108 | #define JZ_LCD_STATE_DISABLED BIT(0) | ||
109 | |||
110 | struct jzfb_framedesc { | ||
111 | uint32_t next; | ||
112 | uint32_t addr; | ||
113 | uint32_t id; | ||
114 | uint32_t cmd; | ||
115 | } __packed; | ||
116 | |||
117 | struct jzfb { | ||
118 | struct fb_info *fb; | ||
119 | struct platform_device *pdev; | ||
120 | void __iomem *base; | ||
121 | struct resource *mem; | ||
122 | struct jz4740_fb_platform_data *pdata; | ||
123 | |||
124 | size_t vidmem_size; | ||
125 | void *vidmem; | ||
126 | dma_addr_t vidmem_phys; | ||
127 | struct jzfb_framedesc *framedesc; | ||
128 | dma_addr_t framedesc_phys; | ||
129 | |||
130 | struct clk *ldclk; | ||
131 | struct clk *lpclk; | ||
132 | |||
133 | unsigned is_enabled:1; | ||
134 | struct mutex lock; | ||
135 | |||
136 | uint32_t pseudo_palette[16]; | ||
137 | }; | ||
138 | |||
139 | static const struct fb_fix_screeninfo jzfb_fix __devinitdata = { | ||
140 | .id = "JZ4740 FB", | ||
141 | .type = FB_TYPE_PACKED_PIXELS, | ||
142 | .visual = FB_VISUAL_TRUECOLOR, | ||
143 | .xpanstep = 0, | ||
144 | .ypanstep = 0, | ||
145 | .ywrapstep = 0, | ||
146 | .accel = FB_ACCEL_NONE, | ||
147 | }; | ||
148 | |||
149 | static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = { | ||
150 | JZ_GPIO_BULK_PIN(LCD_PCLK), | ||
151 | JZ_GPIO_BULK_PIN(LCD_HSYNC), | ||
152 | JZ_GPIO_BULK_PIN(LCD_VSYNC), | ||
153 | JZ_GPIO_BULK_PIN(LCD_DE), | ||
154 | JZ_GPIO_BULK_PIN(LCD_PS), | ||
155 | JZ_GPIO_BULK_PIN(LCD_REV), | ||
156 | JZ_GPIO_BULK_PIN(LCD_CLS), | ||
157 | JZ_GPIO_BULK_PIN(LCD_SPL), | ||
158 | }; | ||
159 | |||
160 | static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = { | ||
161 | JZ_GPIO_BULK_PIN(LCD_DATA0), | ||
162 | JZ_GPIO_BULK_PIN(LCD_DATA1), | ||
163 | JZ_GPIO_BULK_PIN(LCD_DATA2), | ||
164 | JZ_GPIO_BULK_PIN(LCD_DATA3), | ||
165 | JZ_GPIO_BULK_PIN(LCD_DATA4), | ||
166 | JZ_GPIO_BULK_PIN(LCD_DATA5), | ||
167 | JZ_GPIO_BULK_PIN(LCD_DATA6), | ||
168 | JZ_GPIO_BULK_PIN(LCD_DATA7), | ||
169 | JZ_GPIO_BULK_PIN(LCD_DATA8), | ||
170 | JZ_GPIO_BULK_PIN(LCD_DATA9), | ||
171 | JZ_GPIO_BULK_PIN(LCD_DATA10), | ||
172 | JZ_GPIO_BULK_PIN(LCD_DATA11), | ||
173 | JZ_GPIO_BULK_PIN(LCD_DATA12), | ||
174 | JZ_GPIO_BULK_PIN(LCD_DATA13), | ||
175 | JZ_GPIO_BULK_PIN(LCD_DATA14), | ||
176 | JZ_GPIO_BULK_PIN(LCD_DATA15), | ||
177 | JZ_GPIO_BULK_PIN(LCD_DATA16), | ||
178 | JZ_GPIO_BULK_PIN(LCD_DATA17), | ||
179 | }; | ||
180 | |||
181 | static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb) | ||
182 | { | ||
183 | unsigned int num; | ||
184 | |||
185 | switch (jzfb->pdata->lcd_type) { | ||
186 | case JZ_LCD_TYPE_GENERIC_16_BIT: | ||
187 | num = 4; | ||
188 | break; | ||
189 | case JZ_LCD_TYPE_GENERIC_18_BIT: | ||
190 | num = 4; | ||
191 | break; | ||
192 | case JZ_LCD_TYPE_8BIT_SERIAL: | ||
193 | num = 3; | ||
194 | break; | ||
195 | case JZ_LCD_TYPE_SPECIAL_TFT_1: | ||
196 | case JZ_LCD_TYPE_SPECIAL_TFT_2: | ||
197 | case JZ_LCD_TYPE_SPECIAL_TFT_3: | ||
198 | num = 8; | ||
199 | break; | ||
200 | default: | ||
201 | num = 0; | ||
202 | break; | ||
203 | } | ||
204 | return num; | ||
205 | } | ||
206 | |||
207 | static unsigned int jzfb_num_data_pins(struct jzfb *jzfb) | ||
208 | { | ||
209 | unsigned int num; | ||
210 | |||
211 | switch (jzfb->pdata->lcd_type) { | ||
212 | case JZ_LCD_TYPE_GENERIC_16_BIT: | ||
213 | num = 16; | ||
214 | break; | ||
215 | case JZ_LCD_TYPE_GENERIC_18_BIT: | ||
216 | num = 18; | ||
217 | break; | ||
218 | case JZ_LCD_TYPE_8BIT_SERIAL: | ||
219 | num = 8; | ||
220 | break; | ||
221 | case JZ_LCD_TYPE_SPECIAL_TFT_1: | ||
222 | case JZ_LCD_TYPE_SPECIAL_TFT_2: | ||
223 | case JZ_LCD_TYPE_SPECIAL_TFT_3: | ||
224 | if (jzfb->pdata->bpp == 18) | ||
225 | num = 18; | ||
226 | else | ||
227 | num = 16; | ||
228 | break; | ||
229 | default: | ||
230 | num = 0; | ||
231 | break; | ||
232 | } | ||
233 | return num; | ||
234 | } | ||
235 | |||
236 | /* Based on CNVT_TOHW macro from skeletonfb.c */ | ||
237 | static inline uint32_t jzfb_convert_color_to_hw(unsigned val, | ||
238 | struct fb_bitfield *bf) | ||
239 | { | ||
240 | return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset; | ||
241 | } | ||
242 | |||
243 | static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
244 | unsigned blue, unsigned transp, struct fb_info *fb) | ||
245 | { | ||
246 | uint32_t color; | ||
247 | |||
248 | if (regno >= 16) | ||
249 | return -EINVAL; | ||
250 | |||
251 | color = jzfb_convert_color_to_hw(red, &fb->var.red); | ||
252 | color |= jzfb_convert_color_to_hw(green, &fb->var.green); | ||
253 | color |= jzfb_convert_color_to_hw(blue, &fb->var.blue); | ||
254 | color |= jzfb_convert_color_to_hw(transp, &fb->var.transp); | ||
255 | |||
256 | ((uint32_t *)(fb->pseudo_palette))[regno] = color; | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int jzfb_get_controller_bpp(struct jzfb *jzfb) | ||
262 | { | ||
263 | switch (jzfb->pdata->bpp) { | ||
264 | case 18: | ||
265 | case 24: | ||
266 | return 32; | ||
267 | case 15: | ||
268 | return 16; | ||
269 | default: | ||
270 | return jzfb->pdata->bpp; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, | ||
275 | struct fb_var_screeninfo *var) | ||
276 | { | ||
277 | size_t i; | ||
278 | struct fb_videomode *mode = jzfb->pdata->modes; | ||
279 | |||
280 | for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) { | ||
281 | if (mode->xres == var->xres && mode->yres == var->yres) | ||
282 | return mode; | ||
283 | } | ||
284 | |||
285 | return NULL; | ||
286 | } | ||
287 | |||
288 | static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) | ||
289 | { | ||
290 | struct jzfb *jzfb = fb->par; | ||
291 | struct fb_videomode *mode; | ||
292 | |||
293 | if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) && | ||
294 | var->bits_per_pixel != jzfb->pdata->bpp) | ||
295 | return -EINVAL; | ||
296 | |||
297 | mode = jzfb_get_mode(jzfb, var); | ||
298 | if (mode == NULL) | ||
299 | return -EINVAL; | ||
300 | |||
301 | fb_videomode_to_var(var, mode); | ||
302 | |||
303 | switch (jzfb->pdata->bpp) { | ||
304 | case 8: | ||
305 | break; | ||
306 | case 15: | ||
307 | var->red.offset = 10; | ||
308 | var->red.length = 5; | ||
309 | var->green.offset = 6; | ||
310 | var->green.length = 5; | ||
311 | var->blue.offset = 0; | ||
312 | var->blue.length = 5; | ||
313 | break; | ||
314 | case 16: | ||
315 | var->red.offset = 11; | ||
316 | var->red.length = 5; | ||
317 | var->green.offset = 5; | ||
318 | var->green.length = 6; | ||
319 | var->blue.offset = 0; | ||
320 | var->blue.length = 5; | ||
321 | break; | ||
322 | case 18: | ||
323 | var->red.offset = 16; | ||
324 | var->red.length = 6; | ||
325 | var->green.offset = 8; | ||
326 | var->green.length = 6; | ||
327 | var->blue.offset = 0; | ||
328 | var->blue.length = 6; | ||
329 | var->bits_per_pixel = 32; | ||
330 | break; | ||
331 | case 32: | ||
332 | case 24: | ||
333 | var->transp.offset = 24; | ||
334 | var->transp.length = 8; | ||
335 | var->red.offset = 16; | ||
336 | var->red.length = 8; | ||
337 | var->green.offset = 8; | ||
338 | var->green.length = 8; | ||
339 | var->blue.offset = 0; | ||
340 | var->blue.length = 8; | ||
341 | var->bits_per_pixel = 32; | ||
342 | break; | ||
343 | default: | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int jzfb_set_par(struct fb_info *info) | ||
351 | { | ||
352 | struct jzfb *jzfb = info->par; | ||
353 | struct jz4740_fb_platform_data *pdata = jzfb->pdata; | ||
354 | struct fb_var_screeninfo *var = &info->var; | ||
355 | struct fb_videomode *mode; | ||
356 | uint16_t hds, vds; | ||
357 | uint16_t hde, vde; | ||
358 | uint16_t ht, vt; | ||
359 | uint32_t ctrl; | ||
360 | uint32_t cfg; | ||
361 | unsigned long rate; | ||
362 | |||
363 | mode = jzfb_get_mode(jzfb, var); | ||
364 | if (mode == NULL) | ||
365 | return -EINVAL; | ||
366 | |||
367 | if (mode == info->mode) | ||
368 | return 0; | ||
369 | |||
370 | info->mode = mode; | ||
371 | |||
372 | hds = mode->hsync_len + mode->left_margin; | ||
373 | hde = hds + mode->xres; | ||
374 | ht = hde + mode->right_margin; | ||
375 | |||
376 | vds = mode->vsync_len + mode->upper_margin; | ||
377 | vde = vds + mode->yres; | ||
378 | vt = vde + mode->lower_margin; | ||
379 | |||
380 | ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16; | ||
381 | |||
382 | switch (pdata->bpp) { | ||
383 | case 1: | ||
384 | ctrl |= JZ_LCD_CTRL_BPP_1; | ||
385 | break; | ||
386 | case 2: | ||
387 | ctrl |= JZ_LCD_CTRL_BPP_2; | ||
388 | break; | ||
389 | case 4: | ||
390 | ctrl |= JZ_LCD_CTRL_BPP_4; | ||
391 | break; | ||
392 | case 8: | ||
393 | ctrl |= JZ_LCD_CTRL_BPP_8; | ||
394 | break; | ||
395 | case 15: | ||
396 | ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */ | ||
397 | case 16: | ||
398 | ctrl |= JZ_LCD_CTRL_BPP_15_16; | ||
399 | break; | ||
400 | case 18: | ||
401 | case 24: | ||
402 | case 32: | ||
403 | ctrl |= JZ_LCD_CTRL_BPP_18_24; | ||
404 | break; | ||
405 | default: | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | cfg = pdata->lcd_type & 0xf; | ||
410 | |||
411 | if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) | ||
412 | cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; | ||
413 | |||
414 | if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT)) | ||
415 | cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; | ||
416 | |||
417 | if (pdata->pixclk_falling_edge) | ||
418 | cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; | ||
419 | |||
420 | if (pdata->date_enable_active_low) | ||
421 | cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; | ||
422 | |||
423 | if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT) | ||
424 | cfg |= JZ_LCD_CFG_18_BIT; | ||
425 | |||
426 | if (mode->pixclock) { | ||
427 | rate = PICOS2KHZ(mode->pixclock) * 1000; | ||
428 | mode->refresh = rate / vt / ht; | ||
429 | } else { | ||
430 | if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL) | ||
431 | rate = mode->refresh * (vt + 2 * mode->xres) * ht; | ||
432 | else | ||
433 | rate = mode->refresh * vt * ht; | ||
434 | |||
435 | mode->pixclock = KHZ2PICOS(rate / 1000); | ||
436 | } | ||
437 | |||
438 | mutex_lock(&jzfb->lock); | ||
439 | if (!jzfb->is_enabled) | ||
440 | clk_enable(jzfb->ldclk); | ||
441 | else | ||
442 | ctrl |= JZ_LCD_CTRL_ENABLE; | ||
443 | |||
444 | switch (pdata->lcd_type) { | ||
445 | case JZ_LCD_TYPE_SPECIAL_TFT_1: | ||
446 | case JZ_LCD_TYPE_SPECIAL_TFT_2: | ||
447 | case JZ_LCD_TYPE_SPECIAL_TFT_3: | ||
448 | writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL); | ||
449 | writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS); | ||
450 | writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS); | ||
451 | writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV); | ||
452 | break; | ||
453 | default: | ||
454 | cfg |= JZ_LCD_CFG_PS_DISABLE; | ||
455 | cfg |= JZ_LCD_CFG_CLS_DISABLE; | ||
456 | cfg |= JZ_LCD_CFG_SPL_DISABLE; | ||
457 | cfg |= JZ_LCD_CFG_REV_DISABLE; | ||
458 | break; | ||
459 | } | ||
460 | |||
461 | writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC); | ||
462 | writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC); | ||
463 | |||
464 | writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT); | ||
465 | |||
466 | writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH); | ||
467 | writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV); | ||
468 | |||
469 | writel(cfg, jzfb->base + JZ_REG_LCD_CFG); | ||
470 | |||
471 | writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); | ||
472 | |||
473 | if (!jzfb->is_enabled) | ||
474 | clk_disable(jzfb->ldclk); | ||
475 | |||
476 | mutex_unlock(&jzfb->lock); | ||
477 | |||
478 | clk_set_rate(jzfb->lpclk, rate); | ||
479 | clk_set_rate(jzfb->ldclk, rate * 3); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static void jzfb_enable(struct jzfb *jzfb) | ||
485 | { | ||
486 | uint32_t ctrl; | ||
487 | |||
488 | clk_enable(jzfb->ldclk); | ||
489 | |||
490 | jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); | ||
491 | jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); | ||
492 | |||
493 | writel(0, jzfb->base + JZ_REG_LCD_STATE); | ||
494 | |||
495 | writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); | ||
496 | |||
497 | ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); | ||
498 | ctrl |= JZ_LCD_CTRL_ENABLE; | ||
499 | ctrl &= ~JZ_LCD_CTRL_DISABLE; | ||
500 | writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); | ||
501 | } | ||
502 | |||
503 | static void jzfb_disable(struct jzfb *jzfb) | ||
504 | { | ||
505 | uint32_t ctrl; | ||
506 | |||
507 | ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); | ||
508 | ctrl |= JZ_LCD_CTRL_DISABLE; | ||
509 | writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); | ||
510 | do { | ||
511 | ctrl = readl(jzfb->base + JZ_REG_LCD_STATE); | ||
512 | } while (!(ctrl & JZ_LCD_STATE_DISABLED)); | ||
513 | |||
514 | jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); | ||
515 | jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); | ||
516 | |||
517 | clk_disable(jzfb->ldclk); | ||
518 | } | ||
519 | |||
520 | static int jzfb_blank(int blank_mode, struct fb_info *info) | ||
521 | { | ||
522 | struct jzfb *jzfb = info->par; | ||
523 | |||
524 | switch (blank_mode) { | ||
525 | case FB_BLANK_UNBLANK: | ||
526 | mutex_lock(&jzfb->lock); | ||
527 | if (jzfb->is_enabled) { | ||
528 | mutex_unlock(&jzfb->lock); | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | jzfb_enable(jzfb); | ||
533 | jzfb->is_enabled = 1; | ||
534 | |||
535 | mutex_unlock(&jzfb->lock); | ||
536 | break; | ||
537 | default: | ||
538 | mutex_lock(&jzfb->lock); | ||
539 | if (!jzfb->is_enabled) { | ||
540 | mutex_unlock(&jzfb->lock); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | jzfb_disable(jzfb); | ||
545 | jzfb->is_enabled = 0; | ||
546 | |||
547 | mutex_unlock(&jzfb->lock); | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static int jzfb_alloc_devmem(struct jzfb *jzfb) | ||
555 | { | ||
556 | int max_videosize = 0; | ||
557 | struct fb_videomode *mode = jzfb->pdata->modes; | ||
558 | void *page; | ||
559 | int i; | ||
560 | |||
561 | for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { | ||
562 | if (max_videosize < mode->xres * mode->yres) | ||
563 | max_videosize = mode->xres * mode->yres; | ||
564 | } | ||
565 | |||
566 | max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3; | ||
567 | |||
568 | jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev, | ||
569 | sizeof(*jzfb->framedesc), | ||
570 | &jzfb->framedesc_phys, GFP_KERNEL); | ||
571 | |||
572 | if (!jzfb->framedesc) | ||
573 | return -ENOMEM; | ||
574 | |||
575 | jzfb->vidmem_size = PAGE_ALIGN(max_videosize); | ||
576 | jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev, | ||
577 | jzfb->vidmem_size, | ||
578 | &jzfb->vidmem_phys, GFP_KERNEL); | ||
579 | |||
580 | if (!jzfb->vidmem) | ||
581 | goto err_free_framedesc; | ||
582 | |||
583 | for (page = jzfb->vidmem; | ||
584 | page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size); | ||
585 | page += PAGE_SIZE) { | ||
586 | SetPageReserved(virt_to_page(page)); | ||
587 | } | ||
588 | |||
589 | jzfb->framedesc->next = jzfb->framedesc_phys; | ||
590 | jzfb->framedesc->addr = jzfb->vidmem_phys; | ||
591 | jzfb->framedesc->id = 0xdeafbead; | ||
592 | jzfb->framedesc->cmd = 0; | ||
593 | jzfb->framedesc->cmd |= max_videosize / 4; | ||
594 | |||
595 | return 0; | ||
596 | |||
597 | err_free_framedesc: | ||
598 | dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), | ||
599 | jzfb->framedesc, jzfb->framedesc_phys); | ||
600 | return -ENOMEM; | ||
601 | } | ||
602 | |||
603 | static void jzfb_free_devmem(struct jzfb *jzfb) | ||
604 | { | ||
605 | dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size, | ||
606 | jzfb->vidmem, jzfb->vidmem_phys); | ||
607 | dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), | ||
608 | jzfb->framedesc, jzfb->framedesc_phys); | ||
609 | } | ||
610 | |||
611 | static struct fb_ops jzfb_ops = { | ||
612 | .owner = THIS_MODULE, | ||
613 | .fb_check_var = jzfb_check_var, | ||
614 | .fb_set_par = jzfb_set_par, | ||
615 | .fb_blank = jzfb_blank, | ||
616 | .fb_fillrect = sys_fillrect, | ||
617 | .fb_copyarea = sys_copyarea, | ||
618 | .fb_imageblit = sys_imageblit, | ||
619 | .fb_setcolreg = jzfb_setcolreg, | ||
620 | }; | ||
621 | |||
622 | static int __devinit jzfb_probe(struct platform_device *pdev) | ||
623 | { | ||
624 | int ret; | ||
625 | struct jzfb *jzfb; | ||
626 | struct fb_info *fb; | ||
627 | struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data; | ||
628 | struct resource *mem; | ||
629 | |||
630 | if (!pdata) { | ||
631 | dev_err(&pdev->dev, "Missing platform data\n"); | ||
632 | return -ENXIO; | ||
633 | } | ||
634 | |||
635 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
636 | if (!mem) { | ||
637 | dev_err(&pdev->dev, "Failed to get register memory resource\n"); | ||
638 | return -ENXIO; | ||
639 | } | ||
640 | |||
641 | mem = request_mem_region(mem->start, resource_size(mem), pdev->name); | ||
642 | if (!mem) { | ||
643 | dev_err(&pdev->dev, "Failed to request register memory region\n"); | ||
644 | return -EBUSY; | ||
645 | } | ||
646 | |||
647 | fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); | ||
648 | if (!fb) { | ||
649 | dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); | ||
650 | ret = -ENOMEM; | ||
651 | goto err_release_mem_region; | ||
652 | } | ||
653 | |||
654 | fb->fbops = &jzfb_ops; | ||
655 | fb->flags = FBINFO_DEFAULT; | ||
656 | |||
657 | jzfb = fb->par; | ||
658 | jzfb->pdev = pdev; | ||
659 | jzfb->pdata = pdata; | ||
660 | jzfb->mem = mem; | ||
661 | |||
662 | jzfb->ldclk = clk_get(&pdev->dev, "lcd"); | ||
663 | if (IS_ERR(jzfb->ldclk)) { | ||
664 | ret = PTR_ERR(jzfb->ldclk); | ||
665 | dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret); | ||
666 | goto err_framebuffer_release; | ||
667 | } | ||
668 | |||
669 | jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); | ||
670 | if (IS_ERR(jzfb->lpclk)) { | ||
671 | ret = PTR_ERR(jzfb->lpclk); | ||
672 | dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); | ||
673 | goto err_put_ldclk; | ||
674 | } | ||
675 | |||
676 | jzfb->base = ioremap(mem->start, resource_size(mem)); | ||
677 | if (!jzfb->base) { | ||
678 | dev_err(&pdev->dev, "Failed to ioremap register memory region\n"); | ||
679 | ret = -EBUSY; | ||
680 | goto err_put_lpclk; | ||
681 | } | ||
682 | |||
683 | platform_set_drvdata(pdev, jzfb); | ||
684 | |||
685 | mutex_init(&jzfb->lock); | ||
686 | |||
687 | fb_videomode_to_modelist(pdata->modes, pdata->num_modes, | ||
688 | &fb->modelist); | ||
689 | fb_videomode_to_var(&fb->var, pdata->modes); | ||
690 | fb->var.bits_per_pixel = pdata->bpp; | ||
691 | jzfb_check_var(&fb->var, fb); | ||
692 | |||
693 | ret = jzfb_alloc_devmem(jzfb); | ||
694 | if (ret) { | ||
695 | dev_err(&pdev->dev, "Failed to allocate video memory\n"); | ||
696 | goto err_iounmap; | ||
697 | } | ||
698 | |||
699 | fb->fix = jzfb_fix; | ||
700 | fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8; | ||
701 | fb->fix.mmio_start = mem->start; | ||
702 | fb->fix.mmio_len = resource_size(mem); | ||
703 | fb->fix.smem_start = jzfb->vidmem_phys; | ||
704 | fb->fix.smem_len = fb->fix.line_length * fb->var.yres; | ||
705 | fb->screen_base = jzfb->vidmem; | ||
706 | fb->pseudo_palette = jzfb->pseudo_palette; | ||
707 | |||
708 | fb_alloc_cmap(&fb->cmap, 256, 0); | ||
709 | |||
710 | clk_enable(jzfb->ldclk); | ||
711 | jzfb->is_enabled = 1; | ||
712 | |||
713 | writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); | ||
714 | |||
715 | fb->mode = NULL; | ||
716 | jzfb_set_par(fb); | ||
717 | |||
718 | jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); | ||
719 | jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); | ||
720 | |||
721 | ret = register_framebuffer(fb); | ||
722 | if (ret) { | ||
723 | dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret); | ||
724 | goto err_free_devmem; | ||
725 | } | ||
726 | |||
727 | jzfb->fb = fb; | ||
728 | |||
729 | return 0; | ||
730 | |||
731 | err_free_devmem: | ||
732 | jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); | ||
733 | jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); | ||
734 | |||
735 | fb_dealloc_cmap(&fb->cmap); | ||
736 | jzfb_free_devmem(jzfb); | ||
737 | err_iounmap: | ||
738 | iounmap(jzfb->base); | ||
739 | err_put_lpclk: | ||
740 | clk_put(jzfb->lpclk); | ||
741 | err_put_ldclk: | ||
742 | clk_put(jzfb->ldclk); | ||
743 | err_framebuffer_release: | ||
744 | framebuffer_release(fb); | ||
745 | err_release_mem_region: | ||
746 | release_mem_region(mem->start, resource_size(mem)); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | static int __devexit jzfb_remove(struct platform_device *pdev) | ||
751 | { | ||
752 | struct jzfb *jzfb = platform_get_drvdata(pdev); | ||
753 | |||
754 | jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb); | ||
755 | |||
756 | jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); | ||
757 | jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); | ||
758 | |||
759 | iounmap(jzfb->base); | ||
760 | release_mem_region(jzfb->mem->start, resource_size(jzfb->mem)); | ||
761 | |||
762 | fb_dealloc_cmap(&jzfb->fb->cmap); | ||
763 | jzfb_free_devmem(jzfb); | ||
764 | |||
765 | platform_set_drvdata(pdev, NULL); | ||
766 | |||
767 | clk_put(jzfb->lpclk); | ||
768 | clk_put(jzfb->ldclk); | ||
769 | |||
770 | framebuffer_release(jzfb->fb); | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | #ifdef CONFIG_PM | ||
776 | |||
777 | static int jzfb_suspend(struct device *dev) | ||
778 | { | ||
779 | struct jzfb *jzfb = dev_get_drvdata(dev); | ||
780 | |||
781 | acquire_console_sem(); | ||
782 | fb_set_suspend(jzfb->fb, 1); | ||
783 | release_console_sem(); | ||
784 | |||
785 | mutex_lock(&jzfb->lock); | ||
786 | if (jzfb->is_enabled) | ||
787 | jzfb_disable(jzfb); | ||
788 | mutex_unlock(&jzfb->lock); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int jzfb_resume(struct device *dev) | ||
794 | { | ||
795 | struct jzfb *jzfb = dev_get_drvdata(dev); | ||
796 | clk_enable(jzfb->ldclk); | ||
797 | |||
798 | mutex_lock(&jzfb->lock); | ||
799 | if (jzfb->is_enabled) | ||
800 | jzfb_enable(jzfb); | ||
801 | mutex_unlock(&jzfb->lock); | ||
802 | |||
803 | acquire_console_sem(); | ||
804 | fb_set_suspend(jzfb->fb, 0); | ||
805 | release_console_sem(); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static const struct dev_pm_ops jzfb_pm_ops = { | ||
811 | .suspend = jzfb_suspend, | ||
812 | .resume = jzfb_resume, | ||
813 | .poweroff = jzfb_suspend, | ||
814 | .restore = jzfb_resume, | ||
815 | }; | ||
816 | |||
817 | #define JZFB_PM_OPS (&jzfb_pm_ops) | ||
818 | |||
819 | #else | ||
820 | #define JZFB_PM_OPS NULL | ||
821 | #endif | ||
822 | |||
823 | static struct platform_driver jzfb_driver = { | ||
824 | .probe = jzfb_probe, | ||
825 | .remove = __devexit_p(jzfb_remove), | ||
826 | .driver = { | ||
827 | .name = "jz4740-fb", | ||
828 | .pm = JZFB_PM_OPS, | ||
829 | }, | ||
830 | }; | ||
831 | |||
832 | static int __init jzfb_init(void) | ||
833 | { | ||
834 | return platform_driver_register(&jzfb_driver); | ||
835 | } | ||
836 | module_init(jzfb_init); | ||
837 | |||
838 | static void __exit jzfb_exit(void) | ||
839 | { | ||
840 | platform_driver_unregister(&jzfb_driver); | ||
841 | } | ||
842 | module_exit(jzfb_exit); | ||
843 | |||
844 | MODULE_LICENSE("GPL"); | ||
845 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
846 | MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver"); | ||
847 | MODULE_ALIAS("platform:jz4740-fb"); | ||
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 9e8bf7d5e249..ad677637ffbb 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
@@ -677,12 +677,12 @@ static int __init leo_init(void) | |||
677 | if (fb_get_options("leofb", NULL)) | 677 | if (fb_get_options("leofb", NULL)) |
678 | return -ENODEV; | 678 | return -ENODEV; |
679 | 679 | ||
680 | return of_register_driver(&leo_driver, &of_bus_type); | 680 | return of_register_platform_driver(&leo_driver); |
681 | } | 681 | } |
682 | 682 | ||
683 | static void __exit leo_exit(void) | 683 | static void __exit leo_exit(void) |
684 | { | 684 | { |
685 | of_unregister_driver(&leo_driver); | 685 | of_unregister_platform_driver(&leo_driver); |
686 | } | 686 | } |
687 | 687 | ||
688 | module_init(leo_init); | 688 | module_init(leo_init); |
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 46dda7d8aaee..cb163a5397be 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
@@ -19,13 +19,14 @@ | |||
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_address.h> | ||
22 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
23 | #include <linux/fb.h> | 25 | #include <linux/fb.h> |
24 | #include <linux/init.h> | 26 | #include <linux/init.h> |
25 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
26 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
27 | #include <asm/io.h> | 29 | #include <asm/io.h> |
28 | #include <asm/prom.h> | ||
29 | 30 | ||
30 | #ifdef CONFIG_PPC64 | 31 | #ifdef CONFIG_PPC64 |
31 | #include <asm/pci-bridge.h> | 32 | #include <asm/pci-bridge.h> |
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c index 2be94eb3bbf5..10459d8bd9a0 100644 --- a/drivers/video/omap/lcd_apollon.c +++ b/drivers/video/omap/lcd_apollon.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | 26 | ||
27 | #include <mach/gpio.h> | 27 | #include <mach/gpio.h> |
28 | #include <plat/mux.h> | ||
29 | 28 | ||
30 | #include "omapfb.h" | 29 | #include "omapfb.h" |
31 | 30 | ||
@@ -34,8 +33,6 @@ | |||
34 | static int apollon_panel_init(struct lcd_panel *panel, | 33 | static int apollon_panel_init(struct lcd_panel *panel, |
35 | struct omapfb_device *fbdev) | 34 | struct omapfb_device *fbdev) |
36 | { | 35 | { |
37 | /* configure LCD PWR_EN */ | ||
38 | omap_cfg_reg(M21_242X_GPIO11); | ||
39 | return 0; | 36 | return 0; |
40 | } | 37 | } |
41 | 38 | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index aaf5d308a046..e1c765d11419 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -28,12 +28,13 @@ | |||
28 | #include <linux/fb.h> | 28 | #include <linux/fb.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/gpio.h> | 30 | #include <linux/gpio.h> |
31 | #include <linux/completion.h> | ||
32 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include <plat/nokia-dsi-panel.h> | ||
37 | 38 | ||
38 | /* DSI Virtual channel. Hardcoded for now. */ | 39 | /* DSI Virtual channel. Hardcoded for now. */ |
39 | #define TCH 0 | 40 | #define TCH 0 |
@@ -62,11 +63,136 @@ | |||
62 | #define DCS_GET_ID2 0xdb | 63 | #define DCS_GET_ID2 0xdb |
63 | #define DCS_GET_ID3 0xdc | 64 | #define DCS_GET_ID3 0xdc |
64 | 65 | ||
65 | /* #define TAAL_USE_ESD_CHECK */ | ||
66 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) | 66 | #define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) |
67 | 67 | ||
68 | static irqreturn_t taal_te_isr(int irq, void *data); | ||
69 | static void taal_te_timeout_work_callback(struct work_struct *work); | ||
68 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 70 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); |
69 | 71 | ||
72 | struct panel_regulator { | ||
73 | struct regulator *regulator; | ||
74 | const char *name; | ||
75 | int min_uV; | ||
76 | int max_uV; | ||
77 | }; | ||
78 | |||
79 | static void free_regulators(struct panel_regulator *regulators, int n) | ||
80 | { | ||
81 | int i; | ||
82 | |||
83 | for (i = 0; i < n; i++) { | ||
84 | /* disable/put in reverse order */ | ||
85 | regulator_disable(regulators[n - i - 1].regulator); | ||
86 | regulator_put(regulators[n - i - 1].regulator); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static int init_regulators(struct omap_dss_device *dssdev, | ||
91 | struct panel_regulator *regulators, int n) | ||
92 | { | ||
93 | int r, i, v; | ||
94 | |||
95 | for (i = 0; i < n; i++) { | ||
96 | struct regulator *reg; | ||
97 | |||
98 | reg = regulator_get(&dssdev->dev, regulators[i].name); | ||
99 | if (IS_ERR(reg)) { | ||
100 | dev_err(&dssdev->dev, "failed to get regulator %s\n", | ||
101 | regulators[i].name); | ||
102 | r = PTR_ERR(reg); | ||
103 | goto err; | ||
104 | } | ||
105 | |||
106 | /* FIXME: better handling of fixed vs. variable regulators */ | ||
107 | v = regulator_get_voltage(reg); | ||
108 | if (v < regulators[i].min_uV || v > regulators[i].max_uV) { | ||
109 | r = regulator_set_voltage(reg, regulators[i].min_uV, | ||
110 | regulators[i].max_uV); | ||
111 | if (r) { | ||
112 | dev_err(&dssdev->dev, | ||
113 | "failed to set regulator %s voltage\n", | ||
114 | regulators[i].name); | ||
115 | regulator_put(reg); | ||
116 | goto err; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | r = regulator_enable(reg); | ||
121 | if (r) { | ||
122 | dev_err(&dssdev->dev, "failed to enable regulator %s\n", | ||
123 | regulators[i].name); | ||
124 | regulator_put(reg); | ||
125 | goto err; | ||
126 | } | ||
127 | |||
128 | regulators[i].regulator = reg; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | |||
133 | err: | ||
134 | free_regulators(regulators, i); | ||
135 | |||
136 | return r; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * struct panel_config - panel configuration | ||
141 | * @name: panel name | ||
142 | * @type: panel type | ||
143 | * @timings: panel resolution | ||
144 | * @sleep: various panel specific delays, passed to msleep() if non-zero | ||
145 | * @reset_sequence: reset sequence timings, passed to udelay() if non-zero | ||
146 | * @regulators: array of panel regulators | ||
147 | * @num_regulators: number of regulators in the array | ||
148 | */ | ||
149 | struct panel_config { | ||
150 | const char *name; | ||
151 | int type; | ||
152 | |||
153 | struct omap_video_timings timings; | ||
154 | |||
155 | struct { | ||
156 | unsigned int sleep_in; | ||
157 | unsigned int sleep_out; | ||
158 | unsigned int hw_reset; | ||
159 | unsigned int enable_te; | ||
160 | } sleep; | ||
161 | |||
162 | struct { | ||
163 | unsigned int high; | ||
164 | unsigned int low; | ||
165 | } reset_sequence; | ||
166 | |||
167 | struct panel_regulator *regulators; | ||
168 | int num_regulators; | ||
169 | }; | ||
170 | |||
171 | enum { | ||
172 | PANEL_TAAL, | ||
173 | }; | ||
174 | |||
175 | static struct panel_config panel_configs[] = { | ||
176 | { | ||
177 | .name = "taal", | ||
178 | .type = PANEL_TAAL, | ||
179 | .timings = { | ||
180 | .x_res = 864, | ||
181 | .y_res = 480, | ||
182 | }, | ||
183 | .sleep = { | ||
184 | .sleep_in = 5, | ||
185 | .sleep_out = 5, | ||
186 | .hw_reset = 5, | ||
187 | .enable_te = 100, /* possible panel bug */ | ||
188 | }, | ||
189 | .reset_sequence = { | ||
190 | .high = 10, | ||
191 | .low = 10, | ||
192 | }, | ||
193 | }, | ||
194 | }; | ||
195 | |||
70 | struct taal_data { | 196 | struct taal_data { |
71 | struct mutex lock; | 197 | struct mutex lock; |
72 | 198 | ||
@@ -84,8 +210,15 @@ struct taal_data { | |||
84 | bool mirror; | 210 | bool mirror; |
85 | 211 | ||
86 | bool te_enabled; | 212 | bool te_enabled; |
87 | bool use_ext_te; | 213 | |
88 | struct completion te_completion; | 214 | atomic_t do_update; |
215 | struct { | ||
216 | u16 x; | ||
217 | u16 y; | ||
218 | u16 w; | ||
219 | u16 h; | ||
220 | } update_region; | ||
221 | struct delayed_work te_timeout_work; | ||
89 | 222 | ||
90 | bool use_dsi_bl; | 223 | bool use_dsi_bl; |
91 | 224 | ||
@@ -96,8 +229,16 @@ struct taal_data { | |||
96 | 229 | ||
97 | struct workqueue_struct *esd_wq; | 230 | struct workqueue_struct *esd_wq; |
98 | struct delayed_work esd_work; | 231 | struct delayed_work esd_work; |
232 | |||
233 | struct panel_config *panel_config; | ||
99 | }; | 234 | }; |
100 | 235 | ||
236 | static inline struct nokia_dsi_panel_data | ||
237 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
238 | { | ||
239 | return (struct nokia_dsi_panel_data *) dssdev->data; | ||
240 | } | ||
241 | |||
101 | static void taal_esd_work(struct work_struct *work); | 242 | static void taal_esd_work(struct work_struct *work); |
102 | 243 | ||
103 | static void hw_guard_start(struct taal_data *td, int guard_msec) | 244 | static void hw_guard_start(struct taal_data *td, int guard_msec) |
@@ -159,7 +300,8 @@ static int taal_sleep_in(struct taal_data *td) | |||
159 | 300 | ||
160 | hw_guard_start(td, 120); | 301 | hw_guard_start(td, 120); |
161 | 302 | ||
162 | msleep(5); | 303 | if (td->panel_config->sleep.sleep_in) |
304 | msleep(td->panel_config->sleep.sleep_in); | ||
163 | 305 | ||
164 | return 0; | 306 | return 0; |
165 | } | 307 | } |
@@ -176,7 +318,8 @@ static int taal_sleep_out(struct taal_data *td) | |||
176 | 318 | ||
177 | hw_guard_start(td, 120); | 319 | hw_guard_start(td, 120); |
178 | 320 | ||
179 | msleep(5); | 321 | if (td->panel_config->sleep.sleep_out) |
322 | msleep(td->panel_config->sleep.sleep_out); | ||
180 | 323 | ||
181 | return 0; | 324 | return 0; |
182 | } | 325 | } |
@@ -279,6 +422,7 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
279 | { | 422 | { |
280 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 423 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); |
281 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 424 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
425 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
282 | int r; | 426 | int r; |
283 | int level; | 427 | int level; |
284 | 428 | ||
@@ -290,24 +434,26 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
290 | 434 | ||
291 | dev_dbg(&dssdev->dev, "update brightness to %d\n", level); | 435 | dev_dbg(&dssdev->dev, "update brightness to %d\n", level); |
292 | 436 | ||
437 | mutex_lock(&td->lock); | ||
438 | |||
293 | if (td->use_dsi_bl) { | 439 | if (td->use_dsi_bl) { |
294 | if (td->enabled) { | 440 | if (td->enabled) { |
295 | dsi_bus_lock(); | 441 | dsi_bus_lock(); |
296 | r = taal_dcs_write_1(DCS_BRIGHTNESS, level); | 442 | r = taal_dcs_write_1(DCS_BRIGHTNESS, level); |
297 | dsi_bus_unlock(); | 443 | dsi_bus_unlock(); |
298 | if (r) | 444 | } else { |
299 | return r; | 445 | r = 0; |
300 | } | 446 | } |
301 | } else { | 447 | } else { |
302 | if (!dssdev->set_backlight) | 448 | if (!panel_data->set_backlight) |
303 | return -EINVAL; | 449 | r = -EINVAL; |
304 | 450 | else | |
305 | r = dssdev->set_backlight(dssdev, level); | 451 | r = panel_data->set_backlight(dssdev, level); |
306 | if (r) | ||
307 | return r; | ||
308 | } | 452 | } |
309 | 453 | ||
310 | return 0; | 454 | mutex_unlock(&td->lock); |
455 | |||
456 | return r; | ||
311 | } | 457 | } |
312 | 458 | ||
313 | static int taal_bl_get_intensity(struct backlight_device *dev) | 459 | static int taal_bl_get_intensity(struct backlight_device *dev) |
@@ -344,16 +490,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev, | |||
344 | } | 490 | } |
345 | } | 491 | } |
346 | 492 | ||
347 | static irqreturn_t taal_te_isr(int irq, void *data) | ||
348 | { | ||
349 | struct omap_dss_device *dssdev = data; | ||
350 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
351 | |||
352 | complete_all(&td->te_completion); | ||
353 | |||
354 | return IRQ_HANDLED; | ||
355 | } | ||
356 | |||
357 | static ssize_t taal_num_errors_show(struct device *dev, | 493 | static ssize_t taal_num_errors_show(struct device *dev, |
358 | struct device_attribute *attr, char *buf) | 494 | struct device_attribute *attr, char *buf) |
359 | { | 495 | { |
@@ -362,6 +498,8 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
362 | u8 errors; | 498 | u8 errors; |
363 | int r; | 499 | int r; |
364 | 500 | ||
501 | mutex_lock(&td->lock); | ||
502 | |||
365 | if (td->enabled) { | 503 | if (td->enabled) { |
366 | dsi_bus_lock(); | 504 | dsi_bus_lock(); |
367 | r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); | 505 | r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); |
@@ -370,6 +508,8 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
370 | r = -ENODEV; | 508 | r = -ENODEV; |
371 | } | 509 | } |
372 | 510 | ||
511 | mutex_unlock(&td->lock); | ||
512 | |||
373 | if (r) | 513 | if (r) |
374 | return r; | 514 | return r; |
375 | 515 | ||
@@ -384,6 +524,8 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
384 | u8 id1, id2, id3; | 524 | u8 id1, id2, id3; |
385 | int r; | 525 | int r; |
386 | 526 | ||
527 | mutex_lock(&td->lock); | ||
528 | |||
387 | if (td->enabled) { | 529 | if (td->enabled) { |
388 | dsi_bus_lock(); | 530 | dsi_bus_lock(); |
389 | r = taal_get_id(&id1, &id2, &id3); | 531 | r = taal_get_id(&id1, &id2, &id3); |
@@ -392,6 +534,8 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
392 | r = -ENODEV; | 534 | r = -ENODEV; |
393 | } | 535 | } |
394 | 536 | ||
537 | mutex_unlock(&td->lock); | ||
538 | |||
395 | if (r) | 539 | if (r) |
396 | return r; | 540 | return r; |
397 | 541 | ||
@@ -441,6 +585,8 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
441 | if (i == ARRAY_SIZE(cabc_modes)) | 585 | if (i == ARRAY_SIZE(cabc_modes)) |
442 | return -EINVAL; | 586 | return -EINVAL; |
443 | 587 | ||
588 | mutex_lock(&td->lock); | ||
589 | |||
444 | if (td->enabled) { | 590 | if (td->enabled) { |
445 | dsi_bus_lock(); | 591 | dsi_bus_lock(); |
446 | if (!td->cabc_broken) | 592 | if (!td->cabc_broken) |
@@ -450,6 +596,8 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
450 | 596 | ||
451 | td->cabc_mode = i; | 597 | td->cabc_mode = i; |
452 | 598 | ||
599 | mutex_unlock(&td->lock); | ||
600 | |||
453 | return count; | 601 | return count; |
454 | } | 602 | } |
455 | 603 | ||
@@ -488,47 +636,93 @@ static struct attribute_group taal_attr_group = { | |||
488 | .attrs = taal_attrs, | 636 | .attrs = taal_attrs, |
489 | }; | 637 | }; |
490 | 638 | ||
639 | static void taal_hw_reset(struct omap_dss_device *dssdev) | ||
640 | { | ||
641 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
642 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
643 | |||
644 | if (panel_data->reset_gpio == -1) | ||
645 | return; | ||
646 | |||
647 | gpio_set_value(panel_data->reset_gpio, 1); | ||
648 | if (td->panel_config->reset_sequence.high) | ||
649 | udelay(td->panel_config->reset_sequence.high); | ||
650 | /* reset the panel */ | ||
651 | gpio_set_value(panel_data->reset_gpio, 0); | ||
652 | /* assert reset */ | ||
653 | if (td->panel_config->reset_sequence.low) | ||
654 | udelay(td->panel_config->reset_sequence.low); | ||
655 | gpio_set_value(panel_data->reset_gpio, 1); | ||
656 | /* wait after releasing reset */ | ||
657 | if (td->panel_config->sleep.hw_reset) | ||
658 | msleep(td->panel_config->sleep.hw_reset); | ||
659 | } | ||
660 | |||
491 | static int taal_probe(struct omap_dss_device *dssdev) | 661 | static int taal_probe(struct omap_dss_device *dssdev) |
492 | { | 662 | { |
493 | struct backlight_properties props; | 663 | struct backlight_properties props; |
494 | struct taal_data *td; | 664 | struct taal_data *td; |
495 | struct backlight_device *bldev; | 665 | struct backlight_device *bldev; |
496 | int r; | 666 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
497 | 667 | struct panel_config *panel_config = NULL; | |
498 | const struct omap_video_timings taal_panel_timings = { | 668 | int r, i; |
499 | .x_res = 864, | ||
500 | .y_res = 480, | ||
501 | }; | ||
502 | 669 | ||
503 | dev_dbg(&dssdev->dev, "probe\n"); | 670 | dev_dbg(&dssdev->dev, "probe\n"); |
504 | 671 | ||
672 | if (!panel_data || !panel_data->name) { | ||
673 | r = -EINVAL; | ||
674 | goto err; | ||
675 | } | ||
676 | |||
677 | for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { | ||
678 | if (strcmp(panel_data->name, panel_configs[i].name) == 0) { | ||
679 | panel_config = &panel_configs[i]; | ||
680 | break; | ||
681 | } | ||
682 | } | ||
683 | |||
684 | if (!panel_config) { | ||
685 | r = -EINVAL; | ||
686 | goto err; | ||
687 | } | ||
688 | |||
505 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | 689 | dssdev->panel.config = OMAP_DSS_LCD_TFT; |
506 | dssdev->panel.timings = taal_panel_timings; | 690 | dssdev->panel.timings = panel_config->timings; |
507 | dssdev->ctrl.pixel_size = 24; | 691 | dssdev->ctrl.pixel_size = 24; |
508 | 692 | ||
509 | td = kzalloc(sizeof(*td), GFP_KERNEL); | 693 | td = kzalloc(sizeof(*td), GFP_KERNEL); |
510 | if (!td) { | 694 | if (!td) { |
511 | r = -ENOMEM; | 695 | r = -ENOMEM; |
512 | goto err0; | 696 | goto err; |
513 | } | 697 | } |
514 | td->dssdev = dssdev; | 698 | td->dssdev = dssdev; |
699 | td->panel_config = panel_config; | ||
515 | 700 | ||
516 | mutex_init(&td->lock); | 701 | mutex_init(&td->lock); |
517 | 702 | ||
703 | atomic_set(&td->do_update, 0); | ||
704 | |||
705 | r = init_regulators(dssdev, panel_config->regulators, | ||
706 | panel_config->num_regulators); | ||
707 | if (r) | ||
708 | goto err_reg; | ||
709 | |||
518 | td->esd_wq = create_singlethread_workqueue("taal_esd"); | 710 | td->esd_wq = create_singlethread_workqueue("taal_esd"); |
519 | if (td->esd_wq == NULL) { | 711 | if (td->esd_wq == NULL) { |
520 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 712 | dev_err(&dssdev->dev, "can't create ESD workqueue\n"); |
521 | r = -ENOMEM; | 713 | r = -ENOMEM; |
522 | goto err1; | 714 | goto err_wq; |
523 | } | 715 | } |
524 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); | 716 | INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); |
525 | 717 | ||
526 | dev_set_drvdata(&dssdev->dev, td); | 718 | dev_set_drvdata(&dssdev->dev, td); |
527 | 719 | ||
720 | taal_hw_reset(dssdev); | ||
721 | |||
528 | /* if no platform set_backlight() defined, presume DSI backlight | 722 | /* if no platform set_backlight() defined, presume DSI backlight |
529 | * control */ | 723 | * control */ |
530 | memset(&props, 0, sizeof(struct backlight_properties)); | 724 | memset(&props, 0, sizeof(struct backlight_properties)); |
531 | if (!dssdev->set_backlight) | 725 | if (!panel_data->set_backlight) |
532 | td->use_dsi_bl = true; | 726 | td->use_dsi_bl = true; |
533 | 727 | ||
534 | if (td->use_dsi_bl) | 728 | if (td->use_dsi_bl) |
@@ -539,7 +733,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
539 | &taal_bl_ops, &props); | 733 | &taal_bl_ops, &props); |
540 | if (IS_ERR(bldev)) { | 734 | if (IS_ERR(bldev)) { |
541 | r = PTR_ERR(bldev); | 735 | r = PTR_ERR(bldev); |
542 | goto err2; | 736 | goto err_bl; |
543 | } | 737 | } |
544 | 738 | ||
545 | td->bldev = bldev; | 739 | td->bldev = bldev; |
@@ -553,13 +747,13 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
553 | 747 | ||
554 | taal_bl_update_status(bldev); | 748 | taal_bl_update_status(bldev); |
555 | 749 | ||
556 | if (dssdev->phy.dsi.ext_te) { | 750 | if (panel_data->use_ext_te) { |
557 | int gpio = dssdev->phy.dsi.ext_te_gpio; | 751 | int gpio = panel_data->ext_te_gpio; |
558 | 752 | ||
559 | r = gpio_request(gpio, "taal irq"); | 753 | r = gpio_request(gpio, "taal irq"); |
560 | if (r) { | 754 | if (r) { |
561 | dev_err(&dssdev->dev, "GPIO request failed\n"); | 755 | dev_err(&dssdev->dev, "GPIO request failed\n"); |
562 | goto err3; | 756 | goto err_gpio; |
563 | } | 757 | } |
564 | 758 | ||
565 | gpio_direction_input(gpio); | 759 | gpio_direction_input(gpio); |
@@ -571,49 +765,52 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
571 | if (r) { | 765 | if (r) { |
572 | dev_err(&dssdev->dev, "IRQ request failed\n"); | 766 | dev_err(&dssdev->dev, "IRQ request failed\n"); |
573 | gpio_free(gpio); | 767 | gpio_free(gpio); |
574 | goto err3; | 768 | goto err_irq; |
575 | } | 769 | } |
576 | 770 | ||
577 | init_completion(&td->te_completion); | 771 | INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work, |
772 | taal_te_timeout_work_callback); | ||
578 | 773 | ||
579 | td->use_ext_te = true; | 774 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); |
580 | } | 775 | } |
581 | 776 | ||
582 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 777 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); |
583 | if (r) { | 778 | if (r) { |
584 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); | 779 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); |
585 | goto err4; | 780 | goto err_sysfs; |
586 | } | 781 | } |
587 | 782 | ||
588 | return 0; | 783 | return 0; |
589 | err4: | 784 | err_sysfs: |
590 | if (td->use_ext_te) { | 785 | if (panel_data->use_ext_te) |
591 | int gpio = dssdev->phy.dsi.ext_te_gpio; | 786 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); |
592 | free_irq(gpio_to_irq(gpio), dssdev); | 787 | err_irq: |
593 | gpio_free(gpio); | 788 | if (panel_data->use_ext_te) |
594 | } | 789 | gpio_free(panel_data->ext_te_gpio); |
595 | err3: | 790 | err_gpio: |
596 | backlight_device_unregister(bldev); | 791 | backlight_device_unregister(bldev); |
597 | err2: | 792 | err_bl: |
598 | cancel_delayed_work_sync(&td->esd_work); | ||
599 | destroy_workqueue(td->esd_wq); | 793 | destroy_workqueue(td->esd_wq); |
600 | err1: | 794 | err_wq: |
795 | free_regulators(panel_config->regulators, panel_config->num_regulators); | ||
796 | err_reg: | ||
601 | kfree(td); | 797 | kfree(td); |
602 | err0: | 798 | err: |
603 | return r; | 799 | return r; |
604 | } | 800 | } |
605 | 801 | ||
606 | static void taal_remove(struct omap_dss_device *dssdev) | 802 | static void taal_remove(struct omap_dss_device *dssdev) |
607 | { | 803 | { |
608 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 804 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
805 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
609 | struct backlight_device *bldev; | 806 | struct backlight_device *bldev; |
610 | 807 | ||
611 | dev_dbg(&dssdev->dev, "remove\n"); | 808 | dev_dbg(&dssdev->dev, "remove\n"); |
612 | 809 | ||
613 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); | 810 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); |
614 | 811 | ||
615 | if (td->use_ext_te) { | 812 | if (panel_data->use_ext_te) { |
616 | int gpio = dssdev->phy.dsi.ext_te_gpio; | 813 | int gpio = panel_data->ext_te_gpio; |
617 | free_irq(gpio_to_irq(gpio), dssdev); | 814 | free_irq(gpio_to_irq(gpio), dssdev); |
618 | gpio_free(gpio); | 815 | gpio_free(gpio); |
619 | } | 816 | } |
@@ -623,9 +820,15 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
623 | taal_bl_update_status(bldev); | 820 | taal_bl_update_status(bldev); |
624 | backlight_device_unregister(bldev); | 821 | backlight_device_unregister(bldev); |
625 | 822 | ||
626 | cancel_delayed_work_sync(&td->esd_work); | 823 | cancel_delayed_work(&td->esd_work); |
627 | destroy_workqueue(td->esd_wq); | 824 | destroy_workqueue(td->esd_wq); |
628 | 825 | ||
826 | /* reset, to be sure that the panel is in a valid state */ | ||
827 | taal_hw_reset(dssdev); | ||
828 | |||
829 | free_regulators(td->panel_config->regulators, | ||
830 | td->panel_config->num_regulators); | ||
831 | |||
629 | kfree(td); | 832 | kfree(td); |
630 | } | 833 | } |
631 | 834 | ||
@@ -635,23 +838,14 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
635 | u8 id1, id2, id3; | 838 | u8 id1, id2, id3; |
636 | int r; | 839 | int r; |
637 | 840 | ||
638 | if (dssdev->platform_enable) { | ||
639 | r = dssdev->platform_enable(dssdev); | ||
640 | if (r) | ||
641 | return r; | ||
642 | } | ||
643 | |||
644 | /* it seems we have to wait a bit until taal is ready */ | ||
645 | msleep(5); | ||
646 | |||
647 | dsi_bus_lock(); | ||
648 | |||
649 | r = omapdss_dsi_display_enable(dssdev); | 841 | r = omapdss_dsi_display_enable(dssdev); |
650 | if (r) { | 842 | if (r) { |
651 | dev_err(&dssdev->dev, "failed to enable DSI\n"); | 843 | dev_err(&dssdev->dev, "failed to enable DSI\n"); |
652 | goto err0; | 844 | goto err0; |
653 | } | 845 | } |
654 | 846 | ||
847 | taal_hw_reset(dssdev); | ||
848 | |||
655 | omapdss_dsi_vc_enable_hs(TCH, false); | 849 | omapdss_dsi_vc_enable_hs(TCH, false); |
656 | 850 | ||
657 | r = taal_sleep_out(td); | 851 | r = taal_sleep_out(td); |
@@ -662,34 +856,47 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
662 | if (r) | 856 | if (r) |
663 | goto err; | 857 | goto err; |
664 | 858 | ||
665 | /* on early revisions CABC is broken */ | 859 | /* on early Taal revisions CABC is broken */ |
666 | if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) | 860 | if (td->panel_config->type == PANEL_TAAL && |
861 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | ||
667 | td->cabc_broken = true; | 862 | td->cabc_broken = true; |
668 | 863 | ||
669 | taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); | 864 | r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); |
670 | taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ | 865 | if (r) |
866 | goto err; | ||
867 | |||
868 | r = taal_dcs_write_1(DCS_CTRL_DISPLAY, | ||
869 | (1<<2) | (1<<5)); /* BL | BCTRL */ | ||
870 | if (r) | ||
871 | goto err; | ||
872 | |||
873 | r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | ||
874 | if (r) | ||
875 | goto err; | ||
671 | 876 | ||
672 | taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 877 | r = taal_set_addr_mode(td->rotate, td->mirror); |
878 | if (r) | ||
879 | goto err; | ||
673 | 880 | ||
674 | taal_set_addr_mode(td->rotate, td->mirror); | 881 | if (!td->cabc_broken) { |
675 | if (!td->cabc_broken) | 882 | r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); |
676 | taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); | 883 | if (r) |
884 | goto err; | ||
885 | } | ||
677 | 886 | ||
678 | taal_dcs_write_0(DCS_DISPLAY_ON); | 887 | r = taal_dcs_write_0(DCS_DISPLAY_ON); |
888 | if (r) | ||
889 | goto err; | ||
679 | 890 | ||
680 | r = _taal_enable_te(dssdev, td->te_enabled); | 891 | r = _taal_enable_te(dssdev, td->te_enabled); |
681 | if (r) | 892 | if (r) |
682 | goto err; | 893 | goto err; |
683 | 894 | ||
684 | #ifdef TAAL_USE_ESD_CHECK | ||
685 | queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | ||
686 | #endif | ||
687 | |||
688 | td->enabled = 1; | 895 | td->enabled = 1; |
689 | 896 | ||
690 | if (!td->intro_printed) { | 897 | if (!td->intro_printed) { |
691 | dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", | 898 | dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n", |
692 | id1, id2, id3); | 899 | td->panel_config->name, id1, id2, id3); |
693 | if (td->cabc_broken) | 900 | if (td->cabc_broken) |
694 | dev_info(&dssdev->dev, | 901 | dev_info(&dssdev->dev, |
695 | "old Taal version, CABC disabled\n"); | 902 | "old Taal version, CABC disabled\n"); |
@@ -698,46 +905,44 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
698 | 905 | ||
699 | omapdss_dsi_vc_enable_hs(TCH, true); | 906 | omapdss_dsi_vc_enable_hs(TCH, true); |
700 | 907 | ||
701 | dsi_bus_unlock(); | ||
702 | |||
703 | return 0; | 908 | return 0; |
704 | err: | 909 | err: |
910 | dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n"); | ||
911 | |||
912 | taal_hw_reset(dssdev); | ||
913 | |||
705 | omapdss_dsi_display_disable(dssdev); | 914 | omapdss_dsi_display_disable(dssdev); |
706 | err0: | 915 | err0: |
707 | dsi_bus_unlock(); | ||
708 | if (dssdev->platform_disable) | ||
709 | dssdev->platform_disable(dssdev); | ||
710 | |||
711 | return r; | 916 | return r; |
712 | } | 917 | } |
713 | 918 | ||
714 | static void taal_power_off(struct omap_dss_device *dssdev) | 919 | static void taal_power_off(struct omap_dss_device *dssdev) |
715 | { | 920 | { |
716 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 921 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
922 | int r; | ||
717 | 923 | ||
718 | dsi_bus_lock(); | 924 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); |
719 | 925 | if (!r) { | |
720 | cancel_delayed_work(&td->esd_work); | 926 | r = taal_sleep_in(td); |
721 | 927 | /* HACK: wait a bit so that the message goes through */ | |
722 | taal_dcs_write_0(DCS_DISPLAY_OFF); | 928 | msleep(10); |
723 | taal_sleep_in(td); | 929 | } |
724 | 930 | ||
725 | /* wait a bit so that the message goes through */ | 931 | if (r) { |
726 | msleep(10); | 932 | dev_err(&dssdev->dev, |
933 | "error disabling panel, issuing HW reset\n"); | ||
934 | taal_hw_reset(dssdev); | ||
935 | } | ||
727 | 936 | ||
728 | omapdss_dsi_display_disable(dssdev); | 937 | omapdss_dsi_display_disable(dssdev); |
729 | 938 | ||
730 | if (dssdev->platform_disable) | ||
731 | dssdev->platform_disable(dssdev); | ||
732 | |||
733 | td->enabled = 0; | 939 | td->enabled = 0; |
734 | |||
735 | dsi_bus_unlock(); | ||
736 | } | 940 | } |
737 | 941 | ||
738 | static int taal_enable(struct omap_dss_device *dssdev) | 942 | static int taal_enable(struct omap_dss_device *dssdev) |
739 | { | 943 | { |
740 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 944 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
945 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
741 | int r; | 946 | int r; |
742 | 947 | ||
743 | dev_dbg(&dssdev->dev, "enable\n"); | 948 | dev_dbg(&dssdev->dev, "enable\n"); |
@@ -749,10 +954,19 @@ static int taal_enable(struct omap_dss_device *dssdev) | |||
749 | goto err; | 954 | goto err; |
750 | } | 955 | } |
751 | 956 | ||
957 | dsi_bus_lock(); | ||
958 | |||
752 | r = taal_power_on(dssdev); | 959 | r = taal_power_on(dssdev); |
960 | |||
961 | dsi_bus_unlock(); | ||
962 | |||
753 | if (r) | 963 | if (r) |
754 | goto err; | 964 | goto err; |
755 | 965 | ||
966 | if (panel_data->use_esd_check) | ||
967 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
968 | TAAL_ESD_CHECK_PERIOD); | ||
969 | |||
756 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 970 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
757 | 971 | ||
758 | mutex_unlock(&td->lock); | 972 | mutex_unlock(&td->lock); |
@@ -772,9 +986,15 @@ static void taal_disable(struct omap_dss_device *dssdev) | |||
772 | 986 | ||
773 | mutex_lock(&td->lock); | 987 | mutex_lock(&td->lock); |
774 | 988 | ||
989 | cancel_delayed_work(&td->esd_work); | ||
990 | |||
991 | dsi_bus_lock(); | ||
992 | |||
775 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 993 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) |
776 | taal_power_off(dssdev); | 994 | taal_power_off(dssdev); |
777 | 995 | ||
996 | dsi_bus_unlock(); | ||
997 | |||
778 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 998 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; |
779 | 999 | ||
780 | mutex_unlock(&td->lock); | 1000 | mutex_unlock(&td->lock); |
@@ -794,7 +1014,14 @@ static int taal_suspend(struct omap_dss_device *dssdev) | |||
794 | goto err; | 1014 | goto err; |
795 | } | 1015 | } |
796 | 1016 | ||
1017 | cancel_delayed_work(&td->esd_work); | ||
1018 | |||
1019 | dsi_bus_lock(); | ||
1020 | |||
797 | taal_power_off(dssdev); | 1021 | taal_power_off(dssdev); |
1022 | |||
1023 | dsi_bus_unlock(); | ||
1024 | |||
798 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 1025 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; |
799 | 1026 | ||
800 | mutex_unlock(&td->lock); | 1027 | mutex_unlock(&td->lock); |
@@ -808,6 +1035,7 @@ err: | |||
808 | static int taal_resume(struct omap_dss_device *dssdev) | 1035 | static int taal_resume(struct omap_dss_device *dssdev) |
809 | { | 1036 | { |
810 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1037 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1038 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
811 | int r; | 1039 | int r; |
812 | 1040 | ||
813 | dev_dbg(&dssdev->dev, "resume\n"); | 1041 | dev_dbg(&dssdev->dev, "resume\n"); |
@@ -819,8 +1047,20 @@ static int taal_resume(struct omap_dss_device *dssdev) | |||
819 | goto err; | 1047 | goto err; |
820 | } | 1048 | } |
821 | 1049 | ||
1050 | dsi_bus_lock(); | ||
1051 | |||
822 | r = taal_power_on(dssdev); | 1052 | r = taal_power_on(dssdev); |
823 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 1053 | |
1054 | dsi_bus_unlock(); | ||
1055 | |||
1056 | if (r) { | ||
1057 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
1058 | } else { | ||
1059 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
1060 | if (panel_data->use_esd_check) | ||
1061 | queue_delayed_work(td->esd_wq, &td->esd_work, | ||
1062 | TAAL_ESD_CHECK_PERIOD); | ||
1063 | } | ||
824 | 1064 | ||
825 | mutex_unlock(&td->lock); | 1065 | mutex_unlock(&td->lock); |
826 | 1066 | ||
@@ -837,10 +1077,52 @@ static void taal_framedone_cb(int err, void *data) | |||
837 | dsi_bus_unlock(); | 1077 | dsi_bus_unlock(); |
838 | } | 1078 | } |
839 | 1079 | ||
1080 | static irqreturn_t taal_te_isr(int irq, void *data) | ||
1081 | { | ||
1082 | struct omap_dss_device *dssdev = data; | ||
1083 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1084 | int old; | ||
1085 | int r; | ||
1086 | |||
1087 | old = atomic_cmpxchg(&td->do_update, 1, 0); | ||
1088 | |||
1089 | if (old) { | ||
1090 | cancel_delayed_work(&td->te_timeout_work); | ||
1091 | |||
1092 | r = omap_dsi_update(dssdev, TCH, | ||
1093 | td->update_region.x, | ||
1094 | td->update_region.y, | ||
1095 | td->update_region.w, | ||
1096 | td->update_region.h, | ||
1097 | taal_framedone_cb, dssdev); | ||
1098 | if (r) | ||
1099 | goto err; | ||
1100 | } | ||
1101 | |||
1102 | return IRQ_HANDLED; | ||
1103 | err: | ||
1104 | dev_err(&dssdev->dev, "start update failed\n"); | ||
1105 | dsi_bus_unlock(); | ||
1106 | return IRQ_HANDLED; | ||
1107 | } | ||
1108 | |||
1109 | static void taal_te_timeout_work_callback(struct work_struct *work) | ||
1110 | { | ||
1111 | struct taal_data *td = container_of(work, struct taal_data, | ||
1112 | te_timeout_work.work); | ||
1113 | struct omap_dss_device *dssdev = td->dssdev; | ||
1114 | |||
1115 | dev_err(&dssdev->dev, "TE not received for 250ms!\n"); | ||
1116 | |||
1117 | atomic_set(&td->do_update, 0); | ||
1118 | dsi_bus_unlock(); | ||
1119 | } | ||
1120 | |||
840 | static int taal_update(struct omap_dss_device *dssdev, | 1121 | static int taal_update(struct omap_dss_device *dssdev, |
841 | u16 x, u16 y, u16 w, u16 h) | 1122 | u16 x, u16 y, u16 w, u16 h) |
842 | { | 1123 | { |
843 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1124 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1125 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
844 | int r; | 1126 | int r; |
845 | 1127 | ||
846 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 1128 | dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); |
@@ -853,7 +1135,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
853 | goto err; | 1135 | goto err; |
854 | } | 1136 | } |
855 | 1137 | ||
856 | r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h); | 1138 | r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true); |
857 | if (r) | 1139 | if (r) |
858 | goto err; | 1140 | goto err; |
859 | 1141 | ||
@@ -861,10 +1143,21 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
861 | if (r) | 1143 | if (r) |
862 | goto err; | 1144 | goto err; |
863 | 1145 | ||
864 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 1146 | if (td->te_enabled && panel_data->use_ext_te) { |
865 | taal_framedone_cb, dssdev); | 1147 | td->update_region.x = x; |
866 | if (r) | 1148 | td->update_region.y = y; |
867 | goto err; | 1149 | td->update_region.w = w; |
1150 | td->update_region.h = h; | ||
1151 | barrier(); | ||
1152 | schedule_delayed_work(&td->te_timeout_work, | ||
1153 | msecs_to_jiffies(250)); | ||
1154 | atomic_set(&td->do_update, 1); | ||
1155 | } else { | ||
1156 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | ||
1157 | taal_framedone_cb, dssdev); | ||
1158 | if (r) | ||
1159 | goto err; | ||
1160 | } | ||
868 | 1161 | ||
869 | /* note: no bus_unlock here. unlock is in framedone_cb */ | 1162 | /* note: no bus_unlock here. unlock is in framedone_cb */ |
870 | mutex_unlock(&td->lock); | 1163 | mutex_unlock(&td->lock); |
@@ -894,20 +1187,19 @@ static int taal_sync(struct omap_dss_device *dssdev) | |||
894 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 1187 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) |
895 | { | 1188 | { |
896 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1189 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1190 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
897 | int r; | 1191 | int r; |
898 | 1192 | ||
899 | td->te_enabled = enable; | ||
900 | |||
901 | if (enable) | 1193 | if (enable) |
902 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1194 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); |
903 | else | 1195 | else |
904 | r = taal_dcs_write_0(DCS_TEAR_OFF); | 1196 | r = taal_dcs_write_0(DCS_TEAR_OFF); |
905 | 1197 | ||
906 | omapdss_dsi_enable_te(dssdev, enable); | 1198 | if (!panel_data->use_ext_te) |
1199 | omapdss_dsi_enable_te(dssdev, enable); | ||
907 | 1200 | ||
908 | /* XXX for some reason, DSI TE breaks if we don't wait here. | 1201 | if (td->panel_config->sleep.enable_te) |
909 | * Panel bug? Needs more studying */ | 1202 | msleep(td->panel_config->sleep.enable_te); |
910 | msleep(100); | ||
911 | 1203 | ||
912 | return r; | 1204 | return r; |
913 | } | 1205 | } |
@@ -918,10 +1210,26 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
918 | int r; | 1210 | int r; |
919 | 1211 | ||
920 | mutex_lock(&td->lock); | 1212 | mutex_lock(&td->lock); |
1213 | |||
1214 | if (td->te_enabled == enable) | ||
1215 | goto end; | ||
1216 | |||
921 | dsi_bus_lock(); | 1217 | dsi_bus_lock(); |
922 | 1218 | ||
923 | r = _taal_enable_te(dssdev, enable); | 1219 | if (td->enabled) { |
1220 | r = _taal_enable_te(dssdev, enable); | ||
1221 | if (r) | ||
1222 | goto err; | ||
1223 | } | ||
1224 | |||
1225 | td->te_enabled = enable; | ||
1226 | |||
1227 | dsi_bus_unlock(); | ||
1228 | end: | ||
1229 | mutex_unlock(&td->lock); | ||
924 | 1230 | ||
1231 | return 0; | ||
1232 | err: | ||
925 | dsi_bus_unlock(); | 1233 | dsi_bus_unlock(); |
926 | mutex_unlock(&td->lock); | 1234 | mutex_unlock(&td->lock); |
927 | 1235 | ||
@@ -948,6 +1256,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
948 | dev_dbg(&dssdev->dev, "rotate %d\n", rotate); | 1256 | dev_dbg(&dssdev->dev, "rotate %d\n", rotate); |
949 | 1257 | ||
950 | mutex_lock(&td->lock); | 1258 | mutex_lock(&td->lock); |
1259 | |||
1260 | if (td->rotate == rotate) | ||
1261 | goto end; | ||
1262 | |||
951 | dsi_bus_lock(); | 1263 | dsi_bus_lock(); |
952 | 1264 | ||
953 | if (td->enabled) { | 1265 | if (td->enabled) { |
@@ -959,6 +1271,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
959 | td->rotate = rotate; | 1271 | td->rotate = rotate; |
960 | 1272 | ||
961 | dsi_bus_unlock(); | 1273 | dsi_bus_unlock(); |
1274 | end: | ||
962 | mutex_unlock(&td->lock); | 1275 | mutex_unlock(&td->lock); |
963 | return 0; | 1276 | return 0; |
964 | err: | 1277 | err: |
@@ -987,6 +1300,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
987 | dev_dbg(&dssdev->dev, "mirror %d\n", enable); | 1300 | dev_dbg(&dssdev->dev, "mirror %d\n", enable); |
988 | 1301 | ||
989 | mutex_lock(&td->lock); | 1302 | mutex_lock(&td->lock); |
1303 | |||
1304 | if (td->mirror == enable) | ||
1305 | goto end; | ||
1306 | |||
990 | dsi_bus_lock(); | 1307 | dsi_bus_lock(); |
991 | if (td->enabled) { | 1308 | if (td->enabled) { |
992 | r = taal_set_addr_mode(td->rotate, enable); | 1309 | r = taal_set_addr_mode(td->rotate, enable); |
@@ -997,6 +1314,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
997 | td->mirror = enable; | 1314 | td->mirror = enable; |
998 | 1315 | ||
999 | dsi_bus_unlock(); | 1316 | dsi_bus_unlock(); |
1317 | end: | ||
1000 | mutex_unlock(&td->lock); | 1318 | mutex_unlock(&td->lock); |
1001 | return 0; | 1319 | return 0; |
1002 | err: | 1320 | err: |
@@ -1024,23 +1342,30 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1024 | int r; | 1342 | int r; |
1025 | 1343 | ||
1026 | mutex_lock(&td->lock); | 1344 | mutex_lock(&td->lock); |
1345 | |||
1346 | if (!td->enabled) { | ||
1347 | r = -ENODEV; | ||
1348 | goto err1; | ||
1349 | } | ||
1350 | |||
1027 | dsi_bus_lock(); | 1351 | dsi_bus_lock(); |
1028 | 1352 | ||
1029 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 1353 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); |
1030 | if (r) | 1354 | if (r) |
1031 | goto err; | 1355 | goto err2; |
1032 | r = taal_dcs_read_1(DCS_GET_ID2, &id2); | 1356 | r = taal_dcs_read_1(DCS_GET_ID2, &id2); |
1033 | if (r) | 1357 | if (r) |
1034 | goto err; | 1358 | goto err2; |
1035 | r = taal_dcs_read_1(DCS_GET_ID3, &id3); | 1359 | r = taal_dcs_read_1(DCS_GET_ID3, &id3); |
1036 | if (r) | 1360 | if (r) |
1037 | goto err; | 1361 | goto err2; |
1038 | 1362 | ||
1039 | dsi_bus_unlock(); | 1363 | dsi_bus_unlock(); |
1040 | mutex_unlock(&td->lock); | 1364 | mutex_unlock(&td->lock); |
1041 | return 0; | 1365 | return 0; |
1042 | err: | 1366 | err2: |
1043 | dsi_bus_unlock(); | 1367 | dsi_bus_unlock(); |
1368 | err1: | ||
1044 | mutex_unlock(&td->lock); | 1369 | mutex_unlock(&td->lock); |
1045 | return r; | 1370 | return r; |
1046 | } | 1371 | } |
@@ -1128,6 +1453,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1128 | struct taal_data *td = container_of(work, struct taal_data, | 1453 | struct taal_data *td = container_of(work, struct taal_data, |
1129 | esd_work.work); | 1454 | esd_work.work); |
1130 | struct omap_dss_device *dssdev = td->dssdev; | 1455 | struct omap_dss_device *dssdev = td->dssdev; |
1456 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
1131 | u8 state1, state2; | 1457 | u8 state1, state2; |
1132 | int r; | 1458 | int r; |
1133 | 1459 | ||
@@ -1168,7 +1494,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1168 | } | 1494 | } |
1169 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1495 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1170 | * to re-enable TE after self diagnostics */ | 1496 | * to re-enable TE after self diagnostics */ |
1171 | if (td->use_ext_te && td->te_enabled) { | 1497 | if (td->te_enabled && panel_data->use_ext_te) { |
1172 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1498 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); |
1173 | if (r) | 1499 | if (r) |
1174 | goto err; | 1500 | goto err; |
@@ -1184,6 +1510,7 @@ err: | |||
1184 | dev_err(&dssdev->dev, "performing LCD reset\n"); | 1510 | dev_err(&dssdev->dev, "performing LCD reset\n"); |
1185 | 1511 | ||
1186 | taal_power_off(dssdev); | 1512 | taal_power_off(dssdev); |
1513 | taal_hw_reset(dssdev); | ||
1187 | taal_power_on(dssdev); | 1514 | taal_power_on(dssdev); |
1188 | 1515 | ||
1189 | dsi_bus_unlock(); | 1516 | dsi_bus_unlock(); |
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c index fa434ca6e4b7..e320e67d06f3 100644 --- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c +++ b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c | |||
@@ -73,8 +73,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev) | |||
73 | 73 | ||
74 | static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) | 74 | static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) |
75 | { | 75 | { |
76 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | 76 | dssdev->panel.config = OMAP_DSS_LCD_TFT | |
77 | OMAP_DSS_LCD_IHS; | 77 | OMAP_DSS_LCD_IVS | |
78 | OMAP_DSS_LCD_IHS | | ||
79 | OMAP_DSS_LCD_IPC | | ||
80 | OMAP_DSS_LCD_ONOFF; | ||
81 | |||
78 | dssdev->panel.timings = toppoly_tdo_panel_timings; | 82 | dssdev->panel.timings = toppoly_tdo_panel_timings; |
79 | 83 | ||
80 | return 0; | 84 | return 0; |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e777e352dbcd..5ecdc0004094 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/hardirq.h> | ||
34 | 35 | ||
35 | #include <plat/sram.h> | 36 | #include <plat/sram.h> |
36 | #include <plat/clock.h> | 37 | #include <plat/clock.h> |
@@ -335,7 +336,7 @@ void dispc_save_context(void) | |||
335 | void dispc_restore_context(void) | 336 | void dispc_restore_context(void) |
336 | { | 337 | { |
337 | RR(SYSCONFIG); | 338 | RR(SYSCONFIG); |
338 | RR(IRQENABLE); | 339 | /*RR(IRQENABLE);*/ |
339 | /*RR(CONTROL);*/ | 340 | /*RR(CONTROL);*/ |
340 | RR(CONFIG); | 341 | RR(CONFIG); |
341 | RR(DEFAULT_COLOR0); | 342 | RR(DEFAULT_COLOR0); |
@@ -472,6 +473,15 @@ void dispc_restore_context(void) | |||
472 | 473 | ||
473 | /* enable last, because LCD & DIGIT enable are here */ | 474 | /* enable last, because LCD & DIGIT enable are here */ |
474 | RR(CONTROL); | 475 | RR(CONTROL); |
476 | |||
477 | /* clear spurious SYNC_LOST_DIGIT interrupts */ | ||
478 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | ||
479 | |||
480 | /* | ||
481 | * enable last so IRQs won't trigger before | ||
482 | * the context is fully restored | ||
483 | */ | ||
484 | RR(IRQENABLE); | ||
475 | } | 485 | } |
476 | 486 | ||
477 | #undef SR | 487 | #undef SR |
@@ -3019,7 +3029,7 @@ void dispc_fake_vsync_irq(void) | |||
3019 | u32 irqstatus = DISPC_IRQ_VSYNC; | 3029 | u32 irqstatus = DISPC_IRQ_VSYNC; |
3020 | int i; | 3030 | int i; |
3021 | 3031 | ||
3022 | local_irq_disable(); | 3032 | WARN_ON(!in_interrupt()); |
3023 | 3033 | ||
3024 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { | 3034 | for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { |
3025 | struct omap_dispc_isr_data *isr_data; | 3035 | struct omap_dispc_isr_data *isr_data; |
@@ -3031,8 +3041,6 @@ void dispc_fake_vsync_irq(void) | |||
3031 | if (isr_data->mask & irqstatus) | 3041 | if (isr_data->mask & irqstatus) |
3032 | isr_data->isr(isr_data->arg, irqstatus); | 3042 | isr_data->isr(isr_data->arg, irqstatus); |
3033 | } | 3043 | } |
3034 | |||
3035 | local_irq_enable(); | ||
3036 | } | 3044 | } |
3037 | #endif | 3045 | #endif |
3038 | 3046 | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index ef8c8529dda2..22dd7a474f79 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev, | |||
82 | int val, r; | 82 | int val, r; |
83 | enum omap_dss_update_mode mode; | 83 | enum omap_dss_update_mode mode; |
84 | 84 | ||
85 | if (!dssdev->driver->set_update_mode) | ||
86 | return -EINVAL; | ||
87 | |||
85 | val = simple_strtoul(buf, NULL, 10); | 88 | val = simple_strtoul(buf, NULL, 10); |
86 | 89 | ||
87 | switch (val) { | 90 | switch (val) { |
@@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
343 | case OMAP_DISPLAY_TYPE_VENC: | 346 | case OMAP_DISPLAY_TYPE_VENC: |
344 | case OMAP_DISPLAY_TYPE_SDI: | 347 | case OMAP_DISPLAY_TYPE_SDI: |
345 | return 24; | 348 | return 24; |
346 | return 24; | ||
347 | default: | 349 | default: |
348 | BUG(); | 350 | BUG(); |
349 | } | 351 | } |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 3af207b2bde3..b3fa3a7db911 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -165,6 +165,14 @@ struct dsi_reg { u16 idx; }; | |||
165 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) | 165 | #define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) |
166 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) | 166 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) |
167 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) | 167 | #define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) |
168 | #define DSI_CIO_IRQ_ERROR_MASK \ | ||
169 | (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \ | ||
170 | DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \ | ||
171 | DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \ | ||
172 | DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \ | ||
173 | DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \ | ||
174 | DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \ | ||
175 | DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3) | ||
168 | 176 | ||
169 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 | 177 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 |
170 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 | 178 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 |
@@ -232,13 +240,15 @@ static struct | |||
232 | unsigned pll_locked; | 240 | unsigned pll_locked; |
233 | 241 | ||
234 | struct completion bta_completion; | 242 | struct completion bta_completion; |
243 | void (*bta_callback)(void); | ||
235 | 244 | ||
236 | int update_channel; | 245 | int update_channel; |
237 | struct dsi_update_region update_region; | 246 | struct dsi_update_region update_region; |
238 | 247 | ||
239 | bool te_enabled; | 248 | bool te_enabled; |
240 | 249 | ||
241 | struct work_struct framedone_work; | 250 | struct workqueue_struct *workqueue; |
251 | |||
242 | void (*framedone_callback)(int, void *); | 252 | void (*framedone_callback)(int, void *); |
243 | void *framedone_data; | 253 | void *framedone_data; |
244 | 254 | ||
@@ -509,9 +519,13 @@ void dsi_irq_handler(void) | |||
509 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | 519 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); |
510 | #endif | 520 | #endif |
511 | 521 | ||
512 | if (vcstatus & DSI_VC_IRQ_BTA) | 522 | if (vcstatus & DSI_VC_IRQ_BTA) { |
513 | complete(&dsi.bta_completion); | 523 | complete(&dsi.bta_completion); |
514 | 524 | ||
525 | if (dsi.bta_callback) | ||
526 | dsi.bta_callback(); | ||
527 | } | ||
528 | |||
515 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { | 529 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { |
516 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", | 530 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", |
517 | i, vcstatus); | 531 | i, vcstatus); |
@@ -536,8 +550,12 @@ void dsi_irq_handler(void) | |||
536 | /* flush posted write */ | 550 | /* flush posted write */ |
537 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 551 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
538 | 552 | ||
539 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | 553 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { |
540 | print_irq_status_cio(ciostatus); | 554 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); |
555 | print_irq_status_cio(ciostatus); | ||
556 | } else if (debug_irq) { | ||
557 | print_irq_status_cio(ciostatus); | ||
558 | } | ||
541 | } | 559 | } |
542 | 560 | ||
543 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 561 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); |
@@ -584,11 +602,8 @@ static void _dsi_initialize_irq(void) | |||
584 | for (i = 0; i < 4; ++i) | 602 | for (i = 0; i < 4; ++i) |
585 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); | 603 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); |
586 | 604 | ||
587 | /* XXX zonda responds incorrectly, causing control error: | 605 | l = DSI_CIO_IRQ_ERROR_MASK; |
588 | Exit from LP-ESC mode to LP11 uses wrong transition states on the | 606 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); |
589 | data lines LP0 and LN0. */ | ||
590 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, | ||
591 | -1 & (~DSI_CIO_IRQ_ERRCONTROL2)); | ||
592 | } | 607 | } |
593 | 608 | ||
594 | static u32 dsi_get_errors(void) | 609 | static u32 dsi_get_errors(void) |
@@ -1098,6 +1113,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1098 | if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { | 1113 | if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { |
1099 | DSSERR("PLL not coming out of reset.\n"); | 1114 | DSSERR("PLL not coming out of reset.\n"); |
1100 | r = -ENODEV; | 1115 | r = -ENODEV; |
1116 | dispc_pck_free_enable(0); | ||
1101 | goto err1; | 1117 | goto err1; |
1102 | } | 1118 | } |
1103 | 1119 | ||
@@ -1740,42 +1756,52 @@ static void dsi_vc_initial_config(int channel) | |||
1740 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | 1756 | dsi.vc[channel].mode = DSI_VC_MODE_L4; |
1741 | } | 1757 | } |
1742 | 1758 | ||
1743 | static void dsi_vc_config_l4(int channel) | 1759 | static int dsi_vc_config_l4(int channel) |
1744 | { | 1760 | { |
1745 | if (dsi.vc[channel].mode == DSI_VC_MODE_L4) | 1761 | if (dsi.vc[channel].mode == DSI_VC_MODE_L4) |
1746 | return; | 1762 | return 0; |
1747 | 1763 | ||
1748 | DSSDBGF("%d", channel); | 1764 | DSSDBGF("%d", channel); |
1749 | 1765 | ||
1750 | dsi_vc_enable(channel, 0); | 1766 | dsi_vc_enable(channel, 0); |
1751 | 1767 | ||
1752 | if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ | 1768 | /* VC_BUSY */ |
1769 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | ||
1753 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); | 1770 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); |
1771 | return -EIO; | ||
1772 | } | ||
1754 | 1773 | ||
1755 | REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ | 1774 | REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ |
1756 | 1775 | ||
1757 | dsi_vc_enable(channel, 1); | 1776 | dsi_vc_enable(channel, 1); |
1758 | 1777 | ||
1759 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | 1778 | dsi.vc[channel].mode = DSI_VC_MODE_L4; |
1779 | |||
1780 | return 0; | ||
1760 | } | 1781 | } |
1761 | 1782 | ||
1762 | static void dsi_vc_config_vp(int channel) | 1783 | static int dsi_vc_config_vp(int channel) |
1763 | { | 1784 | { |
1764 | if (dsi.vc[channel].mode == DSI_VC_MODE_VP) | 1785 | if (dsi.vc[channel].mode == DSI_VC_MODE_VP) |
1765 | return; | 1786 | return 0; |
1766 | 1787 | ||
1767 | DSSDBGF("%d", channel); | 1788 | DSSDBGF("%d", channel); |
1768 | 1789 | ||
1769 | dsi_vc_enable(channel, 0); | 1790 | dsi_vc_enable(channel, 0); |
1770 | 1791 | ||
1771 | if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ | 1792 | /* VC_BUSY */ |
1793 | if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) { | ||
1772 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); | 1794 | DSSERR("vc(%d) busy when trying to config for VP\n", channel); |
1795 | return -EIO; | ||
1796 | } | ||
1773 | 1797 | ||
1774 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ | 1798 | REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ |
1775 | 1799 | ||
1776 | dsi_vc_enable(channel, 1); | 1800 | dsi_vc_enable(channel, 1); |
1777 | 1801 | ||
1778 | dsi.vc[channel].mode = DSI_VC_MODE_VP; | 1802 | dsi.vc[channel].mode = DSI_VC_MODE_VP; |
1803 | |||
1804 | return 0; | ||
1779 | } | 1805 | } |
1780 | 1806 | ||
1781 | 1807 | ||
@@ -1854,19 +1880,19 @@ static u16 dsi_vc_flush_receive_data(int channel) | |||
1854 | u32 val; | 1880 | u32 val; |
1855 | u8 dt; | 1881 | u8 dt; |
1856 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); | 1882 | val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); |
1857 | DSSDBG("\trawval %#08x\n", val); | 1883 | DSSERR("\trawval %#08x\n", val); |
1858 | dt = FLD_GET(val, 5, 0); | 1884 | dt = FLD_GET(val, 5, 0); |
1859 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 1885 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { |
1860 | u16 err = FLD_GET(val, 23, 8); | 1886 | u16 err = FLD_GET(val, 23, 8); |
1861 | dsi_show_rx_ack_with_err(err); | 1887 | dsi_show_rx_ack_with_err(err); |
1862 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 1888 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { |
1863 | DSSDBG("\tDCS short response, 1 byte: %#x\n", | 1889 | DSSERR("\tDCS short response, 1 byte: %#x\n", |
1864 | FLD_GET(val, 23, 8)); | 1890 | FLD_GET(val, 23, 8)); |
1865 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 1891 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { |
1866 | DSSDBG("\tDCS short response, 2 byte: %#x\n", | 1892 | DSSERR("\tDCS short response, 2 byte: %#x\n", |
1867 | FLD_GET(val, 23, 8)); | 1893 | FLD_GET(val, 23, 8)); |
1868 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 1894 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { |
1869 | DSSDBG("\tDCS long response, len %d\n", | 1895 | DSSERR("\tDCS long response, len %d\n", |
1870 | FLD_GET(val, 23, 8)); | 1896 | FLD_GET(val, 23, 8)); |
1871 | dsi_vc_flush_long_data(channel); | 1897 | dsi_vc_flush_long_data(channel); |
1872 | } else { | 1898 | } else { |
@@ -2087,6 +2113,13 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len) | |||
2087 | if (r) | 2113 | if (r) |
2088 | goto err; | 2114 | goto err; |
2089 | 2115 | ||
2116 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ | ||
2117 | DSSERR("rx fifo not empty after write, dumping data:\n"); | ||
2118 | dsi_vc_flush_receive_data(channel); | ||
2119 | r = -EIO; | ||
2120 | goto err; | ||
2121 | } | ||
2122 | |||
2090 | return 0; | 2123 | return 0; |
2091 | err: | 2124 | err: |
2092 | DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", | 2125 | DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", |
@@ -2233,11 +2266,12 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data) | |||
2233 | } | 2266 | } |
2234 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); | 2267 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); |
2235 | 2268 | ||
2236 | int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data) | 2269 | int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2) |
2237 | { | 2270 | { |
2271 | u8 buf[2]; | ||
2238 | int r; | 2272 | int r; |
2239 | 2273 | ||
2240 | r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2); | 2274 | r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2); |
2241 | 2275 | ||
2242 | if (r < 0) | 2276 | if (r < 0) |
2243 | return r; | 2277 | return r; |
@@ -2245,231 +2279,122 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data) | |||
2245 | if (r != 2) | 2279 | if (r != 2) |
2246 | return -EIO; | 2280 | return -EIO; |
2247 | 2281 | ||
2282 | *data1 = buf[0]; | ||
2283 | *data2 = buf[1]; | ||
2284 | |||
2248 | return 0; | 2285 | return 0; |
2249 | } | 2286 | } |
2250 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); | 2287 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); |
2251 | 2288 | ||
2252 | int dsi_vc_set_max_rx_packet_size(int channel, u16 len) | 2289 | int dsi_vc_set_max_rx_packet_size(int channel, u16 len) |
2253 | { | 2290 | { |
2254 | int r; | 2291 | return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, |
2255 | r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | ||
2256 | len, 0); | 2292 | len, 0); |
2257 | |||
2258 | if (r) | ||
2259 | return r; | ||
2260 | |||
2261 | r = dsi_vc_send_bta_sync(channel); | ||
2262 | |||
2263 | return r; | ||
2264 | } | 2293 | } |
2265 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); | 2294 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); |
2266 | 2295 | ||
2267 | static void dsi_set_lp_rx_timeout(unsigned long ns) | 2296 | static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16) |
2268 | { | 2297 | { |
2269 | u32 r; | ||
2270 | unsigned x4, x16; | ||
2271 | unsigned long fck; | 2298 | unsigned long fck; |
2272 | unsigned long ticks; | 2299 | unsigned long total_ticks; |
2300 | u32 r; | ||
2273 | 2301 | ||
2274 | /* ticks in DSI_FCK */ | 2302 | BUG_ON(ticks > 0x1fff); |
2275 | 2303 | ||
2304 | /* ticks in DSI_FCK */ | ||
2276 | fck = dsi_fclk_rate(); | 2305 | fck = dsi_fclk_rate(); |
2277 | ticks = (fck / 1000 / 1000) * ns / 1000; | ||
2278 | x4 = 0; | ||
2279 | x16 = 0; | ||
2280 | |||
2281 | if (ticks > 0x1fff) { | ||
2282 | ticks = (fck / 1000 / 1000) * ns / 1000 / 4; | ||
2283 | x4 = 1; | ||
2284 | x16 = 0; | ||
2285 | } | ||
2286 | |||
2287 | if (ticks > 0x1fff) { | ||
2288 | ticks = (fck / 1000 / 1000) * ns / 1000 / 16; | ||
2289 | x4 = 0; | ||
2290 | x16 = 1; | ||
2291 | } | ||
2292 | |||
2293 | if (ticks > 0x1fff) { | ||
2294 | ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); | ||
2295 | x4 = 1; | ||
2296 | x16 = 1; | ||
2297 | } | ||
2298 | |||
2299 | if (ticks > 0x1fff) { | ||
2300 | DSSWARN("LP_TX_TO over limit, setting it to max\n"); | ||
2301 | ticks = 0x1fff; | ||
2302 | x4 = 1; | ||
2303 | x16 = 1; | ||
2304 | } | ||
2305 | 2306 | ||
2306 | r = dsi_read_reg(DSI_TIMING2); | 2307 | r = dsi_read_reg(DSI_TIMING2); |
2307 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ | 2308 | r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ |
2308 | r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ | 2309 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */ |
2309 | r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ | 2310 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */ |
2310 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ | 2311 | r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ |
2311 | dsi_write_reg(DSI_TIMING2, r); | 2312 | dsi_write_reg(DSI_TIMING2, r); |
2312 | 2313 | ||
2313 | DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n", | 2314 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2314 | (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / | 2315 | |
2315 | (fck / 1000 / 1000), | 2316 | DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n", |
2316 | ticks, x4 ? " x4" : "", x16 ? " x16" : ""); | 2317 | total_ticks, |
2318 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", | ||
2319 | (total_ticks * 1000) / (fck / 1000 / 1000)); | ||
2317 | } | 2320 | } |
2318 | 2321 | ||
2319 | static void dsi_set_ta_timeout(unsigned long ns) | 2322 | static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16) |
2320 | { | 2323 | { |
2321 | u32 r; | ||
2322 | unsigned x8, x16; | ||
2323 | unsigned long fck; | 2324 | unsigned long fck; |
2324 | unsigned long ticks; | 2325 | unsigned long total_ticks; |
2326 | u32 r; | ||
2327 | |||
2328 | BUG_ON(ticks > 0x1fff); | ||
2325 | 2329 | ||
2326 | /* ticks in DSI_FCK */ | 2330 | /* ticks in DSI_FCK */ |
2327 | fck = dsi_fclk_rate(); | 2331 | fck = dsi_fclk_rate(); |
2328 | ticks = (fck / 1000 / 1000) * ns / 1000; | ||
2329 | x8 = 0; | ||
2330 | x16 = 0; | ||
2331 | |||
2332 | if (ticks > 0x1fff) { | ||
2333 | ticks = (fck / 1000 / 1000) * ns / 1000 / 8; | ||
2334 | x8 = 1; | ||
2335 | x16 = 0; | ||
2336 | } | ||
2337 | |||
2338 | if (ticks > 0x1fff) { | ||
2339 | ticks = (fck / 1000 / 1000) * ns / 1000 / 16; | ||
2340 | x8 = 0; | ||
2341 | x16 = 1; | ||
2342 | } | ||
2343 | |||
2344 | if (ticks > 0x1fff) { | ||
2345 | ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16); | ||
2346 | x8 = 1; | ||
2347 | x16 = 1; | ||
2348 | } | ||
2349 | |||
2350 | if (ticks > 0x1fff) { | ||
2351 | DSSWARN("TA_TO over limit, setting it to max\n"); | ||
2352 | ticks = 0x1fff; | ||
2353 | x8 = 1; | ||
2354 | x16 = 1; | ||
2355 | } | ||
2356 | 2332 | ||
2357 | r = dsi_read_reg(DSI_TIMING1); | 2333 | r = dsi_read_reg(DSI_TIMING1); |
2358 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ | 2334 | r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ |
2359 | r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ | 2335 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */ |
2360 | r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ | 2336 | r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */ |
2361 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ | 2337 | r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ |
2362 | dsi_write_reg(DSI_TIMING1, r); | 2338 | dsi_write_reg(DSI_TIMING1, r); |
2363 | 2339 | ||
2364 | DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n", | 2340 | total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1); |
2365 | (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / | 2341 | |
2366 | (fck / 1000 / 1000), | 2342 | DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n", |
2367 | ticks, x8 ? " x8" : "", x16 ? " x16" : ""); | 2343 | total_ticks, |
2344 | ticks, x8 ? " x8" : "", x16 ? " x16" : "", | ||
2345 | (total_ticks * 1000) / (fck / 1000 / 1000)); | ||
2368 | } | 2346 | } |
2369 | 2347 | ||
2370 | static void dsi_set_stop_state_counter(unsigned long ns) | 2348 | static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16) |
2371 | { | 2349 | { |
2372 | u32 r; | ||
2373 | unsigned x4, x16; | ||
2374 | unsigned long fck; | 2350 | unsigned long fck; |
2375 | unsigned long ticks; | 2351 | unsigned long total_ticks; |
2352 | u32 r; | ||
2376 | 2353 | ||
2377 | /* ticks in DSI_FCK */ | 2354 | BUG_ON(ticks > 0x1fff); |
2378 | 2355 | ||
2356 | /* ticks in DSI_FCK */ | ||
2379 | fck = dsi_fclk_rate(); | 2357 | fck = dsi_fclk_rate(); |
2380 | ticks = (fck / 1000 / 1000) * ns / 1000; | ||
2381 | x4 = 0; | ||
2382 | x16 = 0; | ||
2383 | |||
2384 | if (ticks > 0x1fff) { | ||
2385 | ticks = (fck / 1000 / 1000) * ns / 1000 / 4; | ||
2386 | x4 = 1; | ||
2387 | x16 = 0; | ||
2388 | } | ||
2389 | |||
2390 | if (ticks > 0x1fff) { | ||
2391 | ticks = (fck / 1000 / 1000) * ns / 1000 / 16; | ||
2392 | x4 = 0; | ||
2393 | x16 = 1; | ||
2394 | } | ||
2395 | |||
2396 | if (ticks > 0x1fff) { | ||
2397 | ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); | ||
2398 | x4 = 1; | ||
2399 | x16 = 1; | ||
2400 | } | ||
2401 | |||
2402 | if (ticks > 0x1fff) { | ||
2403 | DSSWARN("STOP_STATE_COUNTER_IO over limit, " | ||
2404 | "setting it to max\n"); | ||
2405 | ticks = 0x1fff; | ||
2406 | x4 = 1; | ||
2407 | x16 = 1; | ||
2408 | } | ||
2409 | 2358 | ||
2410 | r = dsi_read_reg(DSI_TIMING1); | 2359 | r = dsi_read_reg(DSI_TIMING1); |
2411 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ | 2360 | r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ |
2412 | r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ | 2361 | r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */ |
2413 | r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ | 2362 | r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */ |
2414 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ | 2363 | r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ |
2415 | dsi_write_reg(DSI_TIMING1, r); | 2364 | dsi_write_reg(DSI_TIMING1, r); |
2416 | 2365 | ||
2417 | DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n", | 2366 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2418 | (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / | 2367 | |
2419 | (fck / 1000 / 1000), | 2368 | DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n", |
2420 | ticks, x4 ? " x4" : "", x16 ? " x16" : ""); | 2369 | total_ticks, |
2370 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", | ||
2371 | (total_ticks * 1000) / (fck / 1000 / 1000)); | ||
2421 | } | 2372 | } |
2422 | 2373 | ||
2423 | static void dsi_set_hs_tx_timeout(unsigned long ns) | 2374 | static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16) |
2424 | { | 2375 | { |
2425 | u32 r; | ||
2426 | unsigned x4, x16; | ||
2427 | unsigned long fck; | 2376 | unsigned long fck; |
2428 | unsigned long ticks; | 2377 | unsigned long total_ticks; |
2378 | u32 r; | ||
2429 | 2379 | ||
2430 | /* ticks in TxByteClkHS */ | 2380 | BUG_ON(ticks > 0x1fff); |
2431 | 2381 | ||
2382 | /* ticks in TxByteClkHS */ | ||
2432 | fck = dsi_get_txbyteclkhs(); | 2383 | fck = dsi_get_txbyteclkhs(); |
2433 | ticks = (fck / 1000 / 1000) * ns / 1000; | ||
2434 | x4 = 0; | ||
2435 | x16 = 0; | ||
2436 | |||
2437 | if (ticks > 0x1fff) { | ||
2438 | ticks = (fck / 1000 / 1000) * ns / 1000 / 4; | ||
2439 | x4 = 1; | ||
2440 | x16 = 0; | ||
2441 | } | ||
2442 | |||
2443 | if (ticks > 0x1fff) { | ||
2444 | ticks = (fck / 1000 / 1000) * ns / 1000 / 16; | ||
2445 | x4 = 0; | ||
2446 | x16 = 1; | ||
2447 | } | ||
2448 | |||
2449 | if (ticks > 0x1fff) { | ||
2450 | ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16); | ||
2451 | x4 = 1; | ||
2452 | x16 = 1; | ||
2453 | } | ||
2454 | |||
2455 | if (ticks > 0x1fff) { | ||
2456 | DSSWARN("HS_TX_TO over limit, setting it to max\n"); | ||
2457 | ticks = 0x1fff; | ||
2458 | x4 = 1; | ||
2459 | x16 = 1; | ||
2460 | } | ||
2461 | 2384 | ||
2462 | r = dsi_read_reg(DSI_TIMING2); | 2385 | r = dsi_read_reg(DSI_TIMING2); |
2463 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ | 2386 | r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ |
2464 | r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ | 2387 | r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */ |
2465 | r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ | 2388 | r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */ |
2466 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ | 2389 | r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ |
2467 | dsi_write_reg(DSI_TIMING2, r); | 2390 | dsi_write_reg(DSI_TIMING2, r); |
2468 | 2391 | ||
2469 | DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n", | 2392 | total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1); |
2470 | (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / | 2393 | |
2471 | (fck / 1000 / 1000), | 2394 | DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n", |
2472 | ticks, x4 ? " x4" : "", x16 ? " x16" : ""); | 2395 | total_ticks, |
2396 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", | ||
2397 | (total_ticks * 1000) / (fck / 1000 / 1000)); | ||
2473 | } | 2398 | } |
2474 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 2399 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
2475 | { | 2400 | { |
@@ -2487,10 +2412,10 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
2487 | DSI_FIFO_SIZE_32); | 2412 | DSI_FIFO_SIZE_32); |
2488 | 2413 | ||
2489 | /* XXX what values for the timeouts? */ | 2414 | /* XXX what values for the timeouts? */ |
2490 | dsi_set_stop_state_counter(1000); | 2415 | dsi_set_stop_state_counter(0x1000, false, false); |
2491 | dsi_set_ta_timeout(6400000); | 2416 | dsi_set_ta_timeout(0x1fff, true, true); |
2492 | dsi_set_lp_rx_timeout(48000); | 2417 | dsi_set_lp_rx_timeout(0x1fff, true, true); |
2493 | dsi_set_hs_tx_timeout(1000000); | 2418 | dsi_set_hs_tx_timeout(0x1fff, true, true); |
2494 | 2419 | ||
2495 | switch (dssdev->ctrl.pixel_size) { | 2420 | switch (dssdev->ctrl.pixel_size) { |
2496 | case 16: | 2421 | case 16: |
@@ -2759,6 +2684,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
2759 | unsigned packet_payload; | 2684 | unsigned packet_payload; |
2760 | unsigned packet_len; | 2685 | unsigned packet_len; |
2761 | u32 l; | 2686 | u32 l; |
2687 | int r; | ||
2762 | const unsigned channel = dsi.update_channel; | 2688 | const unsigned channel = dsi.update_channel; |
2763 | /* line buffer is 1024 x 24bits */ | 2689 | /* line buffer is 1024 x 24bits */ |
2764 | /* XXX: for some reason using full buffer size causes considerable TX | 2690 | /* XXX: for some reason using full buffer size causes considerable TX |
@@ -2809,8 +2735,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
2809 | 2735 | ||
2810 | dsi_perf_mark_start(); | 2736 | dsi_perf_mark_start(); |
2811 | 2737 | ||
2812 | schedule_delayed_work(&dsi.framedone_timeout_work, | 2738 | r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work, |
2813 | msecs_to_jiffies(250)); | 2739 | msecs_to_jiffies(250)); |
2740 | BUG_ON(r == 0); | ||
2814 | 2741 | ||
2815 | dss_start_update(dssdev); | 2742 | dss_start_update(dssdev); |
2816 | 2743 | ||
@@ -2834,62 +2761,70 @@ static void dsi_te_timeout(unsigned long arg) | |||
2834 | } | 2761 | } |
2835 | #endif | 2762 | #endif |
2836 | 2763 | ||
2837 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) | 2764 | static void dsi_handle_framedone(int error) |
2838 | { | 2765 | { |
2839 | int r; | ||
2840 | const int channel = dsi.update_channel; | 2766 | const int channel = dsi.update_channel; |
2841 | 2767 | ||
2842 | DSSERR("Framedone not received for 250ms!\n"); | 2768 | cancel_delayed_work(&dsi.framedone_timeout_work); |
2769 | |||
2770 | dsi_vc_disable_bta_irq(channel); | ||
2843 | 2771 | ||
2844 | /* SIDLEMODE back to smart-idle */ | 2772 | /* SIDLEMODE back to smart-idle */ |
2845 | dispc_enable_sidle(); | 2773 | dispc_enable_sidle(); |
2846 | 2774 | ||
2775 | dsi.bta_callback = NULL; | ||
2776 | |||
2847 | if (dsi.te_enabled) { | 2777 | if (dsi.te_enabled) { |
2848 | /* enable LP_RX_TO again after the TE */ | 2778 | /* enable LP_RX_TO again after the TE */ |
2849 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 2779 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
2850 | } | 2780 | } |
2851 | 2781 | ||
2852 | /* Send BTA after the frame. We need this for the TE to work, as TE | ||
2853 | * trigger is only sent for BTAs without preceding packet. Thus we need | ||
2854 | * to BTA after the pixel packets so that next BTA will cause TE | ||
2855 | * trigger. | ||
2856 | * | ||
2857 | * This is not needed when TE is not in use, but we do it anyway to | ||
2858 | * make sure that the transfer has been completed. It would be more | ||
2859 | * optimal, but more complex, to wait only just before starting next | ||
2860 | * transfer. */ | ||
2861 | r = dsi_vc_send_bta_sync(channel); | ||
2862 | if (r) | ||
2863 | DSSERR("BTA after framedone failed\n"); | ||
2864 | |||
2865 | /* RX_FIFO_NOT_EMPTY */ | 2782 | /* RX_FIFO_NOT_EMPTY */ |
2866 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2783 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { |
2867 | DSSERR("Received error during frame transfer:\n"); | 2784 | DSSERR("Received error during frame transfer:\n"); |
2868 | dsi_vc_flush_receive_data(channel); | 2785 | dsi_vc_flush_receive_data(channel); |
2786 | if (!error) | ||
2787 | error = -EIO; | ||
2869 | } | 2788 | } |
2870 | 2789 | ||
2871 | dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data); | 2790 | dsi.framedone_callback(error, dsi.framedone_data); |
2791 | |||
2792 | if (!error) | ||
2793 | dsi_perf_show("DISPC"); | ||
2872 | } | 2794 | } |
2873 | 2795 | ||
2874 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 2796 | static void dsi_framedone_timeout_work_callback(struct work_struct *work) |
2875 | { | 2797 | { |
2876 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and | 2798 | /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after |
2877 | * turns itself off. However, DSI still has the pixels in its buffers, | 2799 | * 250ms which would conflict with this timeout work. What should be |
2878 | * and is sending the data. | 2800 | * done is first cancel the transfer on the HW, and then cancel the |
2879 | */ | 2801 | * possibly scheduled framedone work. However, cancelling the transfer |
2802 | * on the HW is buggy, and would probably require resetting the whole | ||
2803 | * DSI */ | ||
2880 | 2804 | ||
2881 | /* SIDLEMODE back to smart-idle */ | 2805 | DSSERR("Framedone not received for 250ms!\n"); |
2882 | dispc_enable_sidle(); | ||
2883 | 2806 | ||
2884 | schedule_work(&dsi.framedone_work); | 2807 | dsi_handle_framedone(-ETIMEDOUT); |
2885 | } | 2808 | } |
2886 | 2809 | ||
2887 | static void dsi_handle_framedone(void) | 2810 | static void dsi_framedone_bta_callback(void) |
2811 | { | ||
2812 | dsi_handle_framedone(0); | ||
2813 | |||
2814 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
2815 | dispc_fake_vsync_irq(); | ||
2816 | #endif | ||
2817 | } | ||
2818 | |||
2819 | static void dsi_framedone_irq_callback(void *data, u32 mask) | ||
2888 | { | 2820 | { |
2889 | int r; | ||
2890 | const int channel = dsi.update_channel; | 2821 | const int channel = dsi.update_channel; |
2822 | int r; | ||
2891 | 2823 | ||
2892 | DSSDBG("FRAMEDONE\n"); | 2824 | /* Note: We get FRAMEDONE when DISPC has finished sending pixels and |
2825 | * turns itself off. However, DSI still has the pixels in its buffers, | ||
2826 | * and is sending the data. | ||
2827 | */ | ||
2893 | 2828 | ||
2894 | if (dsi.te_enabled) { | 2829 | if (dsi.te_enabled) { |
2895 | /* enable LP_RX_TO again after the TE */ | 2830 | /* enable LP_RX_TO again after the TE */ |
@@ -2904,37 +2839,30 @@ static void dsi_handle_framedone(void) | |||
2904 | * This is not needed when TE is not in use, but we do it anyway to | 2839 | * This is not needed when TE is not in use, but we do it anyway to |
2905 | * make sure that the transfer has been completed. It would be more | 2840 | * make sure that the transfer has been completed. It would be more |
2906 | * optimal, but more complex, to wait only just before starting next | 2841 | * optimal, but more complex, to wait only just before starting next |
2907 | * transfer. */ | 2842 | * transfer. |
2908 | r = dsi_vc_send_bta_sync(channel); | 2843 | * |
2909 | if (r) | 2844 | * Also, as there's no interrupt telling when the transfer has been |
2910 | DSSERR("BTA after framedone failed\n"); | 2845 | * done and the channel could be reconfigured, the only way is to |
2911 | 2846 | * busyloop until TE_SIZE is zero. With BTA we can do this | |
2912 | /* RX_FIFO_NOT_EMPTY */ | 2847 | * asynchronously. |
2913 | if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { | 2848 | * */ |
2914 | DSSERR("Received error during frame transfer:\n"); | ||
2915 | dsi_vc_flush_receive_data(channel); | ||
2916 | } | ||
2917 | |||
2918 | #ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC | ||
2919 | dispc_fake_vsync_irq(); | ||
2920 | #endif | ||
2921 | } | ||
2922 | |||
2923 | static void dsi_framedone_work_callback(struct work_struct *work) | ||
2924 | { | ||
2925 | DSSDBGF(); | ||
2926 | 2849 | ||
2927 | cancel_delayed_work_sync(&dsi.framedone_timeout_work); | 2850 | dsi.bta_callback = dsi_framedone_bta_callback; |
2928 | 2851 | ||
2929 | dsi_handle_framedone(); | 2852 | barrier(); |
2930 | 2853 | ||
2931 | dsi_perf_show("DISPC"); | 2854 | dsi_vc_enable_bta_irq(channel); |
2932 | 2855 | ||
2933 | dsi.framedone_callback(0, dsi.framedone_data); | 2856 | r = dsi_vc_send_bta(channel); |
2857 | if (r) { | ||
2858 | DSSERR("BTA after framedone failed\n"); | ||
2859 | dsi_handle_framedone(-EIO); | ||
2860 | } | ||
2934 | } | 2861 | } |
2935 | 2862 | ||
2936 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | 2863 | int omap_dsi_prepare_update(struct omap_dss_device *dssdev, |
2937 | u16 *x, u16 *y, u16 *w, u16 *h) | 2864 | u16 *x, u16 *y, u16 *w, u16 *h, |
2865 | bool enlarge_update_area) | ||
2938 | { | 2866 | { |
2939 | u16 dw, dh; | 2867 | u16 dw, dh; |
2940 | 2868 | ||
@@ -2958,7 +2886,8 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
2958 | dsi_perf_mark_setup(); | 2886 | dsi_perf_mark_setup(); |
2959 | 2887 | ||
2960 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 2888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
2961 | dss_setup_partial_planes(dssdev, x, y, w, h); | 2889 | dss_setup_partial_planes(dssdev, x, y, w, h, |
2890 | enlarge_update_area); | ||
2962 | dispc_set_lcd_size(*w, *h); | 2891 | dispc_set_lcd_size(*w, *h); |
2963 | } | 2892 | } |
2964 | 2893 | ||
@@ -2973,6 +2902,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
2973 | { | 2902 | { |
2974 | dsi.update_channel = channel; | 2903 | dsi.update_channel = channel; |
2975 | 2904 | ||
2905 | /* OMAP DSS cannot send updates of odd widths. | ||
2906 | * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON | ||
2907 | * here to make sure we catch erroneous updates. Otherwise we'll only | ||
2908 | * see rather obscure HW error happening, as DSS halts. */ | ||
2909 | BUG_ON(x % 2 == 1); | ||
2910 | |||
2976 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 2911 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
2977 | dsi.framedone_callback = callback; | 2912 | dsi.framedone_callback = callback; |
2978 | dsi.framedone_data = data; | 2913 | dsi.framedone_data = data; |
@@ -2985,7 +2920,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
2985 | 2920 | ||
2986 | dsi_update_screen_dispc(dssdev, x, y, w, h); | 2921 | dsi_update_screen_dispc(dssdev, x, y, w, h); |
2987 | } else { | 2922 | } else { |
2988 | dsi_update_screen_l4(dssdev, x, y, w, h); | 2923 | int r; |
2924 | |||
2925 | r = dsi_update_screen_l4(dssdev, x, y, w, h); | ||
2926 | if (r) | ||
2927 | return r; | ||
2928 | |||
2989 | dsi_perf_show("L4"); | 2929 | dsi_perf_show("L4"); |
2990 | callback(0, data); | 2930 | callback(0, data); |
2991 | } | 2931 | } |
@@ -3048,8 +2988,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
3048 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 2988 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; |
3049 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 2989 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; |
3050 | r = dsi_calc_clock_rates(&cinfo); | 2990 | r = dsi_calc_clock_rates(&cinfo); |
3051 | if (r) | 2991 | if (r) { |
2992 | DSSERR("Failed to calc dsi clocks\n"); | ||
3052 | return r; | 2993 | return r; |
2994 | } | ||
3053 | 2995 | ||
3054 | r = dsi_pll_set_clock_div(&cinfo); | 2996 | r = dsi_pll_set_clock_div(&cinfo); |
3055 | if (r) { | 2997 | if (r) { |
@@ -3147,6 +3089,13 @@ err0: | |||
3147 | 3089 | ||
3148 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | 3090 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) |
3149 | { | 3091 | { |
3092 | /* disable interface */ | ||
3093 | dsi_if_enable(0); | ||
3094 | dsi_vc_enable(0, 0); | ||
3095 | dsi_vc_enable(1, 0); | ||
3096 | dsi_vc_enable(2, 0); | ||
3097 | dsi_vc_enable(3, 0); | ||
3098 | |||
3150 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3099 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); |
3151 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3100 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); |
3152 | dsi_complexio_uninit(); | 3101 | dsi_complexio_uninit(); |
@@ -3257,7 +3206,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | |||
3257 | burst_size_bytes = 16 * 32 / 8; | 3206 | burst_size_bytes = 16 * 32 / 8; |
3258 | 3207 | ||
3259 | *fifo_high = fifo_size - burst_size_bytes; | 3208 | *fifo_high = fifo_size - burst_size_bytes; |
3260 | *fifo_low = fifo_size - burst_size_bytes * 8; | 3209 | *fifo_low = fifo_size - burst_size_bytes * 2; |
3261 | } | 3210 | } |
3262 | 3211 | ||
3263 | int dsi_init_display(struct omap_dss_device *dssdev) | 3212 | int dsi_init_display(struct omap_dss_device *dssdev) |
@@ -3274,6 +3223,18 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
3274 | return 0; | 3223 | return 0; |
3275 | } | 3224 | } |
3276 | 3225 | ||
3226 | void dsi_wait_dsi1_pll_active(void) | ||
3227 | { | ||
3228 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | ||
3229 | DSSERR("DSI1 PLL clock not active\n"); | ||
3230 | } | ||
3231 | |||
3232 | void dsi_wait_dsi2_pll_active(void) | ||
3233 | { | ||
3234 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | ||
3235 | DSSERR("DSI2 PLL clock not active\n"); | ||
3236 | } | ||
3237 | |||
3277 | int dsi_init(struct platform_device *pdev) | 3238 | int dsi_init(struct platform_device *pdev) |
3278 | { | 3239 | { |
3279 | u32 rev; | 3240 | u32 rev; |
@@ -3292,7 +3253,10 @@ int dsi_init(struct platform_device *pdev) | |||
3292 | mutex_init(&dsi.lock); | 3253 | mutex_init(&dsi.lock); |
3293 | sema_init(&dsi.bus_lock, 1); | 3254 | sema_init(&dsi.bus_lock, 1); |
3294 | 3255 | ||
3295 | INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback); | 3256 | dsi.workqueue = create_singlethread_workqueue("dsi"); |
3257 | if (dsi.workqueue == NULL) | ||
3258 | return -ENOMEM; | ||
3259 | |||
3296 | INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, | 3260 | INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, |
3297 | dsi_framedone_timeout_work_callback); | 3261 | dsi_framedone_timeout_work_callback); |
3298 | 3262 | ||
@@ -3328,6 +3292,7 @@ int dsi_init(struct platform_device *pdev) | |||
3328 | err2: | 3292 | err2: |
3329 | iounmap(dsi.base); | 3293 | iounmap(dsi.base); |
3330 | err1: | 3294 | err1: |
3295 | destroy_workqueue(dsi.workqueue); | ||
3331 | return r; | 3296 | return r; |
3332 | } | 3297 | } |
3333 | 3298 | ||
@@ -3335,6 +3300,8 @@ void dsi_exit(void) | |||
3335 | { | 3300 | { |
3336 | iounmap(dsi.base); | 3301 | iounmap(dsi.base); |
3337 | 3302 | ||
3303 | destroy_workqueue(dsi.workqueue); | ||
3304 | |||
3338 | DSSDBG("omap_dsi_exit\n"); | 3305 | DSSDBG("omap_dsi_exit\n"); |
3339 | } | 3306 | } |
3340 | 3307 | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 24b18258654f..77c3621c9171 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | |||
265 | 265 | ||
266 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | 266 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; |
267 | 267 | ||
268 | if (clk_src == DSS_SRC_DSI1_PLL_FCLK) | ||
269 | dsi_wait_dsi1_pll_active(); | ||
270 | |||
268 | REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ | 271 | REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ |
269 | 272 | ||
270 | dss.dispc_clk_source = clk_src; | 273 | dss.dispc_clk_source = clk_src; |
@@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | |||
279 | 282 | ||
280 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | 283 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; |
281 | 284 | ||
285 | if (clk_src == DSS_SRC_DSI2_PLL_FCLK) | ||
286 | dsi_wait_dsi2_pll_active(); | ||
287 | |||
282 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 288 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ |
283 | 289 | ||
284 | dss.dsi_clk_source = clk_src; | 290 | dss.dsi_clk_source = clk_src; |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 786f433fd571..5c7940d5f282 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev); | |||
199 | void dss_uninit_overlay_managers(struct platform_device *pdev); | 199 | void dss_uninit_overlay_managers(struct platform_device *pdev); |
200 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); | 200 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); |
201 | void dss_setup_partial_planes(struct omap_dss_device *dssdev, | 201 | void dss_setup_partial_planes(struct omap_dss_device *dssdev, |
202 | u16 *x, u16 *y, u16 *w, u16 *h); | 202 | u16 *x, u16 *y, u16 *w, u16 *h, |
203 | bool enlarge_update_area); | ||
203 | void dss_start_update(struct omap_dss_device *dssdev); | 204 | void dss_start_update(struct omap_dss_device *dssdev); |
204 | 205 | ||
205 | /* overlay */ | 206 | /* overlay */ |
@@ -281,6 +282,8 @@ void dsi_pll_uninit(void); | |||
281 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 282 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
282 | u32 fifo_size, enum omap_burst_size *burst_size, | 283 | u32 fifo_size, enum omap_burst_size *burst_size, |
283 | u32 *fifo_low, u32 *fifo_high); | 284 | u32 *fifo_low, u32 *fifo_high); |
285 | void dsi_wait_dsi1_pll_active(void); | ||
286 | void dsi_wait_dsi2_pll_active(void); | ||
284 | #else | 287 | #else |
285 | static inline int dsi_init(struct platform_device *pdev) | 288 | static inline int dsi_init(struct platform_device *pdev) |
286 | { | 289 | { |
@@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev) | |||
289 | static inline void dsi_exit(void) | 292 | static inline void dsi_exit(void) |
290 | { | 293 | { |
291 | } | 294 | } |
295 | static inline void dsi_wait_dsi1_pll_active(void) | ||
296 | { | ||
297 | } | ||
298 | static inline void dsi_wait_dsi2_pll_active(void) | ||
299 | { | ||
300 | } | ||
292 | #endif | 301 | #endif |
293 | 302 | ||
294 | /* DPI */ | 303 | /* DPI */ |
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 9e1fbe531bf0..6a649ab5539e 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -440,6 +440,10 @@ struct manager_cache_data { | |||
440 | 440 | ||
441 | /* manual update region */ | 441 | /* manual update region */ |
442 | u16 x, y, w, h; | 442 | u16 x, y, w, h; |
443 | |||
444 | /* enlarge the update area if the update area contains scaled | ||
445 | * overlays */ | ||
446 | bool enlarge_update_area; | ||
443 | }; | 447 | }; |
444 | 448 | ||
445 | static struct { | 449 | static struct { |
@@ -525,7 +529,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
525 | int i; | 529 | int i; |
526 | struct omap_dss_device *dssdev = mgr->device; | 530 | struct omap_dss_device *dssdev = mgr->device; |
527 | 531 | ||
528 | if (!dssdev) | 532 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
529 | return 0; | 533 | return 0; |
530 | 534 | ||
531 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 535 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { |
@@ -596,11 +600,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
596 | int r; | 600 | int r; |
597 | int i; | 601 | int i; |
598 | 602 | ||
599 | if (!ovl->manager || !ovl->manager->device) | 603 | if (!ovl->manager) |
600 | return 0; | 604 | return 0; |
601 | 605 | ||
602 | dssdev = ovl->manager->device; | 606 | dssdev = ovl->manager->device; |
603 | 607 | ||
608 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
609 | return 0; | ||
610 | |||
604 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 611 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { |
605 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 612 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
606 | channel = OMAP_DSS_CHANNEL_DIGIT; | 613 | channel = OMAP_DSS_CHANNEL_DIGIT; |
@@ -718,6 +725,7 @@ static int configure_overlay(enum omap_plane plane) | |||
718 | u16 x, y, w, h; | 725 | u16 x, y, w, h; |
719 | u32 paddr; | 726 | u32 paddr; |
720 | int r; | 727 | int r; |
728 | u16 orig_w, orig_h, orig_outw, orig_outh; | ||
721 | 729 | ||
722 | DSSDBGF("%d", plane); | 730 | DSSDBGF("%d", plane); |
723 | 731 | ||
@@ -738,8 +746,16 @@ static int configure_overlay(enum omap_plane plane) | |||
738 | outh = c->out_height == 0 ? c->height : c->out_height; | 746 | outh = c->out_height == 0 ? c->height : c->out_height; |
739 | paddr = c->paddr; | 747 | paddr = c->paddr; |
740 | 748 | ||
749 | orig_w = w; | ||
750 | orig_h = h; | ||
751 | orig_outw = outw; | ||
752 | orig_outh = outh; | ||
753 | |||
741 | if (c->manual_update && mc->do_manual_update) { | 754 | if (c->manual_update && mc->do_manual_update) { |
742 | unsigned bpp; | 755 | unsigned bpp; |
756 | unsigned scale_x_m = w, scale_x_d = outw; | ||
757 | unsigned scale_y_m = h, scale_y_d = outh; | ||
758 | |||
743 | /* If the overlay is outside the update region, disable it */ | 759 | /* If the overlay is outside the update region, disable it */ |
744 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, | 760 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, |
745 | x, y, outw, outh)) { | 761 | x, y, outw, outh)) { |
@@ -770,38 +786,47 @@ static int configure_overlay(enum omap_plane plane) | |||
770 | BUG(); | 786 | BUG(); |
771 | } | 787 | } |
772 | 788 | ||
773 | if (dispc_is_overlay_scaled(c)) { | 789 | if (mc->x > c->pos_x) { |
774 | /* If the overlay is scaled, the update area has | 790 | x = 0; |
775 | * already been enlarged to cover the whole overlay. We | 791 | outw -= (mc->x - c->pos_x); |
776 | * only need to adjust x/y here */ | 792 | paddr += (mc->x - c->pos_x) * |
777 | x = c->pos_x - mc->x; | 793 | scale_x_m / scale_x_d * bpp / 8; |
778 | y = c->pos_y - mc->y; | ||
779 | } else { | 794 | } else { |
780 | if (mc->x > c->pos_x) { | 795 | x = c->pos_x - mc->x; |
781 | x = 0; | 796 | } |
782 | w -= (mc->x - c->pos_x); | ||
783 | paddr += (mc->x - c->pos_x) * bpp / 8; | ||
784 | } else { | ||
785 | x = c->pos_x - mc->x; | ||
786 | } | ||
787 | |||
788 | if (mc->y > c->pos_y) { | ||
789 | y = 0; | ||
790 | h -= (mc->y - c->pos_y); | ||
791 | paddr += (mc->y - c->pos_y) * c->screen_width * | ||
792 | bpp / 8; | ||
793 | } else { | ||
794 | y = c->pos_y - mc->y; | ||
795 | } | ||
796 | |||
797 | if (mc->w < (x+w)) | ||
798 | w -= (x+w) - (mc->w); | ||
799 | 797 | ||
800 | if (mc->h < (y+h)) | 798 | if (mc->y > c->pos_y) { |
801 | h -= (y+h) - (mc->h); | 799 | y = 0; |
800 | outh -= (mc->y - c->pos_y); | ||
801 | paddr += (mc->y - c->pos_y) * | ||
802 | scale_y_m / scale_y_d * | ||
803 | c->screen_width * bpp / 8; | ||
804 | } else { | ||
805 | y = c->pos_y - mc->y; | ||
806 | } | ||
802 | 807 | ||
803 | outw = w; | 808 | if (mc->w < (x + outw)) |
804 | outh = h; | 809 | outw -= (x + outw) - (mc->w); |
810 | |||
811 | if (mc->h < (y + outh)) | ||
812 | outh -= (y + outh) - (mc->h); | ||
813 | |||
814 | w = w * outw / orig_outw; | ||
815 | h = h * outh / orig_outh; | ||
816 | |||
817 | /* YUV mode overlay's input width has to be even and the | ||
818 | * algorithm above may adjust the width to be odd. | ||
819 | * | ||
820 | * Here we adjust the width if needed, preferring to increase | ||
821 | * the width if the original width was bigger. | ||
822 | */ | ||
823 | if ((w & 1) && | ||
824 | (c->color_mode == OMAP_DSS_COLOR_YUV2 || | ||
825 | c->color_mode == OMAP_DSS_COLOR_UYVY)) { | ||
826 | if (orig_w > w) | ||
827 | w += 1; | ||
828 | else | ||
829 | w -= 1; | ||
805 | } | 830 | } |
806 | } | 831 | } |
807 | 832 | ||
@@ -960,7 +985,7 @@ static void make_even(u16 *x, u16 *w) | |||
960 | /* Configure dispc for partial update. Return possibly modified update | 985 | /* Configure dispc for partial update. Return possibly modified update |
961 | * area */ | 986 | * area */ |
962 | void dss_setup_partial_planes(struct omap_dss_device *dssdev, | 987 | void dss_setup_partial_planes(struct omap_dss_device *dssdev, |
963 | u16 *xi, u16 *yi, u16 *wi, u16 *hi) | 988 | u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area) |
964 | { | 989 | { |
965 | struct overlay_cache_data *oc; | 990 | struct overlay_cache_data *oc; |
966 | struct manager_cache_data *mc; | 991 | struct manager_cache_data *mc; |
@@ -969,6 +994,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, | |||
969 | int i; | 994 | int i; |
970 | u16 x, y, w, h; | 995 | u16 x, y, w, h; |
971 | unsigned long flags; | 996 | unsigned long flags; |
997 | bool area_changed; | ||
972 | 998 | ||
973 | x = *xi; | 999 | x = *xi; |
974 | y = *yi; | 1000 | y = *yi; |
@@ -989,73 +1015,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, | |||
989 | 1015 | ||
990 | spin_lock_irqsave(&dss_cache.lock, flags); | 1016 | spin_lock_irqsave(&dss_cache.lock, flags); |
991 | 1017 | ||
992 | /* We need to show the whole overlay if it is scaled. So look for | 1018 | /* |
993 | * those, and make the update area larger if found. | 1019 | * Execute the outer loop until the inner loop has completed |
994 | * Also mark the overlay cache dirty */ | 1020 | * once without increasing the update area. This will ensure that |
995 | for (i = 0; i < num_ovls; ++i) { | 1021 | * all scaled overlays end up completely within the update area. |
996 | unsigned x1, y1, x2, y2; | 1022 | */ |
997 | unsigned outw, outh; | 1023 | do { |
1024 | area_changed = false; | ||
998 | 1025 | ||
999 | oc = &dss_cache.overlay_cache[i]; | 1026 | /* We need to show the whole overlay if it is scaled. So look |
1027 | * for those, and make the update area larger if found. | ||
1028 | * Also mark the overlay cache dirty */ | ||
1029 | for (i = 0; i < num_ovls; ++i) { | ||
1030 | unsigned x1, y1, x2, y2; | ||
1031 | unsigned outw, outh; | ||
1000 | 1032 | ||
1001 | if (oc->channel != mgr->id) | 1033 | oc = &dss_cache.overlay_cache[i]; |
1002 | continue; | ||
1003 | 1034 | ||
1004 | oc->dirty = true; | 1035 | if (oc->channel != mgr->id) |
1036 | continue; | ||
1005 | 1037 | ||
1006 | if (!oc->enabled) | 1038 | oc->dirty = true; |
1007 | continue; | ||
1008 | 1039 | ||
1009 | if (!dispc_is_overlay_scaled(oc)) | 1040 | if (!enlarge_update_area) |
1010 | continue; | 1041 | continue; |
1011 | 1042 | ||
1012 | outw = oc->out_width == 0 ? oc->width : oc->out_width; | 1043 | if (!oc->enabled) |
1013 | outh = oc->out_height == 0 ? oc->height : oc->out_height; | 1044 | continue; |
1014 | 1045 | ||
1015 | /* is the overlay outside the update region? */ | 1046 | if (!dispc_is_overlay_scaled(oc)) |
1016 | if (!rectangle_intersects(x, y, w, h, | 1047 | continue; |
1017 | oc->pos_x, oc->pos_y, | ||
1018 | outw, outh)) | ||
1019 | continue; | ||
1020 | 1048 | ||
1021 | /* if the overlay totally inside the update region? */ | 1049 | outw = oc->out_width == 0 ? |
1022 | if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, | 1050 | oc->width : oc->out_width; |
1023 | x, y, w, h)) | 1051 | outh = oc->out_height == 0 ? |
1024 | continue; | 1052 | oc->height : oc->out_height; |
1053 | |||
1054 | /* is the overlay outside the update region? */ | ||
1055 | if (!rectangle_intersects(x, y, w, h, | ||
1056 | oc->pos_x, oc->pos_y, | ||
1057 | outw, outh)) | ||
1058 | continue; | ||
1025 | 1059 | ||
1026 | if (x > oc->pos_x) | 1060 | /* if the overlay totally inside the update region? */ |
1027 | x1 = oc->pos_x; | 1061 | if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, |
1028 | else | 1062 | x, y, w, h)) |
1029 | x1 = x; | 1063 | continue; |
1030 | 1064 | ||
1031 | if (y > oc->pos_y) | 1065 | if (x > oc->pos_x) |
1032 | y1 = oc->pos_y; | 1066 | x1 = oc->pos_x; |
1033 | else | 1067 | else |
1034 | y1 = y; | 1068 | x1 = x; |
1035 | 1069 | ||
1036 | if ((x + w) < (oc->pos_x + outw)) | 1070 | if (y > oc->pos_y) |
1037 | x2 = oc->pos_x + outw; | 1071 | y1 = oc->pos_y; |
1038 | else | 1072 | else |
1039 | x2 = x + w; | 1073 | y1 = y; |
1040 | 1074 | ||
1041 | if ((y + h) < (oc->pos_y + outh)) | 1075 | if ((x + w) < (oc->pos_x + outw)) |
1042 | y2 = oc->pos_y + outh; | 1076 | x2 = oc->pos_x + outw; |
1043 | else | 1077 | else |
1044 | y2 = y + h; | 1078 | x2 = x + w; |
1045 | 1079 | ||
1046 | x = x1; | 1080 | if ((y + h) < (oc->pos_y + outh)) |
1047 | y = y1; | 1081 | y2 = oc->pos_y + outh; |
1048 | w = x2 - x1; | 1082 | else |
1049 | h = y2 - y1; | 1083 | y2 = y + h; |
1050 | 1084 | ||
1051 | make_even(&x, &w); | 1085 | x = x1; |
1086 | y = y1; | ||
1087 | w = x2 - x1; | ||
1088 | h = y2 - y1; | ||
1052 | 1089 | ||
1053 | DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", | 1090 | make_even(&x, &w); |
1091 | |||
1092 | DSSDBG("changing upd area due to ovl(%d) " | ||
1093 | "scaling %d,%d %dx%d\n", | ||
1054 | i, x, y, w, h); | 1094 | i, x, y, w, h); |
1055 | } | 1095 | |
1096 | area_changed = true; | ||
1097 | } | ||
1098 | } while (area_changed); | ||
1056 | 1099 | ||
1057 | mc = &dss_cache.manager_cache[mgr->id]; | 1100 | mc = &dss_cache.manager_cache[mgr->id]; |
1058 | mc->do_manual_update = true; | 1101 | mc->do_manual_update = true; |
1102 | mc->enlarge_update_area = enlarge_update_area; | ||
1059 | mc->x = x; | 1103 | mc->x = x; |
1060 | mc->y = y; | 1104 | mc->y = y; |
1061 | mc->w = w; | 1105 | mc->w = w; |
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 82336583adef..244dca81a399 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -65,7 +65,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, | |||
65 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 65 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
66 | mgr = omap_dss_get_overlay_manager(i); | 66 | mgr = omap_dss_get_overlay_manager(i); |
67 | 67 | ||
68 | if (strncmp(buf, mgr->name, len) == 0) | 68 | if (sysfs_streq(buf, mgr->name)) |
69 | break; | 69 | break; |
70 | 70 | ||
71 | mgr = NULL; | 71 | mgr = NULL; |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index cc23f53cc62d..bbe62464e92d 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
886 | return -EINVAL; | 886 | return -EINVAL; |
887 | 887 | ||
888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
889 | dss_setup_partial_planes(dssdev, x, y, w, h); | 889 | dss_setup_partial_planes(dssdev, x, y, w, h, true); |
890 | dispc_set_lcd_size(*w, *h); | 890 | dispc_set_lcd_size(*w, *h); |
891 | } | 891 | } |
892 | 892 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 9c7361871d78..6f435450987e 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
@@ -34,12 +34,37 @@ | |||
34 | 34 | ||
35 | #include "omapfb.h" | 35 | #include "omapfb.h" |
36 | 36 | ||
37 | static u8 get_mem_idx(struct omapfb_info *ofbi) | ||
38 | { | ||
39 | if (ofbi->id == ofbi->region->id) | ||
40 | return 0; | ||
41 | |||
42 | return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id; | ||
43 | } | ||
44 | |||
45 | static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi, | ||
46 | u8 mem_idx) | ||
47 | { | ||
48 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
49 | |||
50 | if (mem_idx & OMAPFB_MEM_IDX_ENABLED) | ||
51 | mem_idx &= OMAPFB_MEM_IDX_MASK; | ||
52 | else | ||
53 | mem_idx = ofbi->id; | ||
54 | |||
55 | if (mem_idx >= fbdev->num_fbs) | ||
56 | return NULL; | ||
57 | |||
58 | return &fbdev->regions[mem_idx]; | ||
59 | } | ||
60 | |||
37 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | 61 | static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) |
38 | { | 62 | { |
39 | struct omapfb_info *ofbi = FB2OFB(fbi); | 63 | struct omapfb_info *ofbi = FB2OFB(fbi); |
40 | struct omapfb2_device *fbdev = ofbi->fbdev; | 64 | struct omapfb2_device *fbdev = ofbi->fbdev; |
41 | struct omap_overlay *ovl; | 65 | struct omap_overlay *ovl; |
42 | struct omap_overlay_info info; | 66 | struct omap_overlay_info old_info; |
67 | struct omapfb2_mem_region *old_rg, *new_rg; | ||
43 | int r = 0; | 68 | int r = 0; |
44 | 69 | ||
45 | DBG("omapfb_setup_plane\n"); | 70 | DBG("omapfb_setup_plane\n"); |
@@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
52 | /* XXX uses only the first overlay */ | 77 | /* XXX uses only the first overlay */ |
53 | ovl = ofbi->overlays[0]; | 78 | ovl = ofbi->overlays[0]; |
54 | 79 | ||
55 | if (pi->enabled && !ofbi->region.size) { | 80 | old_rg = ofbi->region; |
81 | new_rg = get_mem_region(ofbi, pi->mem_idx); | ||
82 | if (!new_rg) { | ||
83 | r = -EINVAL; | ||
84 | goto out; | ||
85 | } | ||
86 | |||
87 | /* Take the locks in a specific order to keep lockdep happy */ | ||
88 | if (old_rg->id < new_rg->id) { | ||
89 | omapfb_get_mem_region(old_rg); | ||
90 | omapfb_get_mem_region(new_rg); | ||
91 | } else if (new_rg->id < old_rg->id) { | ||
92 | omapfb_get_mem_region(new_rg); | ||
93 | omapfb_get_mem_region(old_rg); | ||
94 | } else | ||
95 | omapfb_get_mem_region(old_rg); | ||
96 | |||
97 | if (pi->enabled && !new_rg->size) { | ||
56 | /* | 98 | /* |
57 | * This plane's memory was freed, can't enable it | 99 | * This plane's memory was freed, can't enable it |
58 | * until it's reallocated. | 100 | * until it's reallocated. |
59 | */ | 101 | */ |
60 | r = -EINVAL; | 102 | r = -EINVAL; |
61 | goto out; | 103 | goto put_mem; |
62 | } | 104 | } |
63 | 105 | ||
64 | ovl->get_overlay_info(ovl, &info); | 106 | ovl->get_overlay_info(ovl, &old_info); |
65 | 107 | ||
66 | info.pos_x = pi->pos_x; | 108 | if (old_rg != new_rg) { |
67 | info.pos_y = pi->pos_y; | 109 | ofbi->region = new_rg; |
68 | info.out_width = pi->out_width; | 110 | set_fb_fix(fbi); |
69 | info.out_height = pi->out_height; | 111 | } |
70 | info.enabled = pi->enabled; | ||
71 | 112 | ||
72 | r = ovl->set_overlay_info(ovl, &info); | 113 | if (pi->enabled) { |
73 | if (r) | 114 | struct omap_overlay_info info; |
74 | goto out; | ||
75 | 115 | ||
76 | if (ovl->manager) { | 116 | r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, |
77 | r = ovl->manager->apply(ovl->manager); | 117 | pi->out_width, pi->out_height); |
78 | if (r) | 118 | if (r) |
79 | goto out; | 119 | goto undo; |
120 | |||
121 | ovl->get_overlay_info(ovl, &info); | ||
122 | |||
123 | if (!info.enabled) { | ||
124 | info.enabled = pi->enabled; | ||
125 | r = ovl->set_overlay_info(ovl, &info); | ||
126 | if (r) | ||
127 | goto undo; | ||
128 | } | ||
129 | } else { | ||
130 | struct omap_overlay_info info; | ||
131 | |||
132 | ovl->get_overlay_info(ovl, &info); | ||
133 | |||
134 | info.enabled = pi->enabled; | ||
135 | info.pos_x = pi->pos_x; | ||
136 | info.pos_y = pi->pos_y; | ||
137 | info.out_width = pi->out_width; | ||
138 | info.out_height = pi->out_height; | ||
139 | |||
140 | r = ovl->set_overlay_info(ovl, &info); | ||
141 | if (r) | ||
142 | goto undo; | ||
80 | } | 143 | } |
81 | 144 | ||
82 | out: | 145 | if (ovl->manager) |
83 | if (r) | 146 | ovl->manager->apply(ovl->manager); |
84 | dev_err(fbdev->dev, "setup_plane failed\n"); | 147 | |
148 | /* Release the locks in a specific order to keep lockdep happy */ | ||
149 | if (old_rg->id > new_rg->id) { | ||
150 | omapfb_put_mem_region(old_rg); | ||
151 | omapfb_put_mem_region(new_rg); | ||
152 | } else if (new_rg->id > old_rg->id) { | ||
153 | omapfb_put_mem_region(new_rg); | ||
154 | omapfb_put_mem_region(old_rg); | ||
155 | } else | ||
156 | omapfb_put_mem_region(old_rg); | ||
157 | |||
158 | return 0; | ||
159 | |||
160 | undo: | ||
161 | if (old_rg != new_rg) { | ||
162 | ofbi->region = old_rg; | ||
163 | set_fb_fix(fbi); | ||
164 | } | ||
165 | |||
166 | ovl->set_overlay_info(ovl, &old_info); | ||
167 | put_mem: | ||
168 | /* Release the locks in a specific order to keep lockdep happy */ | ||
169 | if (old_rg->id > new_rg->id) { | ||
170 | omapfb_put_mem_region(old_rg); | ||
171 | omapfb_put_mem_region(new_rg); | ||
172 | } else if (new_rg->id > old_rg->id) { | ||
173 | omapfb_put_mem_region(new_rg); | ||
174 | omapfb_put_mem_region(old_rg); | ||
175 | } else | ||
176 | omapfb_put_mem_region(old_rg); | ||
177 | out: | ||
178 | dev_err(fbdev->dev, "setup_plane failed\n"); | ||
179 | |||
85 | return r; | 180 | return r; |
86 | } | 181 | } |
87 | 182 | ||
@@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
92 | if (ofbi->num_overlays != 1) { | 187 | if (ofbi->num_overlays != 1) { |
93 | memset(pi, 0, sizeof(*pi)); | 188 | memset(pi, 0, sizeof(*pi)); |
94 | } else { | 189 | } else { |
95 | struct omap_overlay_info *ovli; | ||
96 | struct omap_overlay *ovl; | 190 | struct omap_overlay *ovl; |
191 | struct omap_overlay_info *ovli; | ||
97 | 192 | ||
98 | ovl = ofbi->overlays[0]; | 193 | ovl = ofbi->overlays[0]; |
99 | ovli = &ovl->info; | 194 | ovli = &ovl->info; |
@@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
103 | pi->enabled = ovli->enabled; | 198 | pi->enabled = ovli->enabled; |
104 | pi->channel_out = 0; /* xxx */ | 199 | pi->channel_out = 0; /* xxx */ |
105 | pi->mirror = 0; | 200 | pi->mirror = 0; |
201 | pi->mem_idx = get_mem_idx(ofbi); | ||
106 | pi->out_width = ovli->out_width; | 202 | pi->out_width = ovli->out_width; |
107 | pi->out_height = ovli->out_height; | 203 | pi->out_height = ovli->out_height; |
108 | } | 204 | } |
@@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
115 | struct omapfb_info *ofbi = FB2OFB(fbi); | 211 | struct omapfb_info *ofbi = FB2OFB(fbi); |
116 | struct omapfb2_device *fbdev = ofbi->fbdev; | 212 | struct omapfb2_device *fbdev = ofbi->fbdev; |
117 | struct omapfb2_mem_region *rg; | 213 | struct omapfb2_mem_region *rg; |
118 | int r, i; | 214 | int r = 0, i; |
119 | size_t size; | 215 | size_t size; |
120 | 216 | ||
121 | if (mi->type > OMAPFB_MEMTYPE_MAX) | 217 | if (mi->type > OMAPFB_MEMTYPE_MAX) |
@@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
123 | 219 | ||
124 | size = PAGE_ALIGN(mi->size); | 220 | size = PAGE_ALIGN(mi->size); |
125 | 221 | ||
126 | rg = &ofbi->region; | 222 | rg = ofbi->region; |
127 | 223 | ||
128 | for (i = 0; i < ofbi->num_overlays; i++) { | 224 | down_write_nested(&rg->lock, rg->id); |
129 | if (ofbi->overlays[i]->info.enabled) | 225 | atomic_inc(&rg->lock_count); |
130 | return -EBUSY; | 226 | |
227 | if (atomic_read(&rg->map_count)) { | ||
228 | r = -EBUSY; | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < fbdev->num_fbs; i++) { | ||
233 | struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); | ||
234 | int j; | ||
235 | |||
236 | if (ofbi2->region != rg) | ||
237 | continue; | ||
238 | |||
239 | for (j = 0; j < ofbi2->num_overlays; j++) { | ||
240 | if (ofbi2->overlays[j]->info.enabled) { | ||
241 | r = -EBUSY; | ||
242 | goto out; | ||
243 | } | ||
244 | } | ||
131 | } | 245 | } |
132 | 246 | ||
133 | if (rg->size != size || rg->type != mi->type) { | 247 | if (rg->size != size || rg->type != mi->type) { |
134 | r = omapfb_realloc_fbmem(fbi, size, mi->type); | 248 | r = omapfb_realloc_fbmem(fbi, size, mi->type); |
135 | if (r) { | 249 | if (r) { |
136 | dev_err(fbdev->dev, "realloc fbmem failed\n"); | 250 | dev_err(fbdev->dev, "realloc fbmem failed\n"); |
137 | return r; | 251 | goto out; |
138 | } | 252 | } |
139 | } | 253 | } |
140 | 254 | ||
141 | return 0; | 255 | out: |
256 | atomic_dec(&rg->lock_count); | ||
257 | up_write(&rg->lock); | ||
258 | |||
259 | return r; | ||
142 | } | 260 | } |
143 | 261 | ||
144 | static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | 262 | static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) |
@@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
146 | struct omapfb_info *ofbi = FB2OFB(fbi); | 264 | struct omapfb_info *ofbi = FB2OFB(fbi); |
147 | struct omapfb2_mem_region *rg; | 265 | struct omapfb2_mem_region *rg; |
148 | 266 | ||
149 | rg = &ofbi->region; | 267 | rg = omapfb_get_mem_region(ofbi->region); |
150 | memset(mi, 0, sizeof(*mi)); | 268 | memset(mi, 0, sizeof(*mi)); |
151 | 269 | ||
152 | mi->size = rg->size; | 270 | mi->size = rg->size; |
153 | mi->type = rg->type; | 271 | mi->type = rg->type; |
154 | 272 | ||
273 | omapfb_put_mem_region(rg); | ||
274 | |||
155 | return 0; | 275 | return 0; |
156 | } | 276 | } |
157 | 277 | ||
@@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
490 | struct omapfb_vram_info vram_info; | 610 | struct omapfb_vram_info vram_info; |
491 | struct omapfb_tearsync_info tearsync_info; | 611 | struct omapfb_tearsync_info tearsync_info; |
492 | struct omapfb_display_info display_info; | 612 | struct omapfb_display_info display_info; |
613 | u32 crt; | ||
493 | } p; | 614 | } p; |
494 | 615 | ||
495 | int r = 0; | 616 | int r = 0; |
@@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
648 | r = -EFAULT; | 769 | r = -EFAULT; |
649 | break; | 770 | break; |
650 | 771 | ||
772 | case FBIO_WAITFORVSYNC: | ||
773 | if (get_user(p.crt, (__u32 __user *)arg)) { | ||
774 | r = -EFAULT; | ||
775 | break; | ||
776 | } | ||
777 | if (p.crt != 0) { | ||
778 | r = -ENODEV; | ||
779 | break; | ||
780 | } | ||
781 | /* FALLTHROUGH */ | ||
782 | |||
651 | case OMAPFB_WAITFORVSYNC: | 783 | case OMAPFB_WAITFORVSYNC: |
652 | DBG("ioctl WAITFORVSYNC\n"); | 784 | DBG("ioctl WAITFORVSYNC\n"); |
653 | if (!display) { | 785 | if (!display) { |
@@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
738 | break; | 870 | break; |
739 | } | 871 | } |
740 | 872 | ||
741 | if (!display->driver->enable_te) { | 873 | if (!display || !display->driver->enable_te) { |
742 | r = -ENODEV; | 874 | r = -ENODEV; |
743 | break; | 875 | break; |
744 | } | 876 | } |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4b4506da96da..04034d410d6d 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi) | |||
157 | 157 | ||
158 | static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) | 158 | static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) |
159 | { | 159 | { |
160 | const struct vrfb *vrfb = &ofbi->region.vrfb; | 160 | const struct vrfb *vrfb = &ofbi->region->vrfb; |
161 | unsigned offset; | 161 | unsigned offset; |
162 | 162 | ||
163 | switch (rot) { | 163 | switch (rot) { |
@@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) | |||
185 | static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) | 185 | static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) |
186 | { | 186 | { |
187 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 187 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { |
188 | return ofbi->region.vrfb.paddr[rot] | 188 | return ofbi->region->vrfb.paddr[rot] |
189 | + omapfb_get_vrfb_offset(ofbi, rot); | 189 | + omapfb_get_vrfb_offset(ofbi, rot); |
190 | } else { | 190 | } else { |
191 | return ofbi->region.paddr; | 191 | return ofbi->region->paddr; |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) | 195 | static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) |
196 | { | 196 | { |
197 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 197 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
198 | return ofbi->region.vrfb.paddr[0]; | 198 | return ofbi->region->vrfb.paddr[0]; |
199 | else | 199 | else |
200 | return ofbi->region.paddr; | 200 | return ofbi->region->paddr; |
201 | } | 201 | } |
202 | 202 | ||
203 | static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) | 203 | static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) |
204 | { | 204 | { |
205 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 205 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
206 | return ofbi->region.vrfb.vaddr[0]; | 206 | return ofbi->region->vrfb.vaddr[0]; |
207 | else | 207 | else |
208 | return ofbi->region.vaddr; | 208 | return ofbi->region->vaddr; |
209 | } | 209 | } |
210 | 210 | ||
211 | static struct omapfb_colormode omapfb_colormodes[] = { | 211 | static struct omapfb_colormode omapfb_colormodes[] = { |
@@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size, | |||
450 | static int check_fb_size(const struct omapfb_info *ofbi, | 450 | static int check_fb_size(const struct omapfb_info *ofbi, |
451 | struct fb_var_screeninfo *var) | 451 | struct fb_var_screeninfo *var) |
452 | { | 452 | { |
453 | unsigned long max_frame_size = ofbi->region.size; | 453 | unsigned long max_frame_size = ofbi->region->size; |
454 | int bytespp = var->bits_per_pixel >> 3; | 454 | int bytespp = var->bits_per_pixel >> 3; |
455 | unsigned long line_size = var->xres_virtual * bytespp; | 455 | unsigned long line_size = var->xres_virtual * bytespp; |
456 | 456 | ||
@@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi, | |||
497 | static int setup_vrfb_rotation(struct fb_info *fbi) | 497 | static int setup_vrfb_rotation(struct fb_info *fbi) |
498 | { | 498 | { |
499 | struct omapfb_info *ofbi = FB2OFB(fbi); | 499 | struct omapfb_info *ofbi = FB2OFB(fbi); |
500 | struct omapfb2_mem_region *rg = &ofbi->region; | 500 | struct omapfb2_mem_region *rg = ofbi->region; |
501 | struct vrfb *vrfb = &rg->vrfb; | 501 | struct vrfb *vrfb = &rg->vrfb; |
502 | struct fb_var_screeninfo *var = &fbi->var; | 502 | struct fb_var_screeninfo *var = &fbi->var; |
503 | struct fb_fix_screeninfo *fix = &fbi->fix; | 503 | struct fb_fix_screeninfo *fix = &fbi->fix; |
@@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi) | |||
558 | return r; | 558 | return r; |
559 | 559 | ||
560 | /* used by open/write in fbmem.c */ | 560 | /* used by open/write in fbmem.c */ |
561 | fbi->screen_base = ofbi->region.vrfb.vaddr[0]; | 561 | fbi->screen_base = ofbi->region->vrfb.vaddr[0]; |
562 | 562 | ||
563 | fix->smem_start = ofbi->region.vrfb.paddr[0]; | 563 | fix->smem_start = ofbi->region->vrfb.paddr[0]; |
564 | 564 | ||
565 | switch (var->nonstd) { | 565 | switch (var->nonstd) { |
566 | case OMAPFB_COLOR_YUV422: | 566 | case OMAPFB_COLOR_YUV422: |
@@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi) | |||
599 | struct fb_fix_screeninfo *fix = &fbi->fix; | 599 | struct fb_fix_screeninfo *fix = &fbi->fix; |
600 | struct fb_var_screeninfo *var = &fbi->var; | 600 | struct fb_var_screeninfo *var = &fbi->var; |
601 | struct omapfb_info *ofbi = FB2OFB(fbi); | 601 | struct omapfb_info *ofbi = FB2OFB(fbi); |
602 | struct omapfb2_mem_region *rg = &ofbi->region; | 602 | struct omapfb2_mem_region *rg = ofbi->region; |
603 | 603 | ||
604 | DBG("set_fb_fix\n"); | 604 | DBG("set_fb_fix\n"); |
605 | 605 | ||
@@ -668,8 +668,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
668 | 668 | ||
669 | DBG("check_fb_var %d\n", ofbi->id); | 669 | DBG("check_fb_var %d\n", ofbi->id); |
670 | 670 | ||
671 | if (ofbi->region.size == 0) | 671 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); |
672 | return 0; | ||
673 | 672 | ||
674 | r = fb_mode_to_dss_mode(var, &mode); | 673 | r = fb_mode_to_dss_mode(var, &mode); |
675 | if (r) { | 674 | if (r) { |
@@ -684,13 +683,14 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
684 | } | 683 | } |
685 | } | 684 | } |
686 | 685 | ||
687 | if (var->rotate < 0 || var->rotate > 3) | 686 | if (var->rotate > 3) |
688 | return -EINVAL; | 687 | return -EINVAL; |
689 | 688 | ||
690 | if (check_fb_res_bounds(var)) | 689 | if (check_fb_res_bounds(var)) |
691 | return -EINVAL; | 690 | return -EINVAL; |
692 | 691 | ||
693 | if (check_fb_size(ofbi, var)) | 692 | /* When no memory is allocated ignore the size check */ |
693 | if (ofbi->region->size != 0 && check_fb_size(ofbi, var)) | ||
694 | return -EINVAL; | 694 | return -EINVAL; |
695 | 695 | ||
696 | if (var->xres + var->xoffset > var->xres_virtual) | 696 | if (var->xres + var->xoffset > var->xres_virtual) |
@@ -822,9 +822,43 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var, | |||
822 | return offset; | 822 | return offset; |
823 | } | 823 | } |
824 | 824 | ||
825 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, | ||
826 | const struct fb_var_screeninfo *var, | ||
827 | const struct fb_fix_screeninfo *fix, | ||
828 | int rotation, u32 *paddr, void __iomem **vaddr) | ||
829 | { | ||
830 | u32 data_start_p; | ||
831 | void __iomem *data_start_v; | ||
832 | int offset; | ||
833 | |||
834 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | ||
835 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | ||
836 | data_start_v = NULL; | ||
837 | } else { | ||
838 | data_start_p = omapfb_get_region_paddr(ofbi); | ||
839 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
840 | } | ||
841 | |||
842 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | ||
843 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | ||
844 | else | ||
845 | offset = calc_rotation_offset_dma(var, fix, rotation); | ||
846 | |||
847 | data_start_p += offset; | ||
848 | data_start_v += offset; | ||
849 | |||
850 | if (offset) | ||
851 | DBG("offset %d, %d = %d\n", | ||
852 | var->xoffset, var->yoffset, offset); | ||
853 | |||
854 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | ||
855 | |||
856 | *paddr = data_start_p; | ||
857 | *vaddr = data_start_v; | ||
858 | } | ||
825 | 859 | ||
826 | /* setup overlay according to the fb */ | 860 | /* setup overlay according to the fb */ |
827 | static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | 861 | int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, |
828 | u16 posx, u16 posy, u16 outw, u16 outh) | 862 | u16 posx, u16 posy, u16 outw, u16 outh) |
829 | { | 863 | { |
830 | int r = 0; | 864 | int r = 0; |
@@ -832,9 +866,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
832 | struct fb_var_screeninfo *var = &fbi->var; | 866 | struct fb_var_screeninfo *var = &fbi->var; |
833 | struct fb_fix_screeninfo *fix = &fbi->fix; | 867 | struct fb_fix_screeninfo *fix = &fbi->fix; |
834 | enum omap_color_mode mode = 0; | 868 | enum omap_color_mode mode = 0; |
835 | int offset; | 869 | u32 data_start_p = 0; |
836 | u32 data_start_p; | 870 | void __iomem *data_start_v = NULL; |
837 | void __iomem *data_start_v; | ||
838 | struct omap_overlay_info info; | 871 | struct omap_overlay_info info; |
839 | int xres, yres; | 872 | int xres, yres; |
840 | int screen_width; | 873 | int screen_width; |
@@ -842,6 +875,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
842 | int rotation = var->rotate; | 875 | int rotation = var->rotate; |
843 | int i; | 876 | int i; |
844 | 877 | ||
878 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
879 | |||
845 | for (i = 0; i < ofbi->num_overlays; i++) { | 880 | for (i = 0; i < ofbi->num_overlays; i++) { |
846 | if (ovl != ofbi->overlays[i]) | 881 | if (ovl != ofbi->overlays[i]) |
847 | continue; | 882 | continue; |
@@ -861,28 +896,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
861 | yres = var->yres; | 896 | yres = var->yres; |
862 | } | 897 | } |
863 | 898 | ||
864 | 899 | if (ofbi->region->size) | |
865 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 900 | omapfb_calc_addr(ofbi, var, fix, rotation, |
866 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | 901 | &data_start_p, &data_start_v); |
867 | data_start_v = NULL; | ||
868 | } else { | ||
869 | data_start_p = omapfb_get_region_paddr(ofbi); | ||
870 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
871 | } | ||
872 | |||
873 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | ||
874 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | ||
875 | else | ||
876 | offset = calc_rotation_offset_dma(var, fix, rotation); | ||
877 | |||
878 | data_start_p += offset; | ||
879 | data_start_v += offset; | ||
880 | |||
881 | if (offset) | ||
882 | DBG("offset %d, %d = %d\n", | ||
883 | var->xoffset, var->yoffset, offset); | ||
884 | |||
885 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | ||
886 | 902 | ||
887 | r = fb_mode_to_dss_mode(var, &mode); | 903 | r = fb_mode_to_dss_mode(var, &mode); |
888 | if (r) { | 904 | if (r) { |
@@ -954,12 +970,14 @@ int omapfb_apply_changes(struct fb_info *fbi, int init) | |||
954 | fill_fb(fbi); | 970 | fill_fb(fbi); |
955 | #endif | 971 | #endif |
956 | 972 | ||
973 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
974 | |||
957 | for (i = 0; i < ofbi->num_overlays; i++) { | 975 | for (i = 0; i < ofbi->num_overlays; i++) { |
958 | ovl = ofbi->overlays[i]; | 976 | ovl = ofbi->overlays[i]; |
959 | 977 | ||
960 | DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); | 978 | DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); |
961 | 979 | ||
962 | if (ofbi->region.size == 0) { | 980 | if (ofbi->region->size == 0) { |
963 | /* the fb is not available. disable the overlay */ | 981 | /* the fb is not available. disable the overlay */ |
964 | omapfb_overlay_enable(ovl, 0); | 982 | omapfb_overlay_enable(ovl, 0); |
965 | if (!init && ovl->manager) | 983 | if (!init && ovl->manager) |
@@ -1007,36 +1025,48 @@ err: | |||
1007 | * DO NOT MODIFY PAR */ | 1025 | * DO NOT MODIFY PAR */ |
1008 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | 1026 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) |
1009 | { | 1027 | { |
1028 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1010 | int r; | 1029 | int r; |
1011 | 1030 | ||
1012 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); | 1031 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); |
1013 | 1032 | ||
1033 | omapfb_get_mem_region(ofbi->region); | ||
1034 | |||
1014 | r = check_fb_var(fbi, var); | 1035 | r = check_fb_var(fbi, var); |
1015 | 1036 | ||
1037 | omapfb_put_mem_region(ofbi->region); | ||
1038 | |||
1016 | return r; | 1039 | return r; |
1017 | } | 1040 | } |
1018 | 1041 | ||
1019 | /* set the video mode according to info->var */ | 1042 | /* set the video mode according to info->var */ |
1020 | static int omapfb_set_par(struct fb_info *fbi) | 1043 | static int omapfb_set_par(struct fb_info *fbi) |
1021 | { | 1044 | { |
1045 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1022 | int r; | 1046 | int r; |
1023 | 1047 | ||
1024 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); | 1048 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); |
1025 | 1049 | ||
1050 | omapfb_get_mem_region(ofbi->region); | ||
1051 | |||
1026 | set_fb_fix(fbi); | 1052 | set_fb_fix(fbi); |
1027 | 1053 | ||
1028 | r = setup_vrfb_rotation(fbi); | 1054 | r = setup_vrfb_rotation(fbi); |
1029 | if (r) | 1055 | if (r) |
1030 | return r; | 1056 | goto out; |
1031 | 1057 | ||
1032 | r = omapfb_apply_changes(fbi, 0); | 1058 | r = omapfb_apply_changes(fbi, 0); |
1033 | 1059 | ||
1060 | out: | ||
1061 | omapfb_put_mem_region(ofbi->region); | ||
1062 | |||
1034 | return r; | 1063 | return r; |
1035 | } | 1064 | } |
1036 | 1065 | ||
1037 | static int omapfb_pan_display(struct fb_var_screeninfo *var, | 1066 | static int omapfb_pan_display(struct fb_var_screeninfo *var, |
1038 | struct fb_info *fbi) | 1067 | struct fb_info *fbi) |
1039 | { | 1068 | { |
1069 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1040 | struct fb_var_screeninfo new_var; | 1070 | struct fb_var_screeninfo new_var; |
1041 | int r; | 1071 | int r; |
1042 | 1072 | ||
@@ -1052,23 +1082,31 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var, | |||
1052 | 1082 | ||
1053 | fbi->var = new_var; | 1083 | fbi->var = new_var; |
1054 | 1084 | ||
1085 | omapfb_get_mem_region(ofbi->region); | ||
1086 | |||
1055 | r = omapfb_apply_changes(fbi, 0); | 1087 | r = omapfb_apply_changes(fbi, 0); |
1056 | 1088 | ||
1089 | omapfb_put_mem_region(ofbi->region); | ||
1090 | |||
1057 | return r; | 1091 | return r; |
1058 | } | 1092 | } |
1059 | 1093 | ||
1060 | static void mmap_user_open(struct vm_area_struct *vma) | 1094 | static void mmap_user_open(struct vm_area_struct *vma) |
1061 | { | 1095 | { |
1062 | struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; | 1096 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1063 | 1097 | ||
1064 | atomic_inc(&ofbi->map_count); | 1098 | omapfb_get_mem_region(rg); |
1099 | atomic_inc(&rg->map_count); | ||
1100 | omapfb_put_mem_region(rg); | ||
1065 | } | 1101 | } |
1066 | 1102 | ||
1067 | static void mmap_user_close(struct vm_area_struct *vma) | 1103 | static void mmap_user_close(struct vm_area_struct *vma) |
1068 | { | 1104 | { |
1069 | struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; | 1105 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1070 | 1106 | ||
1071 | atomic_dec(&ofbi->map_count); | 1107 | omapfb_get_mem_region(rg); |
1108 | atomic_dec(&rg->map_count); | ||
1109 | omapfb_put_mem_region(rg); | ||
1072 | } | 1110 | } |
1073 | 1111 | ||
1074 | static struct vm_operations_struct mmap_user_ops = { | 1112 | static struct vm_operations_struct mmap_user_ops = { |
@@ -1080,9 +1118,11 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1080 | { | 1118 | { |
1081 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1119 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1082 | struct fb_fix_screeninfo *fix = &fbi->fix; | 1120 | struct fb_fix_screeninfo *fix = &fbi->fix; |
1121 | struct omapfb2_mem_region *rg; | ||
1083 | unsigned long off; | 1122 | unsigned long off; |
1084 | unsigned long start; | 1123 | unsigned long start; |
1085 | u32 len; | 1124 | u32 len; |
1125 | int r = -EINVAL; | ||
1086 | 1126 | ||
1087 | if (vma->vm_end - vma->vm_start == 0) | 1127 | if (vma->vm_end - vma->vm_start == 0) |
1088 | return 0; | 1128 | return 0; |
@@ -1090,12 +1130,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1090 | return -EINVAL; | 1130 | return -EINVAL; |
1091 | off = vma->vm_pgoff << PAGE_SHIFT; | 1131 | off = vma->vm_pgoff << PAGE_SHIFT; |
1092 | 1132 | ||
1133 | rg = omapfb_get_mem_region(ofbi->region); | ||
1134 | |||
1093 | start = omapfb_get_region_paddr(ofbi); | 1135 | start = omapfb_get_region_paddr(ofbi); |
1094 | len = fix->smem_len; | 1136 | len = fix->smem_len; |
1095 | if (off >= len) | 1137 | if (off >= len) |
1096 | return -EINVAL; | 1138 | goto error; |
1097 | if ((vma->vm_end - vma->vm_start + off) > len) | 1139 | if ((vma->vm_end - vma->vm_start + off) > len) |
1098 | return -EINVAL; | 1140 | goto error; |
1099 | 1141 | ||
1100 | off += start; | 1142 | off += start; |
1101 | 1143 | ||
@@ -1105,13 +1147,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1105 | vma->vm_flags |= VM_IO | VM_RESERVED; | 1147 | vma->vm_flags |= VM_IO | VM_RESERVED; |
1106 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | 1148 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); |
1107 | vma->vm_ops = &mmap_user_ops; | 1149 | vma->vm_ops = &mmap_user_ops; |
1108 | vma->vm_private_data = ofbi; | 1150 | vma->vm_private_data = rg; |
1109 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | 1151 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, |
1110 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 1152 | vma->vm_end - vma->vm_start, |
1111 | return -EAGAIN; | 1153 | vma->vm_page_prot)) { |
1154 | r = -EAGAIN; | ||
1155 | goto error; | ||
1156 | } | ||
1157 | |||
1112 | /* vm_ops.open won't be called for mmap itself. */ | 1158 | /* vm_ops.open won't be called for mmap itself. */ |
1113 | atomic_inc(&ofbi->map_count); | 1159 | atomic_inc(&rg->map_count); |
1160 | |||
1161 | omapfb_put_mem_region(rg); | ||
1162 | |||
1114 | return 0; | 1163 | return 0; |
1164 | |||
1165 | error: | ||
1166 | omapfb_put_mem_region(ofbi->region); | ||
1167 | |||
1168 | return r; | ||
1115 | } | 1169 | } |
1116 | 1170 | ||
1117 | /* Store a single color palette entry into a pseudo palette or the hardware | 1171 | /* Store a single color palette entry into a pseudo palette or the hardware |
@@ -1154,11 +1208,6 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, | |||
1154 | if (r != 0) | 1208 | if (r != 0) |
1155 | break; | 1209 | break; |
1156 | 1210 | ||
1157 | if (regno < 0) { | ||
1158 | r = -EINVAL; | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | if (regno < 16) { | 1211 | if (regno < 16) { |
1163 | u16 pal; | 1212 | u16 pal; |
1164 | pal = ((red >> (16 - var->red.length)) << | 1213 | pal = ((red >> (16 - var->red.length)) << |
@@ -1217,6 +1266,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1217 | int do_update = 0; | 1266 | int do_update = 0; |
1218 | int r = 0; | 1267 | int r = 0; |
1219 | 1268 | ||
1269 | if (!display) | ||
1270 | return -EINVAL; | ||
1271 | |||
1220 | omapfb_lock(fbdev); | 1272 | omapfb_lock(fbdev); |
1221 | 1273 | ||
1222 | switch (blank) { | 1274 | switch (blank) { |
@@ -1300,7 +1352,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi) | |||
1300 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1352 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1301 | struct omapfb2_mem_region *rg; | 1353 | struct omapfb2_mem_region *rg; |
1302 | 1354 | ||
1303 | rg = &ofbi->region; | 1355 | rg = ofbi->region; |
1356 | |||
1357 | WARN_ON(atomic_read(&rg->map_count)); | ||
1304 | 1358 | ||
1305 | if (rg->paddr) | 1359 | if (rg->paddr) |
1306 | if (omap_vram_free(rg->paddr, rg->size)) | 1360 | if (omap_vram_free(rg->paddr, rg->size)) |
@@ -1355,8 +1409,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, | |||
1355 | void __iomem *vaddr; | 1409 | void __iomem *vaddr; |
1356 | int r; | 1410 | int r; |
1357 | 1411 | ||
1358 | rg = &ofbi->region; | 1412 | rg = ofbi->region; |
1359 | memset(rg, 0, sizeof(*rg)); | 1413 | |
1414 | rg->paddr = 0; | ||
1415 | rg->vaddr = NULL; | ||
1416 | memset(&rg->vrfb, 0, sizeof rg->vrfb); | ||
1417 | rg->size = 0; | ||
1418 | rg->type = 0; | ||
1419 | rg->alloc = false; | ||
1420 | rg->map = false; | ||
1360 | 1421 | ||
1361 | size = PAGE_ALIGN(size); | 1422 | size = PAGE_ALIGN(size); |
1362 | 1423 | ||
@@ -1609,7 +1670,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) | |||
1609 | for (i = 0; i < fbdev->num_fbs; i++) { | 1670 | for (i = 0; i < fbdev->num_fbs; i++) { |
1610 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); | 1671 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); |
1611 | struct omapfb2_mem_region *rg; | 1672 | struct omapfb2_mem_region *rg; |
1612 | rg = &ofbi->region; | 1673 | rg = ofbi->region; |
1613 | 1674 | ||
1614 | DBG("region%d phys %08x virt %p size=%lu\n", | 1675 | DBG("region%d phys %08x virt %p size=%lu\n", |
1615 | i, | 1676 | i, |
@@ -1626,7 +1687,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) | |||
1626 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1687 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1627 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1688 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1628 | struct omap_dss_device *display = fb2display(fbi); | 1689 | struct omap_dss_device *display = fb2display(fbi); |
1629 | struct omapfb2_mem_region *rg = &ofbi->region; | 1690 | struct omapfb2_mem_region *rg = ofbi->region; |
1630 | unsigned long old_size = rg->size; | 1691 | unsigned long old_size = rg->size; |
1631 | unsigned long old_paddr = rg->paddr; | 1692 | unsigned long old_paddr = rg->paddr; |
1632 | int old_type = rg->type; | 1693 | int old_type = rg->type; |
@@ -1709,7 +1770,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) | |||
1709 | fbi->flags = FBINFO_FLAG_DEFAULT; | 1770 | fbi->flags = FBINFO_FLAG_DEFAULT; |
1710 | fbi->pseudo_palette = fbdev->pseudo_palette; | 1771 | fbi->pseudo_palette = fbdev->pseudo_palette; |
1711 | 1772 | ||
1712 | if (ofbi->region.size == 0) { | 1773 | if (ofbi->region->size == 0) { |
1713 | clear_fb_info(fbi); | 1774 | clear_fb_info(fbi); |
1714 | return 0; | 1775 | return 0; |
1715 | } | 1776 | } |
@@ -1871,6 +1932,10 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1871 | ofbi->fbdev = fbdev; | 1932 | ofbi->fbdev = fbdev; |
1872 | ofbi->id = i; | 1933 | ofbi->id = i; |
1873 | 1934 | ||
1935 | ofbi->region = &fbdev->regions[i]; | ||
1936 | ofbi->region->id = i; | ||
1937 | init_rwsem(&ofbi->region->lock); | ||
1938 | |||
1874 | /* assign these early, so that fb alloc can use them */ | 1939 | /* assign these early, so that fb alloc can use them */ |
1875 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : | 1940 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : |
1876 | OMAP_DSS_ROT_DMA; | 1941 | OMAP_DSS_ROT_DMA; |
@@ -1900,7 +1965,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1900 | 1965 | ||
1901 | /* setup fb_infos */ | 1966 | /* setup fb_infos */ |
1902 | for (i = 0; i < fbdev->num_fbs; i++) { | 1967 | for (i = 0; i < fbdev->num_fbs; i++) { |
1903 | r = omapfb_fb_init(fbdev, fbdev->fbs[i]); | 1968 | struct fb_info *fbi = fbdev->fbs[i]; |
1969 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1970 | |||
1971 | omapfb_get_mem_region(ofbi->region); | ||
1972 | r = omapfb_fb_init(fbdev, fbi); | ||
1973 | omapfb_put_mem_region(ofbi->region); | ||
1974 | |||
1904 | if (r) { | 1975 | if (r) { |
1905 | dev_err(fbdev->dev, "failed to setup fb_info\n"); | 1976 | dev_err(fbdev->dev, "failed to setup fb_info\n"); |
1906 | return r; | 1977 | return r; |
@@ -1921,20 +1992,19 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1921 | DBG("framebuffers registered\n"); | 1992 | DBG("framebuffers registered\n"); |
1922 | 1993 | ||
1923 | for (i = 0; i < fbdev->num_fbs; i++) { | 1994 | for (i = 0; i < fbdev->num_fbs; i++) { |
1924 | r = omapfb_apply_changes(fbdev->fbs[i], 1); | 1995 | struct fb_info *fbi = fbdev->fbs[i]; |
1996 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1997 | |||
1998 | omapfb_get_mem_region(ofbi->region); | ||
1999 | r = omapfb_apply_changes(fbi, 1); | ||
2000 | omapfb_put_mem_region(ofbi->region); | ||
2001 | |||
1925 | if (r) { | 2002 | if (r) { |
1926 | dev_err(fbdev->dev, "failed to change mode\n"); | 2003 | dev_err(fbdev->dev, "failed to change mode\n"); |
1927 | return r; | 2004 | return r; |
1928 | } | 2005 | } |
1929 | } | 2006 | } |
1930 | 2007 | ||
1931 | DBG("create sysfs for fbs\n"); | ||
1932 | r = omapfb_create_sysfs(fbdev); | ||
1933 | if (r) { | ||
1934 | dev_err(fbdev->dev, "failed to create sysfs entries\n"); | ||
1935 | return r; | ||
1936 | } | ||
1937 | |||
1938 | /* Enable fb0 */ | 2008 | /* Enable fb0 */ |
1939 | if (fbdev->num_fbs > 0) { | 2009 | if (fbdev->num_fbs > 0) { |
1940 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); | 2010 | struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); |
@@ -1968,11 +2038,11 @@ static int omapfb_mode_to_timings(const char *mode_str, | |||
1968 | #ifdef CONFIG_OMAP2_DSS_VENC | 2038 | #ifdef CONFIG_OMAP2_DSS_VENC |
1969 | if (strcmp(mode_str, "pal") == 0) { | 2039 | if (strcmp(mode_str, "pal") == 0) { |
1970 | *timings = omap_dss_pal_timings; | 2040 | *timings = omap_dss_pal_timings; |
1971 | *bpp = 0; | 2041 | *bpp = 24; |
1972 | return 0; | 2042 | return 0; |
1973 | } else if (strcmp(mode_str, "ntsc") == 0) { | 2043 | } else if (strcmp(mode_str, "ntsc") == 0) { |
1974 | *timings = omap_dss_ntsc_timings; | 2044 | *timings = omap_dss_ntsc_timings; |
1975 | *bpp = 0; | 2045 | *bpp = 24; |
1976 | return 0; | 2046 | return 0; |
1977 | } | 2047 | } |
1978 | #endif | 2048 | #endif |
@@ -2220,6 +2290,13 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2220 | } | 2290 | } |
2221 | } | 2291 | } |
2222 | 2292 | ||
2293 | DBG("create sysfs for fbs\n"); | ||
2294 | r = omapfb_create_sysfs(fbdev); | ||
2295 | if (r) { | ||
2296 | dev_err(fbdev->dev, "failed to create sysfs entries\n"); | ||
2297 | goto cleanup; | ||
2298 | } | ||
2299 | |||
2223 | return 0; | 2300 | return 0; |
2224 | 2301 | ||
2225 | cleanup: | 2302 | cleanup: |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 5179219128bd..6f9c72cd6bb0 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev, | |||
49 | { | 49 | { |
50 | struct fb_info *fbi = dev_get_drvdata(dev); | 50 | struct fb_info *fbi = dev_get_drvdata(dev); |
51 | struct omapfb_info *ofbi = FB2OFB(fbi); | 51 | struct omapfb_info *ofbi = FB2OFB(fbi); |
52 | struct omapfb2_mem_region *rg; | ||
52 | enum omap_dss_rotation_type rot_type; | 53 | enum omap_dss_rotation_type rot_type; |
53 | int r; | 54 | int r; |
54 | 55 | ||
@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev, | |||
64 | if (rot_type == ofbi->rotation_type) | 65 | if (rot_type == ofbi->rotation_type) |
65 | goto out; | 66 | goto out; |
66 | 67 | ||
67 | if (ofbi->region.size) { | 68 | rg = omapfb_get_mem_region(ofbi->region); |
69 | |||
70 | if (rg->size) { | ||
68 | r = -EBUSY; | 71 | r = -EBUSY; |
69 | goto out; | 72 | goto put_region; |
70 | } | 73 | } |
71 | 74 | ||
72 | ofbi->rotation_type = rot_type; | 75 | ofbi->rotation_type = rot_type; |
@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev, | |||
75 | * Since the VRAM for this FB is not allocated at the moment we don't | 78 | * Since the VRAM for this FB is not allocated at the moment we don't |
76 | * need to do any further parameter checking at this point. | 79 | * need to do any further parameter checking at this point. |
77 | */ | 80 | */ |
81 | put_region: | ||
82 | omapfb_put_mem_region(rg); | ||
78 | out: | 83 | out: |
79 | unlock_fb_info(fbi); | 84 | unlock_fb_info(fbi); |
80 | 85 | ||
@@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev, | |||
97 | { | 102 | { |
98 | struct fb_info *fbi = dev_get_drvdata(dev); | 103 | struct fb_info *fbi = dev_get_drvdata(dev); |
99 | struct omapfb_info *ofbi = FB2OFB(fbi); | 104 | struct omapfb_info *ofbi = FB2OFB(fbi); |
100 | bool mirror; | 105 | unsigned long mirror; |
101 | int r; | 106 | int r; |
102 | struct fb_var_screeninfo new_var; | 107 | struct fb_var_screeninfo new_var; |
103 | 108 | ||
@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev, | |||
111 | 116 | ||
112 | ofbi->mirror = mirror; | 117 | ofbi->mirror = mirror; |
113 | 118 | ||
119 | omapfb_get_mem_region(ofbi->region); | ||
120 | |||
114 | memcpy(&new_var, &fbi->var, sizeof(new_var)); | 121 | memcpy(&new_var, &fbi->var, sizeof(new_var)); |
115 | r = check_fb_var(fbi, &new_var); | 122 | r = check_fb_var(fbi, &new_var); |
116 | if (r) | 123 | if (r) |
@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev, | |||
125 | 132 | ||
126 | r = count; | 133 | r = count; |
127 | out: | 134 | out: |
135 | omapfb_put_mem_region(ofbi->region); | ||
136 | |||
128 | unlock_fb_info(fbi); | 137 | unlock_fb_info(fbi); |
129 | 138 | ||
130 | return r; | 139 | return r; |
@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
263 | 272 | ||
264 | DBG("detaching %d\n", ofbi->overlays[i]->id); | 273 | DBG("detaching %d\n", ofbi->overlays[i]->id); |
265 | 274 | ||
275 | omapfb_get_mem_region(ofbi->region); | ||
276 | |||
266 | omapfb_overlay_enable(ovl, 0); | 277 | omapfb_overlay_enable(ovl, 0); |
267 | 278 | ||
268 | if (ovl->manager) | 279 | if (ovl->manager) |
269 | ovl->manager->apply(ovl->manager); | 280 | ovl->manager->apply(ovl->manager); |
270 | 281 | ||
282 | omapfb_put_mem_region(ofbi->region); | ||
283 | |||
271 | for (t = i + 1; t < ofbi->num_overlays; t++) { | 284 | for (t = i + 1; t < ofbi->num_overlays; t++) { |
272 | ofbi->rotation[t-1] = ofbi->rotation[t]; | 285 | ofbi->rotation[t-1] = ofbi->rotation[t]; |
273 | ofbi->overlays[t-1] = ofbi->overlays[t]; | 286 | ofbi->overlays[t-1] = ofbi->overlays[t]; |
@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
300 | } | 313 | } |
301 | 314 | ||
302 | if (added) { | 315 | if (added) { |
316 | omapfb_get_mem_region(ofbi->region); | ||
317 | |||
303 | r = omapfb_apply_changes(fbi, 0); | 318 | r = omapfb_apply_changes(fbi, 0); |
319 | |||
320 | omapfb_put_mem_region(ofbi->region); | ||
321 | |||
304 | if (r) | 322 | if (r) |
305 | goto out; | 323 | goto out; |
306 | } | 324 | } |
@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
388 | for (i = 0; i < num_ovls; ++i) | 406 | for (i = 0; i < num_ovls; ++i) |
389 | ofbi->rotation[i] = rotation[i]; | 407 | ofbi->rotation[i] = rotation[i]; |
390 | 408 | ||
409 | omapfb_get_mem_region(ofbi->region); | ||
410 | |||
391 | r = omapfb_apply_changes(fbi, 0); | 411 | r = omapfb_apply_changes(fbi, 0); |
412 | |||
413 | omapfb_put_mem_region(ofbi->region); | ||
414 | |||
392 | if (r) | 415 | if (r) |
393 | goto out; | 416 | goto out; |
394 | 417 | ||
@@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev, | |||
408 | struct fb_info *fbi = dev_get_drvdata(dev); | 431 | struct fb_info *fbi = dev_get_drvdata(dev); |
409 | struct omapfb_info *ofbi = FB2OFB(fbi); | 432 | struct omapfb_info *ofbi = FB2OFB(fbi); |
410 | 433 | ||
411 | return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); | 434 | return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); |
412 | } | 435 | } |
413 | 436 | ||
414 | static ssize_t store_size(struct device *dev, struct device_attribute *attr, | 437 | static ssize_t store_size(struct device *dev, struct device_attribute *attr, |
@@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
416 | { | 439 | { |
417 | struct fb_info *fbi = dev_get_drvdata(dev); | 440 | struct fb_info *fbi = dev_get_drvdata(dev); |
418 | struct omapfb_info *ofbi = FB2OFB(fbi); | 441 | struct omapfb_info *ofbi = FB2OFB(fbi); |
442 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
443 | struct omapfb2_mem_region *rg; | ||
419 | unsigned long size; | 444 | unsigned long size; |
420 | int r; | 445 | int r; |
421 | int i; | 446 | int i; |
@@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
425 | if (!lock_fb_info(fbi)) | 450 | if (!lock_fb_info(fbi)) |
426 | return -ENODEV; | 451 | return -ENODEV; |
427 | 452 | ||
428 | for (i = 0; i < ofbi->num_overlays; i++) { | 453 | rg = ofbi->region; |
429 | if (ofbi->overlays[i]->info.enabled) { | 454 | |
430 | r = -EBUSY; | 455 | down_write_nested(&rg->lock, rg->id); |
431 | goto out; | 456 | atomic_inc(&rg->lock_count); |
457 | |||
458 | if (atomic_read(&rg->map_count)) { | ||
459 | r = -EBUSY; | ||
460 | goto out; | ||
461 | } | ||
462 | |||
463 | for (i = 0; i < fbdev->num_fbs; i++) { | ||
464 | struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]); | ||
465 | int j; | ||
466 | |||
467 | if (ofbi2->region != rg) | ||
468 | continue; | ||
469 | |||
470 | for (j = 0; j < ofbi2->num_overlays; j++) { | ||
471 | if (ofbi2->overlays[j]->info.enabled) { | ||
472 | r = -EBUSY; | ||
473 | goto out; | ||
474 | } | ||
432 | } | 475 | } |
433 | } | 476 | } |
434 | 477 | ||
435 | if (size != ofbi->region.size) { | 478 | if (size != ofbi->region->size) { |
436 | r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); | 479 | r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type); |
437 | if (r) { | 480 | if (r) { |
438 | dev_err(dev, "realloc fbmem failed\n"); | 481 | dev_err(dev, "realloc fbmem failed\n"); |
439 | goto out; | 482 | goto out; |
@@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
442 | 485 | ||
443 | r = count; | 486 | r = count; |
444 | out: | 487 | out: |
488 | atomic_dec(&rg->lock_count); | ||
489 | up_write(&rg->lock); | ||
490 | |||
445 | unlock_fb_info(fbi); | 491 | unlock_fb_info(fbi); |
446 | 492 | ||
447 | return r; | 493 | return r; |
@@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev, | |||
453 | struct fb_info *fbi = dev_get_drvdata(dev); | 499 | struct fb_info *fbi = dev_get_drvdata(dev); |
454 | struct omapfb_info *ofbi = FB2OFB(fbi); | 500 | struct omapfb_info *ofbi = FB2OFB(fbi); |
455 | 501 | ||
456 | return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); | 502 | return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); |
457 | } | 503 | } |
458 | 504 | ||
459 | static ssize_t show_virt(struct device *dev, | 505 | static ssize_t show_virt(struct device *dev, |
@@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev, | |||
462 | struct fb_info *fbi = dev_get_drvdata(dev); | 508 | struct fb_info *fbi = dev_get_drvdata(dev); |
463 | struct omapfb_info *ofbi = FB2OFB(fbi); | 509 | struct omapfb_info *ofbi = FB2OFB(fbi); |
464 | 510 | ||
465 | return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); | 511 | return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr); |
466 | } | 512 | } |
467 | 513 | ||
468 | static struct device_attribute omapfb_attrs[] = { | 514 | static struct device_attribute omapfb_attrs[] = { |
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index cd54fdbfd8bb..1305fc9880ba 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #define DEBUG | 27 | #define DEBUG |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include <linux/rwsem.h> | ||
31 | |||
30 | #include <plat/display.h> | 32 | #include <plat/display.h> |
31 | 33 | ||
32 | #ifdef DEBUG | 34 | #ifdef DEBUG |
@@ -44,6 +46,7 @@ extern unsigned int omapfb_debug; | |||
44 | #define OMAPFB_MAX_OVL_PER_FB 3 | 46 | #define OMAPFB_MAX_OVL_PER_FB 3 |
45 | 47 | ||
46 | struct omapfb2_mem_region { | 48 | struct omapfb2_mem_region { |
49 | int id; | ||
47 | u32 paddr; | 50 | u32 paddr; |
48 | void __iomem *vaddr; | 51 | void __iomem *vaddr; |
49 | struct vrfb vrfb; | 52 | struct vrfb vrfb; |
@@ -51,13 +54,15 @@ struct omapfb2_mem_region { | |||
51 | u8 type; /* OMAPFB_PLANE_MEM_* */ | 54 | u8 type; /* OMAPFB_PLANE_MEM_* */ |
52 | bool alloc; /* allocated by the driver */ | 55 | bool alloc; /* allocated by the driver */ |
53 | bool map; /* kernel mapped by the driver */ | 56 | bool map; /* kernel mapped by the driver */ |
57 | atomic_t map_count; | ||
58 | struct rw_semaphore lock; | ||
59 | atomic_t lock_count; | ||
54 | }; | 60 | }; |
55 | 61 | ||
56 | /* appended to fb_info */ | 62 | /* appended to fb_info */ |
57 | struct omapfb_info { | 63 | struct omapfb_info { |
58 | int id; | 64 | int id; |
59 | struct omapfb2_mem_region region; | 65 | struct omapfb2_mem_region *region; |
60 | atomic_t map_count; | ||
61 | int num_overlays; | 66 | int num_overlays; |
62 | struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; | 67 | struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; |
63 | struct omapfb2_device *fbdev; | 68 | struct omapfb2_device *fbdev; |
@@ -76,6 +81,7 @@ struct omapfb2_device { | |||
76 | 81 | ||
77 | unsigned num_fbs; | 82 | unsigned num_fbs; |
78 | struct fb_info *fbs[10]; | 83 | struct fb_info *fbs[10]; |
84 | struct omapfb2_mem_region regions[10]; | ||
79 | 85 | ||
80 | unsigned num_displays; | 86 | unsigned num_displays; |
81 | struct omap_dss_device *displays[10]; | 87 | struct omap_dss_device *displays[10]; |
@@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi, | |||
117 | int dss_mode_to_fb_mode(enum omap_color_mode dssmode, | 123 | int dss_mode_to_fb_mode(enum omap_color_mode dssmode, |
118 | struct fb_var_screeninfo *var); | 124 | struct fb_var_screeninfo *var); |
119 | 125 | ||
126 | int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | ||
127 | u16 posx, u16 posy, u16 outw, u16 outh); | ||
128 | |||
120 | /* find the display connected to this fb, if any */ | 129 | /* find the display connected to this fb, if any */ |
121 | static inline struct omap_dss_device *fb2display(struct fb_info *fbi) | 130 | static inline struct omap_dss_device *fb2display(struct fb_info *fbi) |
122 | { | 131 | { |
@@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl, | |||
148 | struct omap_overlay_info info; | 157 | struct omap_overlay_info info; |
149 | 158 | ||
150 | ovl->get_overlay_info(ovl, &info); | 159 | ovl->get_overlay_info(ovl, &info); |
160 | if (info.enabled == enable) | ||
161 | return 0; | ||
151 | info.enabled = enable; | 162 | info.enabled = enable; |
152 | return ovl->set_overlay_info(ovl, &info); | 163 | return ovl->set_overlay_info(ovl, &info); |
153 | } | 164 | } |
154 | 165 | ||
166 | static inline struct omapfb2_mem_region * | ||
167 | omapfb_get_mem_region(struct omapfb2_mem_region *rg) | ||
168 | { | ||
169 | down_read_nested(&rg->lock, rg->id); | ||
170 | atomic_inc(&rg->lock_count); | ||
171 | return rg; | ||
172 | } | ||
173 | |||
174 | static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg) | ||
175 | { | ||
176 | atomic_dec(&rg->lock_count); | ||
177 | up_read(&rg->lock); | ||
178 | } | ||
179 | |||
155 | #endif | 180 | #endif |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 6552751e81aa..688b055abab2 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
@@ -367,12 +367,12 @@ static int __init p9100_init(void) | |||
367 | if (fb_get_options("p9100fb", NULL)) | 367 | if (fb_get_options("p9100fb", NULL)) |
368 | return -ENODEV; | 368 | return -ENODEV; |
369 | 369 | ||
370 | return of_register_driver(&p9100_driver, &of_bus_type); | 370 | return of_register_platform_driver(&p9100_driver); |
371 | } | 371 | } |
372 | 372 | ||
373 | static void __exit p9100_exit(void) | 373 | static void __exit p9100_exit(void) |
374 | { | 374 | { |
375 | of_unregister_driver(&p9100_driver); | 375 | of_unregister_platform_driver(&p9100_driver); |
376 | } | 376 | } |
377 | 377 | ||
378 | module_init(p9100_init); | 378 | module_init(p9100_init); |
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 489b44e8db81..7288934c0d49 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c | |||
@@ -213,12 +213,12 @@ static int __init gfb_init(void) | |||
213 | if (fb_get_options("gfb", NULL)) | 213 | if (fb_get_options("gfb", NULL)) |
214 | return -ENODEV; | 214 | return -ENODEV; |
215 | 215 | ||
216 | return of_register_driver(&gfb_driver, &of_bus_type); | 216 | return of_register_platform_driver(&gfb_driver); |
217 | } | 217 | } |
218 | 218 | ||
219 | static void __exit gfb_exit(void) | 219 | static void __exit gfb_exit(void) |
220 | { | 220 | { |
221 | of_unregister_driver(&gfb_driver); | 221 | of_unregister_platform_driver(&gfb_driver); |
222 | } | 222 | } |
223 | 223 | ||
224 | module_init(gfb_init); | 224 | module_init(gfb_init); |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index cc039b33d2d8..f375e0db6776 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -526,12 +526,12 @@ static int __init tcx_init(void) | |||
526 | if (fb_get_options("tcxfb", NULL)) | 526 | if (fb_get_options("tcxfb", NULL)) |
527 | return -ENODEV; | 527 | return -ENODEV; |
528 | 528 | ||
529 | return of_register_driver(&tcx_driver, &of_bus_type); | 529 | return of_register_platform_driver(&tcx_driver); |
530 | } | 530 | } |
531 | 531 | ||
532 | static void __exit tcx_exit(void) | 532 | static void __exit tcx_exit(void) |
533 | { | 533 | { |
534 | of_unregister_driver(&tcx_driver); | 534 | of_unregister_platform_driver(&tcx_driver); |
535 | } | 535 | } |
536 | 536 | ||
537 | module_init(tcx_init); | 537 | module_init(tcx_init); |
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 980548390048..3ee5e63cfa4f 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1571,8 +1571,8 @@ out_err_iobase: | |||
1571 | if (default_par->mtrr_handle >= 0) | 1571 | if (default_par->mtrr_handle >= 0) |
1572 | mtrr_del(default_par->mtrr_handle, info->fix.smem_start, | 1572 | mtrr_del(default_par->mtrr_handle, info->fix.smem_start, |
1573 | info->fix.smem_len); | 1573 | info->fix.smem_len); |
1574 | release_mem_region(pci_resource_start(pdev, 2), | 1574 | release_region(pci_resource_start(pdev, 2), |
1575 | pci_resource_len(pdev, 2)); | 1575 | pci_resource_len(pdev, 2)); |
1576 | out_err_screenbase: | 1576 | out_err_screenbase: |
1577 | if (info->screen_base) | 1577 | if (info->screen_base) |
1578 | iounmap(info->screen_base); | 1578 | iounmap(info->screen_base); |
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index d9b6e06e0700..ef1f3de2e052 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h | |||
@@ -160,7 +160,6 @@ struct lvds_setting_information { | |||
160 | int v_active; | 160 | int v_active; |
161 | int bpp; | 161 | int bpp; |
162 | int refresh_rate; | 162 | int refresh_rate; |
163 | int get_lcd_size_method; | ||
164 | int lcd_panel_id; | 163 | int lcd_panel_id; |
165 | int lcd_panel_hres; | 164 | int lcd_panel_hres; |
166 | int lcd_panel_vres; | 165 | int lcd_panel_vres; |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index b996803ae2c1..7dcb4d5bb9c3 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -23,143 +23,341 @@ | |||
23 | #include "global.h" | 23 | #include "global.h" |
24 | 24 | ||
25 | static struct pll_map pll_value[] = { | 25 | static struct pll_map pll_value[] = { |
26 | {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, | 26 | {25175000, |
27 | CX700_25_175M, VX855_25_175M}, | 27 | {99, 7, 3}, |
28 | {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, | 28 | {85, 3, 4}, /* ignoring bit difference: 0x00008000 */ |
29 | CX700_29_581M, VX855_29_581M}, | 29 | {141, 5, 4}, |
30 | {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, | 30 | {141, 5, 4} }, |
31 | CX700_26_880M, VX855_26_880M}, | 31 | {29581000, |
32 | {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, | 32 | {33, 4, 2}, |
33 | CX700_31_490M, VX855_31_490M}, | 33 | {66, 2, 4}, /* ignoring bit difference: 0x00808000 */ |
34 | {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, | 34 | {166, 5, 4}, /* ignoring bit difference: 0x00008000 */ |
35 | CX700_31_500M, VX855_31_500M}, | 35 | {165, 5, 4} }, |
36 | {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, | 36 | {26880000, |
37 | CX700_31_728M, VX855_31_728M}, | 37 | {15, 4, 1}, |
38 | {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, | 38 | {30, 2, 3}, /* ignoring bit difference: 0x00808000 */ |
39 | CX700_32_668M, VX855_32_668M}, | 39 | {150, 5, 4}, |
40 | {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, | 40 | {150, 5, 4} }, |
41 | CX700_36_000M, VX855_36_000M}, | 41 | {31500000, |
42 | {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, | 42 | {53, 3, 3}, /* ignoring bit difference: 0x00008000 */ |
43 | CX700_40_000M, VX855_40_000M}, | 43 | {141, 4, 4}, /* ignoring bit difference: 0x00008000 */ |
44 | {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, | 44 | {176, 5, 4}, |
45 | CX700_41_291M, VX855_41_291M}, | 45 | {176, 5, 4} }, |
46 | {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, | 46 | {31728000, |
47 | CX700_43_163M, VX855_43_163M}, | 47 | {31, 7, 1}, |
48 | {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, | 48 | {177, 5, 4}, /* ignoring bit difference: 0x00008000 */ |
49 | CX700_45_250M, VX855_45_250M}, | 49 | {177, 5, 4}, |
50 | {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, | 50 | {142, 4, 4} }, |
51 | CX700_46_000M, VX855_46_000M}, | 51 | {32688000, |
52 | {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, | 52 | {73, 4, 3}, |
53 | CX700_46_996M, VX855_46_996M}, | 53 | {146, 4, 4}, /* ignoring bit difference: 0x00008000 */ |
54 | {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, | 54 | {183, 5, 4}, |
55 | CX700_48_000M, VX855_48_000M}, | 55 | {146, 4, 4} }, |
56 | {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, | 56 | {36000000, |
57 | CX700_48_875M, VX855_48_875M}, | 57 | {101, 5, 3}, /* ignoring bit difference: 0x00008000 */ |
58 | {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, | 58 | {161, 4, 4}, /* ignoring bit difference: 0x00008000 */ |
59 | CX700_49_500M, VX855_49_500M}, | 59 | {202, 5, 4}, |
60 | {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, | 60 | {161, 4, 4} }, |
61 | CX700_52_406M, VX855_52_406M}, | 61 | {40000000, |
62 | {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, | 62 | {89, 4, 3}, |
63 | CX700_52_977M, VX855_52_977M}, | 63 | {89, 4, 3}, /* ignoring bit difference: 0x00008000 */ |
64 | {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, | 64 | {112, 5, 3}, |
65 | CX700_56_250M, VX855_56_250M}, | 65 | {112, 5, 3} }, |
66 | {CLK_57_275M, 0, 0, 0, VX855_57_275M}, | 66 | {41291000, |
67 | {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, | 67 | {23, 4, 1}, |
68 | CX700_60_466M, VX855_60_466M}, | 68 | {69, 3, 3}, /* ignoring bit difference: 0x00008000 */ |
69 | {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, | 69 | {115, 5, 3}, |
70 | CX700_61_500M, VX855_61_500M}, | 70 | {115, 5, 3} }, |
71 | {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, | 71 | {43163000, |
72 | CX700_65_000M, VX855_65_000M}, | 72 | {121, 5, 3}, |
73 | {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, | 73 | {121, 5, 3}, /* ignoring bit difference: 0x00008000 */ |
74 | CX700_65_178M, VX855_65_178M}, | 74 | {121, 5, 3}, |
75 | {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, | 75 | {121, 5, 3} }, |
76 | CX700_66_750M, VX855_66_750M}, | 76 | {45250000, |
77 | {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, | 77 | {127, 5, 3}, |
78 | CX700_68_179M, VX855_68_179M}, | 78 | {127, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
79 | {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, | 79 | {127, 5, 3}, |
80 | CX700_69_924M, VX855_69_924M}, | 80 | {127, 5, 3} }, |
81 | {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, | 81 | {46000000, |
82 | CX700_70_159M, VX855_70_159M}, | 82 | {90, 7, 2}, |
83 | {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, | 83 | {103, 4, 3}, /* ignoring bit difference: 0x00008000 */ |
84 | CX700_72_000M, VX855_72_000M}, | 84 | {129, 5, 3}, |
85 | {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, | 85 | {103, 4, 3} }, |
86 | CX700_78_750M, VX855_78_750M}, | 86 | {46996000, |
87 | {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, | 87 | {105, 4, 3}, /* ignoring bit difference: 0x00008000 */ |
88 | CX700_80_136M, VX855_80_136M}, | 88 | {131, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
89 | {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, | 89 | {131, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
90 | CX700_83_375M, VX855_83_375M}, | 90 | {105, 4, 3} }, |
91 | {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, | 91 | {48000000, |
92 | CX700_83_950M, VX855_83_950M}, | 92 | {67, 20, 0}, |
93 | {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, | 93 | {134, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
94 | CX700_84_750M, VX855_84_750M}, | 94 | {134, 5, 3}, |
95 | {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, | 95 | {134, 5, 3} }, |
96 | CX700_85_860M, VX855_85_860M}, | 96 | {48875000, |
97 | {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, | 97 | {99, 29, 0}, |
98 | CX700_88_750M, VX855_88_750M}, | 98 | {82, 3, 3}, /* ignoring bit difference: 0x00808000 */ |
99 | {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, | 99 | {82, 3, 3}, /* ignoring bit difference: 0x00808000 */ |
100 | CX700_94_500M, VX855_94_500M}, | 100 | {137, 5, 3} }, |
101 | {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, | 101 | {49500000, |
102 | CX700_97_750M, VX855_97_750M}, | 102 | {83, 6, 2}, |
103 | {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M, | 103 | {83, 3, 3}, /* ignoring bit difference: 0x00008000 */ |
104 | CX700_101_000M, VX855_101_000M}, | 104 | {138, 5, 3}, |
105 | {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M, | 105 | {83, 3, 3} }, |
106 | CX700_106_500M, VX855_106_500M}, | 106 | {52406000, |
107 | {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M, | 107 | {117, 4, 3}, |
108 | CX700_108_000M, VX855_108_000M}, | 108 | {117, 4, 3}, /* ignoring bit difference: 0x00008000 */ |
109 | {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M, | 109 | {117, 4, 3}, |
110 | CX700_113_309M, VX855_113_309M}, | 110 | {88, 3, 3} }, |
111 | {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M, | 111 | {52977000, |
112 | CX700_118_840M, VX855_118_840M}, | 112 | {37, 5, 1}, |
113 | {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M, | 113 | {148, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
114 | CX700_119_000M, VX855_119_000M}, | 114 | {148, 5, 3}, |
115 | {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M, | 115 | {148, 5, 3} }, |
116 | CX700_121_750M, 0}, | 116 | {56250000, |
117 | {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M, | 117 | {55, 7, 1}, /* ignoring bit difference: 0x00008000 */ |
118 | CX700_125_104M, 0}, | 118 | {126, 4, 3}, /* ignoring bit difference: 0x00008000 */ |
119 | {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M, | 119 | {157, 5, 3}, |
120 | CX700_133_308M, 0}, | 120 | {157, 5, 3} }, |
121 | {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M, | 121 | {57275000, |
122 | CX700_135_000M, VX855_135_000M}, | 122 | {0, 0, 0}, |
123 | {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M, | 123 | {2, 2, 0}, |
124 | CX700_136_700M, VX855_136_700M}, | 124 | {2, 2, 0}, |
125 | {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M, | 125 | {157, 5, 3} }, /* ignoring bit difference: 0x00808000 */ |
126 | CX700_138_400M, VX855_138_400M}, | 126 | {60466000, |
127 | {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M, | 127 | {76, 9, 1}, |
128 | CX700_146_760M, VX855_146_760M}, | 128 | {169, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
129 | {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M, | 129 | {169, 5, 3}, /* FIXED: old = {72, 2, 3} */ |
130 | CX700_153_920M, VX855_153_920M}, | 130 | {169, 5, 3} }, |
131 | {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M, | 131 | {61500000, |
132 | CX700_156_000M, VX855_156_000M}, | 132 | {86, 20, 0}, |
133 | {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M, | 133 | {172, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
134 | CX700_157_500M, VX855_157_500M}, | 134 | {172, 5, 3}, |
135 | {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M, | 135 | {172, 5, 3} }, |
136 | CX700_162_000M, VX855_162_000M}, | 136 | {65000000, |
137 | {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M, | 137 | {109, 6, 2}, /* ignoring bit difference: 0x00008000 */ |
138 | CX700_187_000M, VX855_187_000M}, | 138 | {109, 3, 3}, /* ignoring bit difference: 0x00008000 */ |
139 | {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M, | 139 | {109, 3, 3}, |
140 | CX700_193_295M, VX855_193_295M}, | 140 | {109, 3, 3} }, |
141 | {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M, | 141 | {65178000, |
142 | CX700_202_500M, VX855_202_500M}, | 142 | {91, 5, 2}, |
143 | {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M, | 143 | {182, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
144 | CX700_204_000M, VX855_204_000M}, | 144 | {109, 3, 3}, |
145 | {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M, | 145 | {182, 5, 3} }, |
146 | CX700_218_500M, VX855_218_500M}, | 146 | {66750000, |
147 | {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M, | 147 | {75, 4, 2}, |
148 | CX700_234_000M, VX855_234_000M}, | 148 | {150, 4, 3}, /* ignoring bit difference: 0x00808000 */ |
149 | {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M, | 149 | {150, 4, 3}, |
150 | CX700_267_250M, VX855_267_250M}, | 150 | {112, 3, 3} }, |
151 | {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M, | 151 | {68179000, |
152 | CX700_297_500M, VX855_297_500M}, | 152 | {19, 4, 0}, |
153 | {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, | 153 | {114, 3, 3}, /* ignoring bit difference: 0x00008000 */ |
154 | CX700_74_481M, VX855_74_481M}, | 154 | {190, 5, 3}, |
155 | {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M, | 155 | {191, 5, 3} }, |
156 | CX700_172_798M, VX855_172_798M}, | 156 | {69924000, |
157 | {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M, | 157 | {83, 17, 0}, |
158 | CX700_122_614M, VX855_122_614M}, | 158 | {195, 5, 3}, /* ignoring bit difference: 0x00808000 */ |
159 | {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, | 159 | {195, 5, 3}, |
160 | CX700_74_270M, 0}, | 160 | {195, 5, 3} }, |
161 | {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M, | 161 | {70159000, |
162 | CX700_148_500M, VX855_148_500M} | 162 | {98, 20, 0}, |
163 | {196, 5, 3}, /* ignoring bit difference: 0x00808000 */ | ||
164 | {196, 5, 3}, | ||
165 | {195, 5, 3} }, | ||
166 | {72000000, | ||
167 | {121, 24, 0}, | ||
168 | {161, 4, 3}, /* ignoring bit difference: 0x00808000 */ | ||
169 | {161, 4, 3}, | ||
170 | {161, 4, 3} }, | ||
171 | {78750000, | ||
172 | {33, 3, 1}, | ||
173 | {66, 3, 2}, /* ignoring bit difference: 0x00008000 */ | ||
174 | {110, 5, 2}, | ||
175 | {110, 5, 2} }, | ||
176 | {80136000, | ||
177 | {28, 5, 0}, | ||
178 | {68, 3, 2}, /* ignoring bit difference: 0x00008000 */ | ||
179 | {112, 5, 2}, | ||
180 | {112, 5, 2} }, | ||
181 | {83375000, | ||
182 | {93, 2, 3}, | ||
183 | {93, 4, 2}, /* ignoring bit difference: 0x00800000 */ | ||
184 | {93, 4, 2}, /* ignoring bit difference: 0x00800000 */ | ||
185 | {117, 5, 2} }, | ||
186 | {83950000, | ||
187 | {41, 7, 0}, | ||
188 | {117, 5, 2}, /* ignoring bit difference: 0x00008000 */ | ||
189 | {117, 5, 2}, | ||
190 | {117, 5, 2} }, | ||
191 | {84750000, | ||
192 | {118, 5, 2}, | ||
193 | {118, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
194 | {118, 5, 2}, | ||
195 | {118, 5, 2} }, | ||
196 | {85860000, | ||
197 | {84, 7, 1}, | ||
198 | {120, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
199 | {120, 5, 2}, | ||
200 | {118, 5, 2} }, | ||
201 | {88750000, | ||
202 | {31, 5, 0}, | ||
203 | {124, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
204 | {174, 7, 2}, /* ignoring bit difference: 0x00808000 */ | ||
205 | {124, 5, 2} }, | ||
206 | {94500000, | ||
207 | {33, 5, 0}, | ||
208 | {132, 5, 2}, /* ignoring bit difference: 0x00008000 */ | ||
209 | {132, 5, 2}, | ||
210 | {132, 5, 2} }, | ||
211 | {97750000, | ||
212 | {82, 6, 1}, | ||
213 | {137, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
214 | {137, 5, 2}, | ||
215 | {137, 5, 2} }, | ||
216 | {101000000, | ||
217 | {127, 9, 1}, | ||
218 | {141, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
219 | {141, 5, 2}, | ||
220 | {141, 5, 2} }, | ||
221 | {106500000, | ||
222 | {119, 4, 2}, | ||
223 | {119, 4, 2}, /* ignoring bit difference: 0x00808000 */ | ||
224 | {119, 4, 2}, | ||
225 | {149, 5, 2} }, | ||
226 | {108000000, | ||
227 | {121, 4, 2}, | ||
228 | {121, 4, 2}, /* ignoring bit difference: 0x00808000 */ | ||
229 | {151, 5, 2}, | ||
230 | {151, 5, 2} }, | ||
231 | {113309000, | ||
232 | {95, 12, 0}, | ||
233 | {95, 3, 2}, /* ignoring bit difference: 0x00808000 */ | ||
234 | {95, 3, 2}, | ||
235 | {159, 5, 2} }, | ||
236 | {118840000, | ||
237 | {83, 5, 1}, | ||
238 | {166, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
239 | {166, 5, 2}, | ||
240 | {166, 5, 2} }, | ||
241 | {119000000, | ||
242 | {108, 13, 0}, | ||
243 | {133, 4, 2}, /* ignoring bit difference: 0x00808000 */ | ||
244 | {133, 4, 2}, | ||
245 | {167, 5, 2} }, | ||
246 | {121750000, | ||
247 | {85, 5, 1}, | ||
248 | {170, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
249 | {68, 2, 2}, | ||
250 | {0, 0, 0} }, | ||
251 | {125104000, | ||
252 | {53, 6, 0}, /* ignoring bit difference: 0x00008000 */ | ||
253 | {106, 3, 2}, /* ignoring bit difference: 0x00008000 */ | ||
254 | {175, 5, 2}, | ||
255 | {0, 0, 0} }, | ||
256 | {135000000, | ||
257 | {94, 5, 1}, | ||
258 | {28, 3, 0}, /* ignoring bit difference: 0x00804000 */ | ||
259 | {151, 4, 2}, | ||
260 | {189, 5, 2} }, | ||
261 | {136700000, | ||
262 | {115, 12, 0}, | ||
263 | {191, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
264 | {191, 5, 2}, | ||
265 | {191, 5, 2} }, | ||
266 | {138400000, | ||
267 | {87, 9, 0}, | ||
268 | {116, 3, 2}, /* ignoring bit difference: 0x00808000 */ | ||
269 | {116, 3, 2}, | ||
270 | {194, 5, 2} }, | ||
271 | {146760000, | ||
272 | {103, 5, 1}, | ||
273 | {206, 5, 2}, /* ignoring bit difference: 0x00808000 */ | ||
274 | {206, 5, 2}, | ||
275 | {206, 5, 2} }, | ||
276 | {153920000, | ||
277 | {86, 8, 0}, | ||
278 | {86, 4, 1}, /* ignoring bit difference: 0x00808000 */ | ||
279 | {86, 4, 1}, | ||
280 | {86, 4, 1} }, /* FIXED: old = {84, 2, 1} */ | ||
281 | {156000000, | ||
282 | {109, 5, 1}, | ||
283 | {109, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
284 | {109, 5, 1}, | ||
285 | {108, 5, 1} }, | ||
286 | {157500000, | ||
287 | {55, 5, 0}, /* ignoring bit difference: 0x00008000 */ | ||
288 | {22, 2, 0}, /* ignoring bit difference: 0x00802000 */ | ||
289 | {110, 5, 1}, | ||
290 | {110, 5, 1} }, | ||
291 | {162000000, | ||
292 | {113, 5, 1}, | ||
293 | {113, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
294 | {113, 5, 1}, | ||
295 | {113, 5, 1} }, | ||
296 | {187000000, | ||
297 | {118, 9, 0}, | ||
298 | {131, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
299 | {131, 5, 1}, | ||
300 | {131, 5, 1} }, | ||
301 | {193295000, | ||
302 | {108, 8, 0}, | ||
303 | {81, 3, 1}, /* ignoring bit difference: 0x00808000 */ | ||
304 | {135, 5, 1}, | ||
305 | {135, 5, 1} }, | ||
306 | {202500000, | ||
307 | {99, 7, 0}, | ||
308 | {85, 3, 1}, /* ignoring bit difference: 0x00808000 */ | ||
309 | {142, 5, 1}, | ||
310 | {142, 5, 1} }, | ||
311 | {204000000, | ||
312 | {100, 7, 0}, | ||
313 | {143, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
314 | {143, 5, 1}, | ||
315 | {143, 5, 1} }, | ||
316 | {218500000, | ||
317 | {92, 6, 0}, | ||
318 | {153, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
319 | {153, 5, 1}, | ||
320 | {153, 5, 1} }, | ||
321 | {234000000, | ||
322 | {98, 6, 0}, | ||
323 | {98, 3, 1}, /* ignoring bit difference: 0x00008000 */ | ||
324 | {98, 3, 1}, | ||
325 | {164, 5, 1} }, | ||
326 | {267250000, | ||
327 | {112, 6, 0}, | ||
328 | {112, 3, 1}, /* ignoring bit difference: 0x00808000 */ | ||
329 | {187, 5, 1}, | ||
330 | {187, 5, 1} }, | ||
331 | {297500000, | ||
332 | {102, 5, 0}, /* ignoring bit difference: 0x00008000 */ | ||
333 | {166, 4, 1}, /* ignoring bit difference: 0x00008000 */ | ||
334 | {208, 5, 1}, | ||
335 | {208, 5, 1} }, | ||
336 | {74481000, | ||
337 | {26, 5, 0}, | ||
338 | {125, 3, 3}, /* ignoring bit difference: 0x00808000 */ | ||
339 | {208, 5, 3}, | ||
340 | {209, 5, 3} }, | ||
341 | {172798000, | ||
342 | {121, 5, 1}, | ||
343 | {121, 5, 1}, /* ignoring bit difference: 0x00808000 */ | ||
344 | {121, 5, 1}, | ||
345 | {121, 5, 1} }, | ||
346 | {122614000, | ||
347 | {60, 7, 0}, | ||
348 | {137, 4, 2}, /* ignoring bit difference: 0x00808000 */ | ||
349 | {137, 4, 2}, | ||
350 | {172, 5, 2} }, | ||
351 | {74270000, | ||
352 | {83, 8, 1}, | ||
353 | {208, 5, 3}, | ||
354 | {208, 5, 3}, | ||
355 | {0, 0, 0} }, | ||
356 | {148500000, | ||
357 | {83, 8, 0}, | ||
358 | {208, 5, 2}, | ||
359 | {166, 4, 2}, | ||
360 | {208, 5, 2} } | ||
163 | }; | 361 | }; |
164 | 362 | ||
165 | static struct fifo_depth_select display_fifo_depth_reg = { | 363 | static struct fifo_depth_select display_fifo_depth_reg = { |
@@ -1360,40 +1558,70 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) | |||
1360 | 1558 | ||
1361 | } | 1559 | } |
1362 | 1560 | ||
1561 | static u32 cle266_encode_pll(struct pll_config pll) | ||
1562 | { | ||
1563 | return (pll.multiplier << 8) | ||
1564 | | (pll.rshift << 6) | ||
1565 | | pll.divisor; | ||
1566 | } | ||
1567 | |||
1568 | static u32 k800_encode_pll(struct pll_config pll) | ||
1569 | { | ||
1570 | return ((pll.divisor - 2) << 16) | ||
1571 | | (pll.rshift << 10) | ||
1572 | | (pll.multiplier - 2); | ||
1573 | } | ||
1574 | |||
1575 | static u32 vx855_encode_pll(struct pll_config pll) | ||
1576 | { | ||
1577 | return (pll.divisor << 16) | ||
1578 | | (pll.rshift << 10) | ||
1579 | | pll.multiplier; | ||
1580 | } | ||
1581 | |||
1363 | u32 viafb_get_clk_value(int clk) | 1582 | u32 viafb_get_clk_value(int clk) |
1364 | { | 1583 | { |
1365 | int i; | 1584 | u32 value = 0; |
1585 | int i = 0; | ||
1366 | 1586 | ||
1367 | for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) { | 1587 | while (i < NUM_TOTAL_PLL_TABLE && clk != pll_value[i].clk) |
1368 | if (clk == pll_value[i].clk) { | 1588 | i++; |
1369 | switch (viaparinfo->chip_info->gfx_chip_name) { | 1589 | |
1370 | case UNICHROME_CLE266: | 1590 | if (i == NUM_TOTAL_PLL_TABLE) { |
1371 | case UNICHROME_K400: | 1591 | printk(KERN_WARNING "viafb_get_clk_value: PLL lookup failed!"); |
1372 | return pll_value[i].cle266_pll; | 1592 | } else { |
1373 | 1593 | switch (viaparinfo->chip_info->gfx_chip_name) { | |
1374 | case UNICHROME_K800: | 1594 | case UNICHROME_CLE266: |
1375 | case UNICHROME_PM800: | 1595 | case UNICHROME_K400: |
1376 | case UNICHROME_CN700: | 1596 | value = cle266_encode_pll(pll_value[i].cle266_pll); |
1377 | return pll_value[i].k800_pll; | 1597 | break; |
1378 | 1598 | ||
1379 | case UNICHROME_CX700: | 1599 | case UNICHROME_K800: |
1380 | case UNICHROME_K8M890: | 1600 | case UNICHROME_PM800: |
1381 | case UNICHROME_P4M890: | 1601 | case UNICHROME_CN700: |
1382 | case UNICHROME_P4M900: | 1602 | value = k800_encode_pll(pll_value[i].k800_pll); |
1383 | case UNICHROME_VX800: | 1603 | break; |
1384 | return pll_value[i].cx700_pll; | 1604 | |
1385 | case UNICHROME_VX855: | 1605 | case UNICHROME_CX700: |
1386 | return pll_value[i].vx855_pll; | 1606 | case UNICHROME_CN750: |
1387 | } | 1607 | case UNICHROME_K8M890: |
1608 | case UNICHROME_P4M890: | ||
1609 | case UNICHROME_P4M900: | ||
1610 | case UNICHROME_VX800: | ||
1611 | value = k800_encode_pll(pll_value[i].cx700_pll); | ||
1612 | break; | ||
1613 | |||
1614 | case UNICHROME_VX855: | ||
1615 | value = vx855_encode_pll(pll_value[i].vx855_pll); | ||
1616 | break; | ||
1388 | } | 1617 | } |
1389 | } | 1618 | } |
1390 | 1619 | ||
1391 | DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n"); | 1620 | return value; |
1392 | return 0; | ||
1393 | } | 1621 | } |
1394 | 1622 | ||
1395 | /* Set VCLK*/ | 1623 | /* Set VCLK*/ |
1396 | void viafb_set_vclock(u32 CLK, int set_iga) | 1624 | void viafb_set_vclock(u32 clk, int set_iga) |
1397 | { | 1625 | { |
1398 | /* H.W. Reset : ON */ | 1626 | /* H.W. Reset : ON */ |
1399 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | 1627 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); |
@@ -1403,26 +1631,23 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1403 | switch (viaparinfo->chip_info->gfx_chip_name) { | 1631 | switch (viaparinfo->chip_info->gfx_chip_name) { |
1404 | case UNICHROME_CLE266: | 1632 | case UNICHROME_CLE266: |
1405 | case UNICHROME_K400: | 1633 | case UNICHROME_K400: |
1406 | viafb_write_reg(SR46, VIASR, CLK / 0x100); | 1634 | via_write_reg(VIASR, SR46, (clk & 0x00FF)); |
1407 | viafb_write_reg(SR47, VIASR, CLK % 0x100); | 1635 | via_write_reg(VIASR, SR47, (clk & 0xFF00) >> 8); |
1408 | break; | 1636 | break; |
1409 | 1637 | ||
1410 | case UNICHROME_K800: | 1638 | case UNICHROME_K800: |
1411 | case UNICHROME_PM800: | 1639 | case UNICHROME_PM800: |
1412 | case UNICHROME_CN700: | 1640 | case UNICHROME_CN700: |
1413 | case UNICHROME_CX700: | 1641 | case UNICHROME_CX700: |
1642 | case UNICHROME_CN750: | ||
1414 | case UNICHROME_K8M890: | 1643 | case UNICHROME_K8M890: |
1415 | case UNICHROME_P4M890: | 1644 | case UNICHROME_P4M890: |
1416 | case UNICHROME_P4M900: | 1645 | case UNICHROME_P4M900: |
1417 | case UNICHROME_VX800: | 1646 | case UNICHROME_VX800: |
1418 | case UNICHROME_VX855: | 1647 | case UNICHROME_VX855: |
1419 | viafb_write_reg(SR44, VIASR, CLK / 0x10000); | 1648 | via_write_reg(VIASR, SR44, (clk & 0x0000FF)); |
1420 | DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000); | 1649 | via_write_reg(VIASR, SR45, (clk & 0x00FF00) >> 8); |
1421 | viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100); | 1650 | via_write_reg(VIASR, SR46, (clk & 0xFF0000) >> 16); |
1422 | DEBUG_MSG(KERN_INFO "\nSR45=%x", | ||
1423 | (CLK & 0xFFFF) / 0x100); | ||
1424 | viafb_write_reg(SR46, VIASR, CLK % 0x100); | ||
1425 | DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100); | ||
1426 | break; | 1651 | break; |
1427 | } | 1652 | } |
1428 | } | 1653 | } |
@@ -1432,22 +1657,23 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1432 | switch (viaparinfo->chip_info->gfx_chip_name) { | 1657 | switch (viaparinfo->chip_info->gfx_chip_name) { |
1433 | case UNICHROME_CLE266: | 1658 | case UNICHROME_CLE266: |
1434 | case UNICHROME_K400: | 1659 | case UNICHROME_K400: |
1435 | viafb_write_reg(SR44, VIASR, CLK / 0x100); | 1660 | via_write_reg(VIASR, SR44, (clk & 0x00FF)); |
1436 | viafb_write_reg(SR45, VIASR, CLK % 0x100); | 1661 | via_write_reg(VIASR, SR45, (clk & 0xFF00) >> 8); |
1437 | break; | 1662 | break; |
1438 | 1663 | ||
1439 | case UNICHROME_K800: | 1664 | case UNICHROME_K800: |
1440 | case UNICHROME_PM800: | 1665 | case UNICHROME_PM800: |
1441 | case UNICHROME_CN700: | 1666 | case UNICHROME_CN700: |
1442 | case UNICHROME_CX700: | 1667 | case UNICHROME_CX700: |
1668 | case UNICHROME_CN750: | ||
1443 | case UNICHROME_K8M890: | 1669 | case UNICHROME_K8M890: |
1444 | case UNICHROME_P4M890: | 1670 | case UNICHROME_P4M890: |
1445 | case UNICHROME_P4M900: | 1671 | case UNICHROME_P4M900: |
1446 | case UNICHROME_VX800: | 1672 | case UNICHROME_VX800: |
1447 | case UNICHROME_VX855: | 1673 | case UNICHROME_VX855: |
1448 | viafb_write_reg(SR4A, VIASR, CLK / 0x10000); | 1674 | via_write_reg(VIASR, SR4A, (clk & 0x0000FF)); |
1449 | viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100); | 1675 | via_write_reg(VIASR, SR4B, (clk & 0x00FF00) >> 8); |
1450 | viafb_write_reg(SR4C, VIASR, CLK % 0x100); | 1676 | via_write_reg(VIASR, SR4C, (clk & 0xFF0000) >> 16); |
1451 | break; | 1677 | break; |
1452 | } | 1678 | } |
1453 | } | 1679 | } |
@@ -1791,8 +2017,6 @@ void viafb_init_chip_info(int chip_type) | |||
1791 | viafb_set_iga_path(); | 2017 | viafb_set_iga_path(); |
1792 | 2018 | ||
1793 | viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method; | 2019 | viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method; |
1794 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
1795 | GET_LCD_SIZE_BY_USER_SETTING; | ||
1796 | viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode; | 2020 | viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode; |
1797 | viaparinfo->lvds_setting_info2->display_method = | 2021 | viaparinfo->lvds_setting_info2->display_method = |
1798 | viaparinfo->lvds_setting_info->display_method; | 2022 | viaparinfo->lvds_setting_info->display_method; |
@@ -1946,13 +2170,6 @@ static void init_tmds_chip_info(void) | |||
1946 | 2170 | ||
1947 | static void init_lvds_chip_info(void) | 2171 | static void init_lvds_chip_info(void) |
1948 | { | 2172 | { |
1949 | if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM) | ||
1950 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
1951 | GET_LCD_SIZE_BY_VGA_BIOS; | ||
1952 | else | ||
1953 | viaparinfo->lvds_setting_info->get_lcd_size_method = | ||
1954 | GET_LCD_SIZE_BY_USER_SETTING; | ||
1955 | |||
1956 | viafb_lvds_trasmitter_identify(); | 2173 | viafb_lvds_trasmitter_identify(); |
1957 | viafb_init_lcd_size(); | 2174 | viafb_init_lcd_size(); |
1958 | viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info, | 2175 | viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info, |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index a109de379816..c44399895294 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -700,12 +700,18 @@ struct _lcd_scaling_factor { | |||
700 | struct _lcd_ver_scaling_factor lcd_ver_scaling_factor; | 700 | struct _lcd_ver_scaling_factor lcd_ver_scaling_factor; |
701 | }; | 701 | }; |
702 | 702 | ||
703 | struct pll_config { | ||
704 | u16 multiplier; | ||
705 | u8 divisor; | ||
706 | u8 rshift; | ||
707 | }; | ||
708 | |||
703 | struct pll_map { | 709 | struct pll_map { |
704 | u32 clk; | 710 | u32 clk; |
705 | u32 cle266_pll; | 711 | struct pll_config cle266_pll; |
706 | u32 k800_pll; | 712 | struct pll_config k800_pll; |
707 | u32 cx700_pll; | 713 | struct pll_config cx700_pll; |
708 | u32 vx855_pll; | 714 | struct pll_config vx855_pll; |
709 | }; | 715 | }; |
710 | 716 | ||
711 | struct rgbLUT { | 717 | struct rgbLUT { |
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h index c430fa23008a..6010d10b59e8 100644 --- a/drivers/video/via/ioctl.h +++ b/drivers/video/via/ioctl.h | |||
@@ -35,11 +35,9 @@ | |||
35 | #define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */ | 35 | #define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */ |
36 | #define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */ | 36 | #define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */ |
37 | #define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */ | 37 | #define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */ |
38 | #define VIAFB_SET_DEVICE 0x5649410A | ||
39 | #define VIAFB_GET_DEVICE 0x5649410B | 38 | #define VIAFB_GET_DEVICE 0x5649410B |
40 | #define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */ | 39 | #define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */ |
41 | #define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */ | 40 | #define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */ |
42 | #define VIAFB_SET_DEVICE_INFO 0x56494114 | ||
43 | #define VIAFB_GET_DEVICE_INFO 0x56494115 | 41 | #define VIAFB_GET_DEVICE_INFO 0x56494115 |
44 | 42 | ||
45 | #define VIAFB_GET_DEVICE_SUPPORT 0x56494118 | 43 | #define VIAFB_GET_DEVICE_SUPPORT 0x56494118 |
@@ -50,7 +48,6 @@ | |||
50 | #define VIAFB_GET_GAMMA_LUT 0x56494124 | 48 | #define VIAFB_GET_GAMMA_LUT 0x56494124 |
51 | #define VIAFB_SET_GAMMA_LUT 0x56494125 | 49 | #define VIAFB_SET_GAMMA_LUT 0x56494125 |
52 | #define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126 | 50 | #define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126 |
53 | #define VIAFB_SET_SECOND_MODE 0x56494129 | ||
54 | #define VIAFB_SYNC_SURFACE 0x56494130 | 51 | #define VIAFB_SYNC_SURFACE 0x56494130 |
55 | #define VIAFB_GET_DRIVER_CAPS 0x56494131 | 52 | #define VIAFB_GET_DRIVER_CAPS 0x56494131 |
56 | #define VIAFB_GET_IGA_SCALING_INFO 0x56494132 | 53 | #define VIAFB_GET_IGA_SCALING_INFO 0x56494132 |
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 2ab0f156439a..fc25ae30c5f6 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c | |||
@@ -75,8 +75,6 @@ static void check_diport_of_integrated_lvds( | |||
75 | static struct display_timing lcd_centering_timging(struct display_timing | 75 | static struct display_timing lcd_centering_timging(struct display_timing |
76 | mode_crt_reg, | 76 | mode_crt_reg, |
77 | struct display_timing panel_crt_reg); | 77 | struct display_timing panel_crt_reg); |
78 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, | ||
79 | int set_vres, int panel_hres, int panel_vres); | ||
80 | 78 | ||
81 | static int check_lvds_chip(int device_id_subaddr, int device_id) | 79 | static int check_lvds_chip(int device_id_subaddr, int device_id) |
82 | { | 80 | { |
@@ -89,33 +87,8 @@ static int check_lvds_chip(int device_id_subaddr, int device_id) | |||
89 | void viafb_init_lcd_size(void) | 87 | void viafb_init_lcd_size(void) |
90 | { | 88 | { |
91 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); | 89 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); |
92 | DEBUG_MSG(KERN_INFO | ||
93 | "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n", | ||
94 | viaparinfo->lvds_setting_info->get_lcd_size_method); | ||
95 | 90 | ||
96 | switch (viaparinfo->lvds_setting_info->get_lcd_size_method) { | 91 | fp_id_to_vindex(viafb_lcd_panel_id); |
97 | case GET_LCD_SIZE_BY_SYSTEM_BIOS: | ||
98 | break; | ||
99 | case GET_LCD_SZIE_BY_HW_STRAPPING: | ||
100 | break; | ||
101 | case GET_LCD_SIZE_BY_VGA_BIOS: | ||
102 | DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); | ||
103 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
104 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | ||
105 | viaparinfo->lvds_setting_info->lcd_panel_id); | ||
106 | break; | ||
107 | case GET_LCD_SIZE_BY_USER_SETTING: | ||
108 | DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); | ||
109 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
110 | DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", | ||
111 | viaparinfo->lvds_setting_info->lcd_panel_id); | ||
112 | break; | ||
113 | default: | ||
114 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); | ||
115 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
116 | LCD_PANEL_ID1_800X600; | ||
117 | fp_id_to_vindex(LCD_PANEL_ID1_800X600); | ||
118 | } | ||
119 | viaparinfo->lvds_setting_info2->lcd_panel_id = | 92 | viaparinfo->lvds_setting_info2->lcd_panel_id = |
120 | viaparinfo->lvds_setting_info->lcd_panel_id; | 93 | viaparinfo->lvds_setting_info->lcd_panel_id; |
121 | viaparinfo->lvds_setting_info2->lcd_panel_hres = | 94 | viaparinfo->lvds_setting_info2->lcd_panel_hres = |
@@ -437,14 +410,9 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | |||
437 | 410 | ||
438 | /* LCD Scaling Enable */ | 411 | /* LCD Scaling Enable */ |
439 | viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2); | 412 | viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2); |
440 | if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) { | ||
441 | viafb_load_scaling_factor_for_p4m900(set_hres, set_vres, | ||
442 | panel_hres, panel_vres); | ||
443 | return; | ||
444 | } | ||
445 | 413 | ||
446 | /* Check if expansion for horizontal */ | 414 | /* Check if expansion for horizontal */ |
447 | if (set_hres != panel_hres) { | 415 | if (set_hres < panel_hres) { |
448 | /* Load Horizontal Scaling Factor */ | 416 | /* Load Horizontal Scaling Factor */ |
449 | switch (viaparinfo->chip_info->gfx_chip_name) { | 417 | switch (viaparinfo->chip_info->gfx_chip_name) { |
450 | case UNICHROME_CLE266: | 418 | case UNICHROME_CLE266: |
@@ -464,6 +432,10 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | |||
464 | case UNICHROME_CX700: | 432 | case UNICHROME_CX700: |
465 | case UNICHROME_K8M890: | 433 | case UNICHROME_K8M890: |
466 | case UNICHROME_P4M890: | 434 | case UNICHROME_P4M890: |
435 | case UNICHROME_P4M900: | ||
436 | case UNICHROME_CN750: | ||
437 | case UNICHROME_VX800: | ||
438 | case UNICHROME_VX855: | ||
467 | reg_value = | 439 | reg_value = |
468 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | 440 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); |
469 | /* Horizontal scaling enabled */ | 441 | /* Horizontal scaling enabled */ |
@@ -483,7 +455,7 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | |||
483 | } | 455 | } |
484 | 456 | ||
485 | /* Check if expansion for vertical */ | 457 | /* Check if expansion for vertical */ |
486 | if (set_vres != panel_vres) { | 458 | if (set_vres < panel_vres) { |
487 | /* Load Vertical Scaling Factor */ | 459 | /* Load Vertical Scaling Factor */ |
488 | switch (viaparinfo->chip_info->gfx_chip_name) { | 460 | switch (viaparinfo->chip_info->gfx_chip_name) { |
489 | case UNICHROME_CLE266: | 461 | case UNICHROME_CLE266: |
@@ -503,6 +475,10 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | |||
503 | case UNICHROME_CX700: | 475 | case UNICHROME_CX700: |
504 | case UNICHROME_K8M890: | 476 | case UNICHROME_K8M890: |
505 | case UNICHROME_P4M890: | 477 | case UNICHROME_P4M890: |
478 | case UNICHROME_P4M900: | ||
479 | case UNICHROME_CN750: | ||
480 | case UNICHROME_VX800: | ||
481 | case UNICHROME_VX855: | ||
506 | reg_value = | 482 | reg_value = |
507 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | 483 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); |
508 | /* Vertical scaling enabled */ | 484 | /* Vertical scaling enabled */ |
@@ -648,9 +624,8 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
648 | (mode_crt_reg, panel_crt_reg), IGA1); | 624 | (mode_crt_reg, panel_crt_reg), IGA1); |
649 | } else { | 625 | } else { |
650 | /* Expansion */ | 626 | /* Expansion */ |
651 | if ((plvds_setting_info->display_method == | 627 | if (plvds_setting_info->display_method == LCD_EXPANDSION |
652 | LCD_EXPANDSION) & ((set_hres != panel_hres) | 628 | && (set_hres < panel_hres || set_vres < panel_vres)) { |
653 | || (set_vres != panel_vres))) { | ||
654 | /* expansion timing IGA2 loaded panel set timing*/ | 629 | /* expansion timing IGA2 loaded panel set timing*/ |
655 | viafb_load_crtc_timing(panel_crt_reg, IGA2); | 630 | viafb_load_crtc_timing(panel_crt_reg, IGA2); |
656 | DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); | 631 | DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); |
@@ -1139,69 +1114,3 @@ bool viafb_lcd_get_mobile_state(bool *mobile) | |||
1139 | return false; | 1114 | return false; |
1140 | } | 1115 | } |
1141 | } | 1116 | } |
1142 | |||
1143 | static void viafb_load_scaling_factor_for_p4m900(int set_hres, | ||
1144 | int set_vres, int panel_hres, int panel_vres) | ||
1145 | { | ||
1146 | int h_scaling_factor; | ||
1147 | int v_scaling_factor; | ||
1148 | u8 cra2 = 0; | ||
1149 | u8 cr77 = 0; | ||
1150 | u8 cr78 = 0; | ||
1151 | u8 cr79 = 0; | ||
1152 | u8 cr9f = 0; | ||
1153 | /* Check if expansion for horizontal */ | ||
1154 | if (set_hres < panel_hres) { | ||
1155 | /* Load Horizontal Scaling Factor */ | ||
1156 | |||
1157 | /* For VIA_K8M800 or later chipsets. */ | ||
1158 | h_scaling_factor = | ||
1159 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
1160 | /* HSCaleFactor[1:0] at CR9F[1:0] */ | ||
1161 | cr9f = h_scaling_factor & 0x0003; | ||
1162 | /* HSCaleFactor[9:2] at CR77[7:0] */ | ||
1163 | cr77 = (h_scaling_factor & 0x03FC) >> 2; | ||
1164 | /* HSCaleFactor[11:10] at CR79[5:4] */ | ||
1165 | cr79 = (h_scaling_factor & 0x0C00) >> 10; | ||
1166 | cr79 <<= 4; | ||
1167 | |||
1168 | /* Horizontal scaling enabled */ | ||
1169 | cra2 = 0xC0; | ||
1170 | |||
1171 | DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n", | ||
1172 | h_scaling_factor); | ||
1173 | } else { | ||
1174 | /* Horizontal scaling disabled */ | ||
1175 | cra2 = 0x00; | ||
1176 | } | ||
1177 | |||
1178 | /* Check if expansion for vertical */ | ||
1179 | if (set_vres < panel_vres) { | ||
1180 | /* Load Vertical Scaling Factor */ | ||
1181 | |||
1182 | /* For VIA_K8M800 or later chipsets. */ | ||
1183 | v_scaling_factor = | ||
1184 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
1185 | |||
1186 | /* Vertical scaling enabled */ | ||
1187 | cra2 |= 0x08; | ||
1188 | /* VSCaleFactor[0] at CR79[3] */ | ||
1189 | cr79 |= ((v_scaling_factor & 0x0001) << 3); | ||
1190 | /* VSCaleFactor[8:1] at CR78[7:0] */ | ||
1191 | cr78 |= (v_scaling_factor & 0x01FE) >> 1; | ||
1192 | /* VSCaleFactor[10:9] at CR79[7:6] */ | ||
1193 | cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6; | ||
1194 | |||
1195 | DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n", | ||
1196 | v_scaling_factor); | ||
1197 | } else { | ||
1198 | /* Vertical scaling disabled */ | ||
1199 | cra2 |= 0x00; | ||
1200 | } | ||
1201 | |||
1202 | viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7); | ||
1203 | viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF); | ||
1204 | viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF); | ||
1205 | viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8); | ||
1206 | viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1); | ||
1207 | } | ||
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 9762ec62b495..b348efc360b8 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h | |||
@@ -28,11 +28,6 @@ | |||
28 | #define VT3271_DEVICE_ID_REG 0x02 | 28 | #define VT3271_DEVICE_ID_REG 0x02 |
29 | #define VT3271_DEVICE_ID 0x71 | 29 | #define VT3271_DEVICE_ID 0x71 |
30 | 30 | ||
31 | #define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01 | ||
32 | #define GET_LCD_SIZE_BY_VGA_BIOS 0x02 | ||
33 | #define GET_LCD_SZIE_BY_HW_STRAPPING 0x03 | ||
34 | #define GET_LCD_SIZE_BY_USER_SETTING 0x04 | ||
35 | |||
36 | /* Definition DVI Panel ID*/ | 31 | /* Definition DVI Panel ID*/ |
37 | /* Resolution: 640x480, Channel: single, Dithering: Enable */ | 32 | /* Resolution: 640x480, Channel: single, Dithering: Enable */ |
38 | #define LCD_PANEL_ID0_640X480 0x00 | 33 | #define LCD_PANEL_ID0_640X480 0x00 |
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 7f0de7f006ad..2cbe1031b421 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h | |||
@@ -631,7 +631,6 @@ | |||
631 | #define CLK_25_175M 25175000 | 631 | #define CLK_25_175M 25175000 |
632 | #define CLK_26_880M 26880000 | 632 | #define CLK_26_880M 26880000 |
633 | #define CLK_29_581M 29581000 | 633 | #define CLK_29_581M 29581000 |
634 | #define CLK_31_490M 31490000 | ||
635 | #define CLK_31_500M 31500000 | 634 | #define CLK_31_500M 31500000 |
636 | #define CLK_31_728M 31728000 | 635 | #define CLK_31_728M 31728000 |
637 | #define CLK_32_668M 32688000 | 636 | #define CLK_32_668M 32688000 |
@@ -676,7 +675,6 @@ | |||
676 | #define CLK_119_000M 119000000 | 675 | #define CLK_119_000M 119000000 |
677 | #define CLK_121_750M 121750000 /* 121.704MHz */ | 676 | #define CLK_121_750M 121750000 /* 121.704MHz */ |
678 | #define CLK_125_104M 125104000 | 677 | #define CLK_125_104M 125104000 |
679 | #define CLK_133_308M 133308000 | ||
680 | #define CLK_135_000M 135000000 | 678 | #define CLK_135_000M 135000000 |
681 | #define CLK_136_700M 136700000 | 679 | #define CLK_136_700M 136700000 |
682 | #define CLK_138_400M 138400000 | 680 | #define CLK_138_400M 138400000 |
@@ -699,313 +697,6 @@ | |||
699 | #define CLK_172_798M 172798000 | 697 | #define CLK_172_798M 172798000 |
700 | #define CLK_122_614M 122614000 | 698 | #define CLK_122_614M 122614000 |
701 | 699 | ||
702 | /* CLE266 PLL value | ||
703 | */ | ||
704 | #define CLE266_PLL_25_175M 0x0000C763 | ||
705 | #define CLE266_PLL_26_880M 0x0000440F | ||
706 | #define CLE266_PLL_29_581M 0x00008421 | ||
707 | #define CLE266_PLL_31_490M 0x00004721 | ||
708 | #define CLE266_PLL_31_500M 0x0000C3B5 | ||
709 | #define CLE266_PLL_31_728M 0x0000471F | ||
710 | #define CLE266_PLL_32_668M 0x0000C449 | ||
711 | #define CLE266_PLL_36_000M 0x0000C5E5 | ||
712 | #define CLE266_PLL_40_000M 0x0000C459 | ||
713 | #define CLE266_PLL_41_291M 0x00004417 | ||
714 | #define CLE266_PLL_43_163M 0x0000C579 | ||
715 | #define CLE266_PLL_45_250M 0x0000C57F /* 45.46MHz */ | ||
716 | #define CLE266_PLL_46_000M 0x0000875A | ||
717 | #define CLE266_PLL_46_996M 0x0000C4E9 | ||
718 | #define CLE266_PLL_48_000M 0x00001443 | ||
719 | #define CLE266_PLL_48_875M 0x00001D63 | ||
720 | #define CLE266_PLL_49_500M 0x00008653 | ||
721 | #define CLE266_PLL_52_406M 0x0000C475 | ||
722 | #define CLE266_PLL_52_977M 0x00004525 | ||
723 | #define CLE266_PLL_56_250M 0x000047B7 | ||
724 | #define CLE266_PLL_60_466M 0x0000494C | ||
725 | #define CLE266_PLL_61_500M 0x00001456 | ||
726 | #define CLE266_PLL_65_000M 0x000086ED | ||
727 | #define CLE266_PLL_65_178M 0x0000855B | ||
728 | #define CLE266_PLL_66_750M 0x0000844B /* 67.116MHz */ | ||
729 | #define CLE266_PLL_68_179M 0x00000413 | ||
730 | #define CLE266_PLL_69_924M 0x00001153 | ||
731 | #define CLE266_PLL_70_159M 0x00001462 | ||
732 | #define CLE266_PLL_72_000M 0x00001879 | ||
733 | #define CLE266_PLL_74_270M 0x00004853 | ||
734 | #define CLE266_PLL_78_750M 0x00004321 | ||
735 | #define CLE266_PLL_80_136M 0x0000051C | ||
736 | #define CLE266_PLL_83_375M 0x0000C25D | ||
737 | #define CLE266_PLL_83_950M 0x00000729 | ||
738 | #define CLE266_PLL_84_750M 0x00008576 /* 84.537MHz */ | ||
739 | #define CLE266_PLL_85_860M 0x00004754 | ||
740 | #define CLE266_PLL_88_750M 0x0000051F | ||
741 | #define CLE266_PLL_94_500M 0x00000521 | ||
742 | #define CLE266_PLL_97_750M 0x00004652 | ||
743 | #define CLE266_PLL_101_000M 0x0000497F | ||
744 | #define CLE266_PLL_106_500M 0x00008477 /* 106.491463 MHz */ | ||
745 | #define CLE266_PLL_108_000M 0x00008479 | ||
746 | #define CLE266_PLL_113_309M 0x00000C5F | ||
747 | #define CLE266_PLL_118_840M 0x00004553 | ||
748 | #define CLE266_PLL_119_000M 0x00000D6C | ||
749 | #define CLE266_PLL_121_750M 0x00004555 /* 121.704MHz */ | ||
750 | #define CLE266_PLL_125_104M 0x000006B5 | ||
751 | #define CLE266_PLL_133_308M 0x0000465F | ||
752 | #define CLE266_PLL_135_000M 0x0000455E | ||
753 | #define CLE266_PLL_136_700M 0x00000C73 | ||
754 | #define CLE266_PLL_138_400M 0x00000957 | ||
755 | #define CLE266_PLL_146_760M 0x00004567 | ||
756 | #define CLE266_PLL_148_500M 0x00000853 | ||
757 | #define CLE266_PLL_153_920M 0x00000856 | ||
758 | #define CLE266_PLL_156_000M 0x0000456D | ||
759 | #define CLE266_PLL_157_500M 0x000005B7 | ||
760 | #define CLE266_PLL_162_000M 0x00004571 | ||
761 | #define CLE266_PLL_187_000M 0x00000976 | ||
762 | #define CLE266_PLL_193_295M 0x0000086C | ||
763 | #define CLE266_PLL_202_500M 0x00000763 | ||
764 | #define CLE266_PLL_204_000M 0x00000764 | ||
765 | #define CLE266_PLL_218_500M 0x0000065C | ||
766 | #define CLE266_PLL_234_000M 0x00000662 | ||
767 | #define CLE266_PLL_267_250M 0x00000670 | ||
768 | #define CLE266_PLL_297_500M 0x000005E6 | ||
769 | #define CLE266_PLL_74_481M 0x0000051A | ||
770 | #define CLE266_PLL_172_798M 0x00004579 | ||
771 | #define CLE266_PLL_122_614M 0x0000073C | ||
772 | |||
773 | /* K800 PLL value | ||
774 | */ | ||
775 | #define K800_PLL_25_175M 0x00539001 | ||
776 | #define K800_PLL_26_880M 0x001C8C80 | ||
777 | #define K800_PLL_29_581M 0x00409080 | ||
778 | #define K800_PLL_31_490M 0x006F9001 | ||
779 | #define K800_PLL_31_500M 0x008B9002 | ||
780 | #define K800_PLL_31_728M 0x00AF9003 | ||
781 | #define K800_PLL_32_668M 0x00909002 | ||
782 | #define K800_PLL_36_000M 0x009F9002 | ||
783 | #define K800_PLL_40_000M 0x00578C02 | ||
784 | #define K800_PLL_41_291M 0x00438C01 | ||
785 | #define K800_PLL_43_163M 0x00778C03 | ||
786 | #define K800_PLL_45_250M 0x007D8C83 /* 45.46MHz */ | ||
787 | #define K800_PLL_46_000M 0x00658C02 | ||
788 | #define K800_PLL_46_996M 0x00818C83 | ||
789 | #define K800_PLL_48_000M 0x00848C83 | ||
790 | #define K800_PLL_48_875M 0x00508C81 | ||
791 | #define K800_PLL_49_500M 0x00518C01 | ||
792 | #define K800_PLL_52_406M 0x00738C02 | ||
793 | #define K800_PLL_52_977M 0x00928C83 | ||
794 | #define K800_PLL_56_250M 0x007C8C02 | ||
795 | #define K800_PLL_60_466M 0x00A78C83 | ||
796 | #define K800_PLL_61_500M 0x00AA8C83 | ||
797 | #define K800_PLL_65_000M 0x006B8C01 | ||
798 | #define K800_PLL_65_178M 0x00B48C83 | ||
799 | #define K800_PLL_66_750M 0x00948C82 /* 67.116MHz */ | ||
800 | #define K800_PLL_68_179M 0x00708C01 | ||
801 | #define K800_PLL_69_924M 0x00C18C83 | ||
802 | #define K800_PLL_70_159M 0x00C28C83 | ||
803 | #define K800_PLL_72_000M 0x009F8C82 | ||
804 | #define K800_PLL_74_270M 0x00ce0c03 | ||
805 | #define K800_PLL_78_750M 0x00408801 | ||
806 | #define K800_PLL_80_136M 0x00428801 | ||
807 | #define K800_PLL_83_375M 0x005B0882 | ||
808 | #define K800_PLL_83_950M 0x00738803 | ||
809 | #define K800_PLL_84_750M 0x00748883 /* 84.477MHz */ | ||
810 | #define K800_PLL_85_860M 0x00768883 | ||
811 | #define K800_PLL_88_750M 0x007A8883 | ||
812 | #define K800_PLL_94_500M 0x00828803 | ||
813 | #define K800_PLL_97_750M 0x00878883 | ||
814 | #define K800_PLL_101_000M 0x008B8883 | ||
815 | #define K800_PLL_106_500M 0x00758882 /* 106.491463 MHz */ | ||
816 | #define K800_PLL_108_000M 0x00778882 | ||
817 | #define K800_PLL_113_309M 0x005D8881 | ||
818 | #define K800_PLL_118_840M 0x00A48883 | ||
819 | #define K800_PLL_119_000M 0x00838882 | ||
820 | #define K800_PLL_121_750M 0x00A88883 /* 121.704MHz */ | ||
821 | #define K800_PLL_125_104M 0x00688801 | ||
822 | #define K800_PLL_133_308M 0x005D8801 | ||
823 | #define K800_PLL_135_000M 0x001A4081 | ||
824 | #define K800_PLL_136_700M 0x00BD8883 | ||
825 | #define K800_PLL_138_400M 0x00728881 | ||
826 | #define K800_PLL_146_760M 0x00CC8883 | ||
827 | #define K800_PLL_148_500M 0x00ce0803 | ||
828 | #define K800_PLL_153_920M 0x00548482 | ||
829 | #define K800_PLL_156_000M 0x006B8483 | ||
830 | #define K800_PLL_157_500M 0x00142080 | ||
831 | #define K800_PLL_162_000M 0x006F8483 | ||
832 | #define K800_PLL_187_000M 0x00818483 | ||
833 | #define K800_PLL_193_295M 0x004F8481 | ||
834 | #define K800_PLL_202_500M 0x00538481 | ||
835 | #define K800_PLL_204_000M 0x008D8483 | ||
836 | #define K800_PLL_218_500M 0x00978483 | ||
837 | #define K800_PLL_234_000M 0x00608401 | ||
838 | #define K800_PLL_267_250M 0x006E8481 | ||
839 | #define K800_PLL_297_500M 0x00A48402 | ||
840 | #define K800_PLL_74_481M 0x007B8C81 | ||
841 | #define K800_PLL_172_798M 0x00778483 | ||
842 | #define K800_PLL_122_614M 0x00878882 | ||
843 | |||
844 | /* PLL for VT3324 */ | ||
845 | #define CX700_25_175M 0x008B1003 | ||
846 | #define CX700_26_719M 0x00931003 | ||
847 | #define CX700_26_880M 0x00941003 | ||
848 | #define CX700_29_581M 0x00A49003 | ||
849 | #define CX700_31_490M 0x00AE1003 | ||
850 | #define CX700_31_500M 0x00AE1003 | ||
851 | #define CX700_31_728M 0x00AF1003 | ||
852 | #define CX700_32_668M 0x00B51003 | ||
853 | #define CX700_36_000M 0x00C81003 | ||
854 | #define CX700_40_000M 0x006E0C03 | ||
855 | #define CX700_41_291M 0x00710C03 | ||
856 | #define CX700_43_163M 0x00770C03 | ||
857 | #define CX700_45_250M 0x007D0C03 /* 45.46MHz */ | ||
858 | #define CX700_46_000M 0x007F0C03 | ||
859 | #define CX700_46_996M 0x00818C83 | ||
860 | #define CX700_48_000M 0x00840C03 | ||
861 | #define CX700_48_875M 0x00508C81 | ||
862 | #define CX700_49_500M 0x00880C03 | ||
863 | #define CX700_52_406M 0x00730C02 | ||
864 | #define CX700_52_977M 0x00920C03 | ||
865 | #define CX700_56_250M 0x009B0C03 | ||
866 | #define CX700_60_466M 0x00460C00 | ||
867 | #define CX700_61_500M 0x00AA0C03 | ||
868 | #define CX700_65_000M 0x006B0C01 | ||
869 | #define CX700_65_178M 0x006B0C01 | ||
870 | #define CX700_66_750M 0x00940C02 /*67.116MHz */ | ||
871 | #define CX700_68_179M 0x00BC0C03 | ||
872 | #define CX700_69_924M 0x00C10C03 | ||
873 | #define CX700_70_159M 0x00C20C03 | ||
874 | #define CX700_72_000M 0x009F0C02 | ||
875 | #define CX700_74_270M 0x00CE0C03 | ||
876 | #define CX700_74_481M 0x00CE0C03 | ||
877 | #define CX700_78_750M 0x006C0803 | ||
878 | #define CX700_80_136M 0x006E0803 | ||
879 | #define CX700_83_375M 0x005B0882 | ||
880 | #define CX700_83_950M 0x00730803 | ||
881 | #define CX700_84_750M 0x00740803 /* 84.537Mhz */ | ||
882 | #define CX700_85_860M 0x00760803 | ||
883 | #define CX700_88_750M 0x00AC8885 | ||
884 | #define CX700_94_500M 0x00820803 | ||
885 | #define CX700_97_750M 0x00870803 | ||
886 | #define CX700_101_000M 0x008B0803 | ||
887 | #define CX700_106_500M 0x00750802 | ||
888 | #define CX700_108_000M 0x00950803 | ||
889 | #define CX700_113_309M 0x005D0801 | ||
890 | #define CX700_118_840M 0x00A40803 | ||
891 | #define CX700_119_000M 0x00830802 | ||
892 | #define CX700_121_750M 0x00420800 /* 121.704MHz */ | ||
893 | #define CX700_125_104M 0x00AD0803 | ||
894 | #define CX700_133_308M 0x00930802 | ||
895 | #define CX700_135_000M 0x00950802 | ||
896 | #define CX700_136_700M 0x00BD0803 | ||
897 | #define CX700_138_400M 0x00720801 | ||
898 | #define CX700_146_760M 0x00CC0803 | ||
899 | #define CX700_148_500M 0x00a40802 | ||
900 | #define CX700_153_920M 0x00540402 | ||
901 | #define CX700_156_000M 0x006B0403 | ||
902 | #define CX700_157_500M 0x006C0403 | ||
903 | #define CX700_162_000M 0x006F0403 | ||
904 | #define CX700_172_798M 0x00770403 | ||
905 | #define CX700_187_000M 0x00810403 | ||
906 | #define CX700_193_295M 0x00850403 | ||
907 | #define CX700_202_500M 0x008C0403 | ||
908 | #define CX700_204_000M 0x008D0403 | ||
909 | #define CX700_218_500M 0x00970403 | ||
910 | #define CX700_234_000M 0x00600401 | ||
911 | #define CX700_267_250M 0x00B90403 | ||
912 | #define CX700_297_500M 0x00CE0403 | ||
913 | #define CX700_122_614M 0x00870802 | ||
914 | |||
915 | /* PLL for VX855 */ | ||
916 | #define VX855_22_000M 0x007B1005 | ||
917 | #define VX855_25_175M 0x008D1005 | ||
918 | #define VX855_26_719M 0x00961005 | ||
919 | #define VX855_26_880M 0x00961005 | ||
920 | #define VX855_27_000M 0x00971005 | ||
921 | #define VX855_29_581M 0x00A51005 | ||
922 | #define VX855_29_829M 0x00641003 | ||
923 | #define VX855_31_490M 0x00B01005 | ||
924 | #define VX855_31_500M 0x00B01005 | ||
925 | #define VX855_31_728M 0x008E1004 | ||
926 | #define VX855_32_668M 0x00921004 | ||
927 | #define VX855_36_000M 0x00A11004 | ||
928 | #define VX855_40_000M 0x00700C05 | ||
929 | #define VX855_41_291M 0x00730C05 | ||
930 | #define VX855_43_163M 0x00790C05 | ||
931 | #define VX855_45_250M 0x007F0C05 /* 45.46MHz */ | ||
932 | #define VX855_46_000M 0x00670C04 | ||
933 | #define VX855_46_996M 0x00690C04 | ||
934 | #define VX855_48_000M 0x00860C05 | ||
935 | #define VX855_48_875M 0x00890C05 | ||
936 | #define VX855_49_500M 0x00530C03 | ||
937 | #define VX855_52_406M 0x00580C03 | ||
938 | #define VX855_52_977M 0x00940C05 | ||
939 | #define VX855_56_250M 0x009D0C05 | ||
940 | #define VX855_57_275M 0x009D8C85 /* Used by XO panel */ | ||
941 | #define VX855_60_466M 0x00A90C05 | ||
942 | #define VX855_61_500M 0x00AC0C05 | ||
943 | #define VX855_65_000M 0x006D0C03 | ||
944 | #define VX855_65_178M 0x00B60C05 | ||
945 | #define VX855_66_750M 0x00700C03 /*67.116MHz */ | ||
946 | #define VX855_67_295M 0x00BC0C05 | ||
947 | #define VX855_68_179M 0x00BF0C05 | ||
948 | #define VX855_68_369M 0x00BF0C05 | ||
949 | #define VX855_69_924M 0x00C30C05 | ||
950 | #define VX855_70_159M 0x00C30C05 | ||
951 | #define VX855_72_000M 0x00A10C04 | ||
952 | #define VX855_73_023M 0x00CC0C05 | ||
953 | #define VX855_74_481M 0x00D10C05 | ||
954 | #define VX855_78_750M 0x006E0805 | ||
955 | #define VX855_79_466M 0x006F0805 | ||
956 | #define VX855_80_136M 0x00700805 | ||
957 | #define VX855_81_627M 0x00720805 | ||
958 | #define VX855_83_375M 0x00750805 | ||
959 | #define VX855_83_527M 0x00750805 | ||
960 | #define VX855_83_950M 0x00750805 | ||
961 | #define VX855_84_537M 0x00760805 | ||
962 | #define VX855_84_750M 0x00760805 /* 84.537Mhz */ | ||
963 | #define VX855_85_500M 0x00760805 /* 85.909080 MHz*/ | ||
964 | #define VX855_85_860M 0x00760805 | ||
965 | #define VX855_85_909M 0x00760805 | ||
966 | #define VX855_88_750M 0x007C0805 | ||
967 | #define VX855_89_489M 0x007D0805 | ||
968 | #define VX855_94_500M 0x00840805 | ||
969 | #define VX855_96_648M 0x00870805 | ||
970 | #define VX855_97_750M 0x00890805 | ||
971 | #define VX855_101_000M 0x008D0805 | ||
972 | #define VX855_106_500M 0x00950805 | ||
973 | #define VX855_108_000M 0x00970805 | ||
974 | #define VX855_110_125M 0x00990805 | ||
975 | #define VX855_112_000M 0x009D0805 | ||
976 | #define VX855_113_309M 0x009F0805 | ||
977 | #define VX855_115_000M 0x00A10805 | ||
978 | #define VX855_118_840M 0x00A60805 | ||
979 | #define VX855_119_000M 0x00A70805 | ||
980 | #define VX855_121_750M 0x00AA0805 /* 121.704MHz */ | ||
981 | #define VX855_122_614M 0x00AC0805 | ||
982 | #define VX855_126_266M 0x00B10805 | ||
983 | #define VX855_130_250M 0x00B60805 /* 130.250 */ | ||
984 | #define VX855_135_000M 0x00BD0805 | ||
985 | #define VX855_136_700M 0x00BF0805 | ||
986 | #define VX855_137_750M 0x00C10805 | ||
987 | #define VX855_138_400M 0x00C20805 | ||
988 | #define VX855_144_300M 0x00CA0805 | ||
989 | #define VX855_146_760M 0x00CE0805 | ||
990 | #define VX855_148_500M 0x00D00805 | ||
991 | #define VX855_153_920M 0x00540402 | ||
992 | #define VX855_156_000M 0x006C0405 | ||
993 | #define VX855_156_867M 0x006E0405 | ||
994 | #define VX855_157_500M 0x006E0405 | ||
995 | #define VX855_162_000M 0x00710405 | ||
996 | #define VX855_172_798M 0x00790405 | ||
997 | #define VX855_187_000M 0x00830405 | ||
998 | #define VX855_193_295M 0x00870405 | ||
999 | #define VX855_202_500M 0x008E0405 | ||
1000 | #define VX855_204_000M 0x008F0405 | ||
1001 | #define VX855_218_500M 0x00990405 | ||
1002 | #define VX855_229_500M 0x00A10405 | ||
1003 | #define VX855_234_000M 0x00A40405 | ||
1004 | #define VX855_267_250M 0x00BB0405 | ||
1005 | #define VX855_297_500M 0x00D00405 | ||
1006 | #define VX855_339_500M 0x00770005 | ||
1007 | #define VX855_340_772M 0x00770005 | ||
1008 | |||
1009 | 700 | ||
1010 | /* Definition CRTC Timing Index */ | 701 | /* Definition CRTC Timing Index */ |
1011 | #define H_TOTAL_INDEX 0 | 702 | #define H_TOTAL_INDEX 0 |
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index e8cfe8392110..66f403033111 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c | |||
@@ -64,7 +64,7 @@ static inline int viafb_mmio_read(int reg) | |||
64 | */ | 64 | */ |
65 | static u32 viafb_enabled_ints; | 65 | static u32 viafb_enabled_ints; |
66 | 66 | ||
67 | static void viafb_int_init(void) | 67 | static void __devinit viafb_int_init(void) |
68 | { | 68 | { |
69 | viafb_enabled_ints = 0; | 69 | viafb_enabled_ints = 0; |
70 | 70 | ||
@@ -489,7 +489,7 @@ out_unmap: | |||
489 | return ret; | 489 | return ret; |
490 | } | 490 | } |
491 | 491 | ||
492 | static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) | 492 | static void via_pci_teardown_mmio(struct viafb_dev *vdev) |
493 | { | 493 | { |
494 | iounmap(vdev->fbmem); | 494 | iounmap(vdev->fbmem); |
495 | iounmap(vdev->engine_mmio); | 495 | iounmap(vdev->engine_mmio); |
@@ -548,7 +548,7 @@ static int __devinit via_setup_subdevs(struct viafb_dev *vdev) | |||
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
551 | static void __devexit via_teardown_subdevs(void) | 551 | static void via_teardown_subdevs(void) |
552 | { | 552 | { |
553 | int i; | 553 | int i; |
554 | 554 | ||
@@ -613,22 +613,24 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) | |||
613 | static struct pci_device_id via_pci_table[] __devinitdata = { | 613 | static struct pci_device_id via_pci_table[] __devinitdata = { |
614 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), | 614 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), |
615 | .driver_data = UNICHROME_CLE266 }, | 615 | .driver_data = UNICHROME_CLE266 }, |
616 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), | ||
617 | .driver_data = UNICHROME_PM800 }, | ||
618 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), | 616 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), |
619 | .driver_data = UNICHROME_K400 }, | 617 | .driver_data = UNICHROME_K400 }, |
620 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), | 618 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), |
621 | .driver_data = UNICHROME_K800 }, | 619 | .driver_data = UNICHROME_K800 }, |
622 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), | 620 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), |
621 | .driver_data = UNICHROME_PM800 }, | ||
622 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID), | ||
623 | .driver_data = UNICHROME_CN700 }, | 623 | .driver_data = UNICHROME_CN700 }, |
624 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), | ||
625 | .driver_data = UNICHROME_K8M890 }, | ||
626 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), | 624 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), |
627 | .driver_data = UNICHROME_CX700 }, | 625 | .driver_data = UNICHROME_CX700 }, |
628 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), | ||
629 | .driver_data = UNICHROME_P4M900 }, | ||
630 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), | 626 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), |
631 | .driver_data = UNICHROME_CN750 }, | 627 | .driver_data = UNICHROME_CN750 }, |
628 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), | ||
629 | .driver_data = UNICHROME_K8M890 }, | ||
630 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), | ||
631 | .driver_data = UNICHROME_P4M890 }, | ||
632 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), | ||
633 | .driver_data = UNICHROME_P4M900 }, | ||
632 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), | 634 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), |
633 | .driver_data = UNICHROME_VX800 }, | 635 | .driver_data = UNICHROME_VX800 }, |
634 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), | 636 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), |
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index 595516aea691..39acb37e7a1d 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c | |||
@@ -73,7 +73,7 @@ struct viafb_gpio_cfg { | |||
73 | struct gpio_chip gpio_chip; | 73 | struct gpio_chip gpio_chip; |
74 | struct viafb_dev *vdev; | 74 | struct viafb_dev *vdev; |
75 | struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS]; | 75 | struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS]; |
76 | char *gpio_names[VIAFB_NUM_GPIOS]; | 76 | const char *gpio_names[VIAFB_NUM_GPIOS]; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* | 79 | /* |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 1082541358f0..bdd0e4130f4e 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -49,11 +49,6 @@ char *viafb_active_dev; | |||
49 | char *viafb_lcd_port = ""; | 49 | char *viafb_lcd_port = ""; |
50 | char *viafb_dvi_port = ""; | 50 | char *viafb_dvi_port = ""; |
51 | 51 | ||
52 | static void viafb_set_device(struct device_t active_dev); | ||
53 | static int apply_device_setting(struct viafb_ioctl_setting setting_info, | ||
54 | struct fb_info *info); | ||
55 | static void apply_second_mode_setting(struct fb_var_screeninfo | ||
56 | *sec_var); | ||
57 | static void retrieve_device_setting(struct viafb_ioctl_setting | 52 | static void retrieve_device_setting(struct viafb_ioctl_setting |
58 | *setting_info); | 53 | *setting_info); |
59 | static int viafb_pan_display(struct fb_var_screeninfo *var, | 54 | static int viafb_pan_display(struct fb_var_screeninfo *var, |
@@ -221,9 +216,9 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
221 | 216 | ||
222 | /* Adjust var according to our driver's own table */ | 217 | /* Adjust var according to our driver's own table */ |
223 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); | 218 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); |
224 | if (info->var.accel_flags & FB_ACCELF_TEXT && | 219 | if (var->accel_flags & FB_ACCELF_TEXT && |
225 | !ppar->shared->vdev->engine_mmio) | 220 | !ppar->shared->vdev->engine_mmio) |
226 | info->var.accel_flags = 0; | 221 | var->accel_flags = 0; |
227 | 222 | ||
228 | return 0; | 223 | return 0; |
229 | } | 224 | } |
@@ -234,6 +229,7 @@ static int viafb_set_par(struct fb_info *info) | |||
234 | struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; | 229 | struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; |
235 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); | 230 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); |
236 | 231 | ||
232 | viafb_update_fix(info); | ||
237 | viapar->depth = fb_get_color_depth(&info->var, &info->fix); | 233 | viapar->depth = fb_get_color_depth(&info->var, &info->fix); |
238 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, | 234 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, |
239 | viafbinfo->var.bits_per_pixel, viafb_refresh, 0); | 235 | viafbinfo->var.bits_per_pixel, viafb_refresh, 0); |
@@ -257,7 +253,6 @@ static int viafb_set_par(struct fb_info *info) | |||
257 | } | 253 | } |
258 | 254 | ||
259 | if (vmode_entry) { | 255 | if (vmode_entry) { |
260 | viafb_update_fix(info); | ||
261 | if (viafb_dual_fb && viapar->iga_path == IGA2) | 256 | if (viafb_dual_fb && viapar->iga_path == IGA2) |
262 | viafb_bpp1 = info->var.bits_per_pixel; | 257 | viafb_bpp1 = info->var.bits_per_pixel; |
263 | else | 258 | else |
@@ -478,13 +473,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
478 | if (gpu32 & LCD_Device) | 473 | if (gpu32 & LCD_Device) |
479 | viafb_lcd_disable(); | 474 | viafb_lcd_disable(); |
480 | break; | 475 | break; |
481 | case VIAFB_SET_DEVICE: | ||
482 | if (copy_from_user(&u.active_dev, (void *)argp, | ||
483 | sizeof(u.active_dev))) | ||
484 | return -EFAULT; | ||
485 | viafb_set_device(u.active_dev); | ||
486 | viafb_set_par(info); | ||
487 | break; | ||
488 | case VIAFB_GET_DEVICE: | 476 | case VIAFB_GET_DEVICE: |
489 | u.active_dev.crt = viafb_CRT_ON; | 477 | u.active_dev.crt = viafb_CRT_ON; |
490 | u.active_dev.dvi = viafb_DVI_ON; | 478 | u.active_dev.dvi = viafb_DVI_ON; |
@@ -527,21 +515,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
527 | 515 | ||
528 | break; | 516 | break; |
529 | 517 | ||
530 | case VIAFB_SET_DEVICE_INFO: | ||
531 | if (copy_from_user(&u.viafb_setting, | ||
532 | argp, sizeof(u.viafb_setting))) | ||
533 | return -EFAULT; | ||
534 | if (apply_device_setting(u.viafb_setting, info) < 0) | ||
535 | return -EINVAL; | ||
536 | |||
537 | break; | ||
538 | |||
539 | case VIAFB_SET_SECOND_MODE: | ||
540 | if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var))) | ||
541 | return -EFAULT; | ||
542 | apply_second_mode_setting(&u.sec_var); | ||
543 | break; | ||
544 | |||
545 | case VIAFB_GET_DEVICE_INFO: | 518 | case VIAFB_GET_DEVICE_INFO: |
546 | 519 | ||
547 | retrieve_device_setting(&u.viafb_setting); | 520 | retrieve_device_setting(&u.viafb_setting); |
@@ -913,112 +886,6 @@ static int viafb_sync(struct fb_info *info) | |||
913 | return 0; | 886 | return 0; |
914 | } | 887 | } |
915 | 888 | ||
916 | static void check_available_device_to_enable(int device_id) | ||
917 | { | ||
918 | int device_num = 0; | ||
919 | |||
920 | /* Initialize: */ | ||
921 | viafb_CRT_ON = STATE_OFF; | ||
922 | viafb_DVI_ON = STATE_OFF; | ||
923 | viafb_LCD_ON = STATE_OFF; | ||
924 | viafb_LCD2_ON = STATE_OFF; | ||
925 | viafb_DeviceStatus = None_Device; | ||
926 | |||
927 | if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
928 | viafb_CRT_ON = STATE_ON; | ||
929 | device_num++; | ||
930 | viafb_DeviceStatus |= CRT_Device; | ||
931 | } | ||
932 | |||
933 | if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
934 | viafb_DVI_ON = STATE_ON; | ||
935 | device_num++; | ||
936 | viafb_DeviceStatus |= DVI_Device; | ||
937 | } | ||
938 | |||
939 | if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
940 | viafb_LCD_ON = STATE_ON; | ||
941 | device_num++; | ||
942 | viafb_DeviceStatus |= LCD_Device; | ||
943 | } | ||
944 | |||
945 | if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) { | ||
946 | viafb_LCD2_ON = STATE_ON; | ||
947 | device_num++; | ||
948 | viafb_DeviceStatus |= LCD2_Device; | ||
949 | } | ||
950 | |||
951 | if (viafb_DeviceStatus == None_Device) { | ||
952 | /* Use CRT as default active device: */ | ||
953 | viafb_CRT_ON = STATE_ON; | ||
954 | viafb_DeviceStatus = CRT_Device; | ||
955 | } | ||
956 | DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus); | ||
957 | } | ||
958 | |||
959 | static void viafb_set_device(struct device_t active_dev) | ||
960 | { | ||
961 | /* Check available device to enable: */ | ||
962 | int device_id = None_Device; | ||
963 | if (active_dev.crt) | ||
964 | device_id |= CRT_Device; | ||
965 | if (active_dev.dvi) | ||
966 | device_id |= DVI_Device; | ||
967 | if (active_dev.lcd) | ||
968 | device_id |= LCD_Device; | ||
969 | |||
970 | check_available_device_to_enable(device_id); | ||
971 | |||
972 | /* Check property of LCD: */ | ||
973 | if (viafb_LCD_ON) { | ||
974 | if (active_dev.lcd_dsp_cent) { | ||
975 | viaparinfo->lvds_setting_info->display_method = | ||
976 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
977 | } else { | ||
978 | viaparinfo->lvds_setting_info->display_method = | ||
979 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
980 | } | ||
981 | |||
982 | if (active_dev.lcd_mode == LCD_SPWG) { | ||
983 | viaparinfo->lvds_setting_info->lcd_mode = | ||
984 | viafb_lcd_mode = LCD_SPWG; | ||
985 | } else { | ||
986 | viaparinfo->lvds_setting_info->lcd_mode = | ||
987 | viafb_lcd_mode = LCD_OPENLDI; | ||
988 | } | ||
989 | |||
990 | if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) { | ||
991 | viafb_lcd_panel_id = active_dev.lcd_panel_id; | ||
992 | viafb_init_lcd_size(); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | /* Check property of mode: */ | ||
997 | if (!active_dev.xres1) | ||
998 | viafb_second_xres = 640; | ||
999 | else | ||
1000 | viafb_second_xres = active_dev.xres1; | ||
1001 | if (!active_dev.yres1) | ||
1002 | viafb_second_yres = 480; | ||
1003 | else | ||
1004 | viafb_second_yres = active_dev.yres1; | ||
1005 | if (active_dev.bpp != 0) | ||
1006 | viafb_bpp = active_dev.bpp; | ||
1007 | if (active_dev.bpp1 != 0) | ||
1008 | viafb_bpp1 = active_dev.bpp1; | ||
1009 | if (active_dev.refresh != 0) | ||
1010 | viafb_refresh = active_dev.refresh; | ||
1011 | if (active_dev.refresh1 != 0) | ||
1012 | viafb_refresh1 = active_dev.refresh1; | ||
1013 | if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON)) | ||
1014 | viafb_SAMM_ON = active_dev.samm; | ||
1015 | viafb_primary_dev = active_dev.primary_dev; | ||
1016 | |||
1017 | via_set_primary_address(0); | ||
1018 | via_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); | ||
1019 | viafb_set_iga_path(); | ||
1020 | } | ||
1021 | |||
1022 | static int get_primary_device(void) | 889 | static int get_primary_device(void) |
1023 | { | 890 | { |
1024 | int primary_device = 0; | 891 | int primary_device = 0; |
@@ -1060,124 +927,6 @@ static int get_primary_device(void) | |||
1060 | return primary_device; | 927 | return primary_device; |
1061 | } | 928 | } |
1062 | 929 | ||
1063 | static void apply_second_mode_setting(struct fb_var_screeninfo | ||
1064 | *sec_var) | ||
1065 | { | ||
1066 | u32 htotal, vtotal, long_refresh; | ||
1067 | |||
1068 | htotal = sec_var->xres + sec_var->left_margin + | ||
1069 | sec_var->right_margin + sec_var->hsync_len; | ||
1070 | vtotal = sec_var->yres + sec_var->upper_margin + | ||
1071 | sec_var->lower_margin + sec_var->vsync_len; | ||
1072 | if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) { | ||
1073 | /*Is 32 bytes alignment? */ | ||
1074 | /*32 pixel alignment */ | ||
1075 | sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31; | ||
1076 | } | ||
1077 | |||
1078 | htotal = sec_var->xres + sec_var->left_margin + | ||
1079 | sec_var->right_margin + sec_var->hsync_len; | ||
1080 | vtotal = sec_var->yres + sec_var->upper_margin + | ||
1081 | sec_var->lower_margin + sec_var->vsync_len; | ||
1082 | long_refresh = 1000000000UL / sec_var->pixclock * 1000; | ||
1083 | long_refresh /= (htotal * vtotal); | ||
1084 | |||
1085 | viafb_second_xres = sec_var->xres; | ||
1086 | viafb_second_yres = sec_var->yres; | ||
1087 | viafb_second_virtual_xres = sec_var->xres_virtual; | ||
1088 | viafb_second_virtual_yres = sec_var->yres_virtual; | ||
1089 | viafb_bpp1 = sec_var->bits_per_pixel; | ||
1090 | viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres, | ||
1091 | long_refresh); | ||
1092 | } | ||
1093 | |||
1094 | static int apply_device_setting(struct viafb_ioctl_setting setting_info, | ||
1095 | struct fb_info *info) | ||
1096 | { | ||
1097 | int need_set_mode = 0; | ||
1098 | DEBUG_MSG(KERN_INFO "apply_device_setting\n"); | ||
1099 | |||
1100 | if (setting_info.device_flag) { | ||
1101 | need_set_mode = 1; | ||
1102 | check_available_device_to_enable(setting_info.device_status); | ||
1103 | } | ||
1104 | |||
1105 | /* Unlock LCD's operation according to LCD flag | ||
1106 | and check if the setting value is valid. */ | ||
1107 | /* If the value is valid, apply the new setting value to the device. */ | ||
1108 | if (viafb_LCD_ON) { | ||
1109 | if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) { | ||
1110 | need_set_mode = 1; | ||
1111 | if (setting_info.lcd_attributes.display_center) { | ||
1112 | /* Centering */ | ||
1113 | viaparinfo->lvds_setting_info->display_method = | ||
1114 | LCD_CENTERING; | ||
1115 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
1116 | viaparinfo->lvds_setting_info2->display_method = | ||
1117 | viafb_lcd_dsp_method = LCD_CENTERING; | ||
1118 | } else { | ||
1119 | /* expandsion */ | ||
1120 | viaparinfo->lvds_setting_info->display_method = | ||
1121 | LCD_EXPANDSION; | ||
1122 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
1123 | viaparinfo->lvds_setting_info2->display_method = | ||
1124 | LCD_EXPANDSION; | ||
1125 | viafb_lcd_dsp_method = LCD_EXPANDSION; | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | if (setting_info.lcd_operation_flag & OP_LCD_MODE) { | ||
1130 | need_set_mode = 1; | ||
1131 | if (setting_info.lcd_attributes.lcd_mode == | ||
1132 | LCD_SPWG) { | ||
1133 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1134 | viafb_lcd_mode = LCD_SPWG; | ||
1135 | } else { | ||
1136 | viaparinfo->lvds_setting_info->lcd_mode = | ||
1137 | viafb_lcd_mode = LCD_OPENLDI; | ||
1138 | } | ||
1139 | viaparinfo->lvds_setting_info2->lcd_mode = | ||
1140 | viaparinfo->lvds_setting_info->lcd_mode; | ||
1141 | } | ||
1142 | |||
1143 | if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) { | ||
1144 | need_set_mode = 1; | ||
1145 | if (setting_info.lcd_attributes.panel_id <= | ||
1146 | LCD_PANEL_ID_MAXIMUM) { | ||
1147 | viafb_lcd_panel_id = | ||
1148 | setting_info.lcd_attributes.panel_id; | ||
1149 | viafb_init_lcd_size(); | ||
1150 | } | ||
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | if (0 != (setting_info.samm_status & OP_SAMM)) { | ||
1155 | setting_info.samm_status = | ||
1156 | setting_info.samm_status & (~OP_SAMM); | ||
1157 | if (setting_info.samm_status == 0 | ||
1158 | || setting_info.samm_status == 1) { | ||
1159 | viafb_SAMM_ON = setting_info.samm_status; | ||
1160 | |||
1161 | if (viafb_SAMM_ON) | ||
1162 | viafb_primary_dev = setting_info.primary_device; | ||
1163 | |||
1164 | via_set_primary_address(0); | ||
1165 | via_set_secondary_address(viafb_SAMM_ON ? | ||
1166 | viafb_second_offset : 0); | ||
1167 | viafb_set_iga_path(); | ||
1168 | } | ||
1169 | need_set_mode = 1; | ||
1170 | } | ||
1171 | |||
1172 | if (!need_set_mode) { | ||
1173 | ; | ||
1174 | } else { | ||
1175 | viafb_set_iga_path(); | ||
1176 | viafb_set_par(info); | ||
1177 | } | ||
1178 | return true; | ||
1179 | } | ||
1180 | |||
1181 | static void retrieve_device_setting(struct viafb_ioctl_setting | 930 | static void retrieve_device_setting(struct viafb_ioctl_setting |
1182 | *setting_info) | 931 | *setting_info) |
1183 | { | 932 | { |
@@ -1776,10 +1525,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1776 | parse_lcd_port(); | 1525 | parse_lcd_port(); |
1777 | parse_dvi_port(); | 1526 | parse_dvi_port(); |
1778 | 1527 | ||
1779 | /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */ | ||
1780 | if (!viafb_SAMM_ON) | ||
1781 | viafb_dual_fb = 0; | ||
1782 | |||
1783 | viafb_init_chip_info(vdev->chip_type); | 1528 | viafb_init_chip_info(vdev->chip_type); |
1784 | /* | 1529 | /* |
1785 | * The framebuffer will have been successfully mapped by | 1530 | * The framebuffer will have been successfully mapped by |
@@ -1823,30 +1568,13 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
1823 | parse_mode(viafb_mode1, &viafb_second_xres, | 1568 | parse_mode(viafb_mode1, &viafb_second_xres, |
1824 | &viafb_second_yres); | 1569 | &viafb_second_yres); |
1825 | 1570 | ||
1826 | if (0 == viafb_second_virtual_xres) { | 1571 | viafb_second_virtual_xres = viafb_second_xres; |
1827 | switch (viafb_second_xres) { | 1572 | viafb_second_virtual_yres = viafb_second_yres; |
1828 | case 1400: | ||
1829 | viafb_second_virtual_xres = 1408; | ||
1830 | break; | ||
1831 | default: | ||
1832 | viafb_second_virtual_xres = viafb_second_xres; | ||
1833 | break; | ||
1834 | } | ||
1835 | } | ||
1836 | if (0 == viafb_second_virtual_yres) | ||
1837 | viafb_second_virtual_yres = viafb_second_yres; | ||
1838 | } | 1573 | } |
1839 | 1574 | ||
1840 | default_var.xres = default_xres; | 1575 | default_var.xres = default_xres; |
1841 | default_var.yres = default_yres; | 1576 | default_var.yres = default_yres; |
1842 | switch (default_xres) { | 1577 | default_var.xres_virtual = default_xres; |
1843 | case 1400: | ||
1844 | default_var.xres_virtual = 1408; | ||
1845 | break; | ||
1846 | default: | ||
1847 | default_var.xres_virtual = default_xres; | ||
1848 | break; | ||
1849 | } | ||
1850 | default_var.yres_virtual = default_yres; | 1578 | default_var.yres_virtual = default_yres; |
1851 | default_var.bits_per_pixel = viafb_bpp; | 1579 | default_var.bits_per_pixel = viafb_bpp; |
1852 | default_var.pixclock = | 1580 | default_var.pixclock = |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index e66b8b19ce5d..d8b12c32e3ef 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -858,9 +858,9 @@ unsigned long w100fb_gpio_read(int port) | |||
858 | void w100fb_gpio_write(int port, unsigned long value) | 858 | void w100fb_gpio_write(int port, unsigned long value) |
859 | { | 859 | { |
860 | if (port==W100_GPIO_PORT_A) | 860 | if (port==W100_GPIO_PORT_A) |
861 | value = writel(value, remapped_regs + mmGPIO_DATA); | 861 | writel(value, remapped_regs + mmGPIO_DATA); |
862 | else | 862 | else |
863 | value = writel(value, remapped_regs + mmGPIO_DATA2); | 863 | writel(value, remapped_regs + mmGPIO_DATA2); |
864 | } | 864 | } |
865 | EXPORT_SYMBOL(w100fb_gpio_read); | 865 | EXPORT_SYMBOL(w100fb_gpio_read); |
866 | EXPORT_SYMBOL(w100fb_gpio_write); | 866 | EXPORT_SYMBOL(w100fb_gpio_write); |
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index fa97d3e7c21a..7c7f42a12796 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c | |||
@@ -684,7 +684,7 @@ static struct xenbus_driver xenfb_driver = { | |||
684 | 684 | ||
685 | static int __init xenfb_init(void) | 685 | static int __init xenfb_init(void) |
686 | { | 686 | { |
687 | if (!xen_domain()) | 687 | if (!xen_pv_domain()) |
688 | return -ENODEV; | 688 | return -ENODEV; |
689 | 689 | ||
690 | /* Nothing to do if running in dom0. */ | 690 | /* Nothing to do if running in dom0. */ |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 574dc54e12d4..29b5daacc217 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -485,6 +485,8 @@ static int __devexit xilinxfb_of_remove(struct of_device *op) | |||
485 | /* Match table for of_platform binding */ | 485 | /* Match table for of_platform binding */ |
486 | static struct of_device_id xilinxfb_of_match[] __devinitdata = { | 486 | static struct of_device_id xilinxfb_of_match[] __devinitdata = { |
487 | { .compatible = "xlnx,xps-tft-1.00.a", }, | 487 | { .compatible = "xlnx,xps-tft-1.00.a", }, |
488 | { .compatible = "xlnx,xps-tft-2.00.a", }, | ||
489 | { .compatible = "xlnx,xps-tft-2.01.a", }, | ||
488 | { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, | 490 | { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, |
489 | { .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", }, | 491 | { .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", }, |
490 | {}, | 492 | {}, |