Pull fbdev updates from Bartlomiej Zolnierkiewicz: - remove fbdev notifier usage for fbcon (as prep work to clean up the fbcon locking), add locking checks in vt/console code and make assorted cleanups in fbdev and backlight code (Daniel Vetter) - add COMPILE_TEST support to atmel_lcdfb, da8xx-fb, gbefb, imxfb, pvr2fb and pxa168fb drivers (me) - fix DMA API abuse in au1200fb and jz4740_fb drivers (Christoph Hellwig) - add check for new BGRT status field rotation bits in efifb driver (Hans de Goede) - mark expected switch fall-throughs in s3c-fb driver (Gustavo A. R. Silva) - remove fbdev mxsfb driver in favour of the drm version (Fabio Estevam) - remove broken rfbi code from omap2fb driver (me) - misc fixes (Arnd Bergmann, Shobhit Kukreti, Wei Yongjun, me) - misc cleanups (Gustavo A. R. Silva, Colin Ian King, me) * tag 'fbdev-v5.3' of git://github.com/bzolnier/linux: (62 commits) video: fbdev: imxfb: fix a typo in imxfb_probe() video: fbdev: s3c-fb: Mark expected switch fall-throughs video: fbdev: s3c-fb: fix sparse warnings about using incorrect types video: fbdev: don't print error message on framebuffer_alloc() failure video: fbdev: intelfb: return -ENOMEM on framebuffer_alloc() failure video: fbdev: s3c-fb: return -ENOMEM on framebuffer_alloc() failure vga_switcheroo: Depend upon fbcon being built-in, if enabled video: fbdev: omap2: remove rfbi video: fbdev: atmel_lcdfb: remove redundant initialization to variable ret video: fbdev-MMP: Use struct_size() in devm_kzalloc() video: fbdev: controlfb: fix warnings about comparing pointer to 0 efifb: BGRT: Add check for new BGRT status field rotation bits jz4740_fb: fix DMA API abuse video: fbdev: pvr2fb: fix link error for pvr2fb_pci_exit video: fbdev: s3c-fb: add COMPILE_TEST support video: fbdev: imxfb: fix sparse warnings about using incorrect types video: fbdev: pvr2fb: fix build warning when compiling as module fbcon: Export fbcon_update_vcs backlight: simplify lcd notifier staging/olpc_dcon: Add drm conversion to TODO ...
Unified · Split
| @@ -347,8 +347,17 @@ int __init am200_init(void) · 346 unmodified lines | |||
| 347 | { | 347 | { |
| 348 | int ret; | 348 | int ret; |
| 349 | 349 | ||
| 350 | /* before anything else, we request notification for any fb | 350 | /* |
| 351 | * creation events */ | 351 | * Before anything else, we request notification for any fb |
| 352 | * creation events. | ||
| 353 | * | ||
| 354 | * FIXME: This is terrible and needs to be nuked. The notifier is used | ||
| 355 | * to get at the fb base address from the boot splash fb driver, which | ||
| 356 | * is then passed to metronomefb. Instaed of metronomfb or this board | ||
| 357 | * support file here figuring this out on their own. | ||
| 358 | * | ||
| 359 | * See also the #ifdef in fbmem.c. | ||
| 360 | */ | ||
| 352 | fb_register_client(&am200_fb_notif); | 361 | fb_register_client(&am200_fb_notif); |
| 353 | 362 | ||
| 354 | pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config)); | 363 | pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config)); |
| @@ -23,6 +23,7 @@ config VGA_SWITCHEROO · 22 unmodified lines | |||
| 23 | depends on X86 | 23 | depends on X86 |
| 24 | depends on ACPI | 24 | depends on ACPI |
| 25 | depends on PCI | 25 | depends on PCI |
| 26 | depends on (FRAMEBUFFER_CONSOLE=n || FB=y) | ||
| 26 | select VGA_ARB | 27 | select VGA_ARB |
| 27 | help | 28 | help |
| 28 | Many laptops released in 2008/9/10 have two GPUs with a multiplexer | 29 | Many laptops released in 2008/9/10 have two GPUs with a multiplexer |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | |||
| 35 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
| 36 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
| 37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
| 38 | #include <linux/fbcon.h> | ||
| 38 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 39 | #include <linux/pci.h> | 40 | #include <linux/pci.h> |
| 40 | #include <linux/pm_domain.h> | 41 | #include <linux/pm_domain.h> |
| @@ -736,14 +737,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) · 695 unmodified lines | |||
| 736 | if (!active->driver_power_control) | 737 | if (!active->driver_power_control) |
| 737 | set_audio_state(active->id, VGA_SWITCHEROO_OFF); | 738 | set_audio_state(active->id, VGA_SWITCHEROO_OFF); |
| 738 | 739 | ||
| 739 | if (new_client->fb_info) { | 740 | if (new_client->fb_info) |
| 740 | struct fb_event event; | 741 | fbcon_remap_all(new_client->fb_info); |
| 741 | |||
| 742 | console_lock(); | ||
| 743 | event.info = new_client->fb_info; | ||
| 744 | fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); | ||
| 745 | console_unlock(); | ||
| 746 | } | ||
| 747 | 742 | ||
| 748 | mutex_lock(&vgasr_priv.mux_hw_lock); | 743 | mutex_lock(&vgasr_priv.mux_hw_lock); |
| 749 | ret = vgasr_priv.handler->switchto(new_client->id); | 744 | ret = vgasr_priv.handler->switchto(new_client->id); |
| @@ -512,10 +512,8 @@ int picolcd_init_framebuffer(struct picolcd_data *data) · 511 unmodified lines | |||
| 512 | sizeof(struct fb_deferred_io) + | 512 | sizeof(struct fb_deferred_io) + |
| 513 | sizeof(struct picolcd_fb_data) + | 513 | sizeof(struct picolcd_fb_data) + |
| 514 | PICOLCDFB_SIZE, dev); | 514 | PICOLCDFB_SIZE, dev); |
| 515 | if (info == NULL) { | 515 | if (!info) |
| 516 | dev_err(dev, "failed to allocate a framebuffer\n"); | ||
| 517 | goto err_nomem; | 516 | goto err_nomem; |
| 518 | } | ||
| 519 | 517 | ||
| 520 | info->fbdefio = info->par; | 518 | info->fbdefio = info->par; |
| 521 | *info->fbdefio = picolcd_fb_defio; | 519 | *info->fbdefio = picolcd_fb_defio; |
| @@ -1256,11 +1256,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p) · 1255 unmodified lines | |||
| 1256 | itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps &= | 1256 | itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps &= |
| 1257 | ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; | 1257 | ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
| 1258 | itv->v4l2_cap &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; | 1258 | itv->v4l2_cap &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY; |
| 1259 | if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { | 1259 | unregister_framebuffer(&itv->osd_info->ivtvfb_info); |
| 1260 | IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", | ||
| 1261 | itv->instance); | ||
| 1262 | return 0; | ||
| 1263 | } | ||
| 1264 | IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); | 1260 | IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); |
| 1265 | itv->ivtvfb_restore = NULL; | 1261 | itv->ivtvfb_restore = NULL; |
| 1266 | ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); | 1262 | ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); |
| @@ -891,7 +891,9 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info) · 890 unmodified lines | |||
| 891 | if (par->fbtftops.unregister_backlight) | 891 | if (par->fbtftops.unregister_backlight) |
| 892 | par->fbtftops.unregister_backlight(par); | 892 | par->fbtftops.unregister_backlight(par); |
| 893 | fbtft_sysfs_exit(par); | 893 | fbtft_sysfs_exit(par); |
| 894 | return unregister_framebuffer(fb_info); | 894 | unregister_framebuffer(fb_info); |
| 895 | |||
| 896 | return 0; | ||
| 895 | } | 897 | } |
| 896 | EXPORT_SYMBOL(fbtft_unregister_framebuffer); | 898 | EXPORT_SYMBOL(fbtft_unregister_framebuffer); |
| 897 | 899 | ||
| @@ -1,4 +1,11 @@ | |||
| 1 | TODO: | 1 | TODO: |
| 2 | - complete rewrite: | ||
| 3 | 1. The underlying fbdev drivers need to be converted into drm kernel | ||
| 4 | modesetting drivers. | ||
| 5 | 2. The dcon low-power display mode can then be integrated using the | ||
| 6 | drm damage tracking and self-refresh helpers. | ||
| 7 | This bolted-on self-refresh support that digs around in fbdev | ||
| 8 | internals, but isn't properly integrated, is not the correct solution. | ||
| 2 | - see if vx855 gpio API can be made similar enough to cs5535 so we can | 9 | - see if vx855 gpio API can be made similar enough to cs5535 so we can |
| 3 | share more code | 10 | share more code |
| 4 | - convert all uses of the old GPIO API from <linux/gpio.h> to the | 11 | - convert all uses of the old GPIO API from <linux/gpio.h> to the |
| @@ -250,11 +250,7 @@ static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank) · 249 unmodified lines | |||
| 250 | int err; | 250 | int err; |
| 251 | 251 | ||
| 252 | console_lock(); | 252 | console_lock(); |
| 253 | if (!lock_fb_info(dcon->fbinfo)) { | 253 | lock_fb_info(dcon->fbinfo); |
| 254 | console_unlock(); | ||
| 255 | dev_err(&dcon->client->dev, "unable to lock framebuffer\n"); | ||
| 256 | return false; | ||
| 257 | } | ||
| 258 | 254 | ||
| 259 | dcon->ignore_fb_events = true; | 255 | dcon->ignore_fb_events = true; |
| 260 | err = fb_blank(dcon->fbinfo, | 256 | err = fb_blank(dcon->fbinfo, |
| @@ -3822,6 +3822,8 @@ int con_is_bound(const struct consw *csw) · 3821 unmodified lines | |||
| 3822 | { | 3822 | { |
| 3823 | int i, bound = 0; | 3823 | int i, bound = 0; |
| 3824 | 3824 | ||
| 3825 | WARN_CONSOLE_UNLOCKED(); | ||
| 3826 | |||
| 3825 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 3827 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
| 3826 | if (con_driver_map[i] == csw) { | 3828 | if (con_driver_map[i] == csw) { |
| 3827 | bound = 1; | 3829 | bound = 1; |
| @@ -3833,6 +3835,20 @@ int con_is_bound(const struct consw *csw) · 5 unmodified lines | |||
| 3833 | } | 3835 | } |
| 3834 | EXPORT_SYMBOL(con_is_bound); | 3836 | EXPORT_SYMBOL(con_is_bound); |
| 3835 | 3837 | ||
| 3838 | /** | ||
| 3839 | * con_is_visible - checks whether the current console is visible | ||
| 3840 | * @vc: virtual console | ||
| 3841 | * | ||
| 3842 | * RETURNS: zero if not visible, nonzero if visible | ||
| 3843 | */ | ||
| 3844 | bool con_is_visible(const struct vc_data *vc) | ||
| 3845 | { | ||
| 3846 | WARN_CONSOLE_UNLOCKED(); | ||
| 3847 | |||
| 3848 | return *vc->vc_display_fg == vc; | ||
| 3849 | } | ||
| 3850 | EXPORT_SYMBOL(con_is_visible); | ||
| 3851 | |||
| 3836 | /** | 3852 | /** |
| 3837 | * con_debug_enter - prepare the console for the kernel debugger | 3853 | * con_debug_enter - prepare the console for the kernel debugger |
| 3838 | * @sw: console driver | 3854 | * @sw: console driver |
| @@ -4166,6 +4182,8 @@ void do_blank_screen(int entering_gfx) · 327 unmodified lines | |||
| 4166 | struct vc_data *vc = vc_cons[fg_console].d; | 4182 | struct vc_data *vc = vc_cons[fg_console].d; |
| 4167 | int i; | 4183 | int i; |
| 4168 | 4184 | ||
| 4185 | might_sleep(); | ||
| 4186 | |||
| 4169 | WARN_CONSOLE_UNLOCKED(); | 4187 | WARN_CONSOLE_UNLOCKED(); |
| 4170 | 4188 | ||
| 4171 | if (console_blanked) { | 4189 | if (console_blanked) { |
| @@ -47,7 +47,7 @@ static int fb_notifier_callback(struct notifier_block *self, · 46 unmodified lines | |||
| 47 | int fb_blank = 0; | 47 | int fb_blank = 0; |
| 48 | 48 | ||
| 49 | /* If we aren't interested in this event, skip it immediately ... */ | 49 | /* If we aren't interested in this event, skip it immediately ... */ |
| 50 | if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) | 50 | if (event != FB_EVENT_BLANK) |
| 51 | return 0; | 51 | return 0; |
| 52 | 52 | ||
| 53 | bd = container_of(self, struct backlight_device, fb_notif); | 53 | bd = container_of(self, struct backlight_device, fb_notif); |
| @@ -30,18 +30,6 @@ static int fb_notifier_callback(struct notifier_block *self, · 29 unmodified lines | |||
| 30 | struct lcd_device *ld; | 30 | struct lcd_device *ld; |
| 31 | struct fb_event *evdata = data; | 31 | struct fb_event *evdata = data; |
| 32 | 32 | ||
| 33 | /* If we aren't interested in this event, skip it immediately ... */ | ||
| 34 | switch (event) { | ||
| 35 | case FB_EVENT_BLANK: | ||
| 36 | case FB_EVENT_MODE_CHANGE: | ||
| 37 | case FB_EVENT_MODE_CHANGE_ALL: | ||
| 38 | case FB_EARLY_EVENT_BLANK: | ||
| 39 | case FB_R_EARLY_EVENT_BLANK: | ||
| 40 | break; | ||
| 41 | default: | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | ld = container_of(self, struct lcd_device, fb_notif); | 33 | ld = container_of(self, struct lcd_device, fb_notif); |
| 46 | if (!ld->ops) | 34 | if (!ld->ops) |
| 47 | return 0; | 35 | return 0; |
| @@ -34,6 +34,8 @@ static bool dummycon_putc_called; · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | void dummycon_register_output_notifier(struct notifier_block *nb) | 35 | void dummycon_register_output_notifier(struct notifier_block *nb) |
| 36 | { | 36 | { |
| 37 | WARN_CONSOLE_UNLOCKED(); | ||
| 38 | |||
| 37 | raw_notifier_chain_register(&dummycon_output_nh, nb); | 39 | raw_notifier_chain_register(&dummycon_output_nh, nb); |
| 38 | 40 | ||
| 39 | if (dummycon_putc_called) | 41 | if (dummycon_putc_called) |
| @@ -42,11 +44,15 @@ void dummycon_register_output_notifier(struct notifier_block *nb) · 2 unmodified lines | |||
| 42 | 44 | ||
| 43 | void dummycon_unregister_output_notifier(struct notifier_block *nb) | 45 | void dummycon_unregister_output_notifier(struct notifier_block *nb) |
| 44 | { | 46 | { |
| 47 | WARN_CONSOLE_UNLOCKED(); | ||
| 48 | |||
| 45 | raw_notifier_chain_unregister(&dummycon_output_nh, nb); | 49 | raw_notifier_chain_unregister(&dummycon_output_nh, nb); |
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) | 52 | static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) |
| 49 | { | 53 | { |
| 54 | WARN_CONSOLE_UNLOCKED(); | ||
| 55 | |||
| 50 | dummycon_putc_called = true; | 56 | dummycon_putc_called = true; |
| 51 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); | 57 | raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); |
| 52 | } | 58 | } |
| @@ -332,7 +332,8 @@ config FB_SA1100 · 331 unmodified lines | |||
| 332 | 332 | ||
| 333 | config FB_IMX | 333 | config FB_IMX |
| 334 | tristate "Freescale i.MX1/21/25/27 LCD support" | 334 | tristate "Freescale i.MX1/21/25/27 LCD support" |
| 335 | depends on FB && ARCH_MXC | 335 | depends on FB && HAVE_CLK && HAS_IOMEM |
| 336 | depends on ARCH_MXC || COMPILE_TEST | ||
| 336 | select LCD_CLASS_DEVICE | 337 | select LCD_CLASS_DEVICE |
| 337 | select FB_CFB_FILLRECT | 338 | select FB_CFB_FILLRECT |
| 338 | select FB_CFB_COPYAREA | 339 | select FB_CFB_COPYAREA |
| @@ -670,7 +671,8 @@ config FB_HGA · 331 unmodified lines | |||
| 670 | 671 | ||
| 671 | config FB_GBE | 672 | config FB_GBE |
| 672 | bool "SGI Graphics Backend frame buffer support" | 673 | bool "SGI Graphics Backend frame buffer support" |
| 673 | depends on (FB = y) && SGI_IP32 | 674 | depends on (FB = y) && HAS_IOMEM |
| 675 | depends on SGI_IP32 || COMPILE_TEST | ||
| 674 | select FB_CFB_FILLRECT | 676 | select FB_CFB_FILLRECT |
| 675 | select FB_CFB_COPYAREA | 677 | select FB_CFB_COPYAREA |
| 676 | select FB_CFB_IMAGEBLIT | 678 | select FB_CFB_IMAGEBLIT |
| @@ -808,7 +810,8 @@ config FB_XVR1000 · 131 unmodified lines | |||
| 808 | 810 | ||
| 809 | config FB_PVR2 | 811 | config FB_PVR2 |
| 810 | tristate "NEC PowerVR 2 display support" | 812 | tristate "NEC PowerVR 2 display support" |
| 811 | depends on FB && SH_DREAMCAST | 813 | depends on FB && HAS_IOMEM |
| 814 | depends on SH_DREAMCAST || COMPILE_TEST | ||
| 812 | select FB_CFB_FILLRECT | 815 | select FB_CFB_FILLRECT |
| 813 | select FB_CFB_COPYAREA | 816 | select FB_CFB_COPYAREA |
| 814 | select FB_CFB_IMAGEBLIT | 817 | select FB_CFB_IMAGEBLIT |
| @@ -856,7 +859,8 @@ config FB_S1D13XXX · 41 unmodified lines | |||
| 856 | 859 | ||
| 857 | config FB_ATMEL | 860 | config FB_ATMEL |
| 858 | tristate "AT91 LCD Controller support" | 861 | tristate "AT91 LCD Controller support" |
| 859 | depends on FB && OF && HAVE_FB_ATMEL | 862 | depends on FB && OF && HAVE_CLK && HAS_IOMEM |
| 863 | depends on HAVE_FB_ATMEL || COMPILE_TEST | ||
| 860 | select FB_BACKLIGHT | 864 | select FB_BACKLIGHT |
| 861 | select FB_CFB_FILLRECT | 865 | select FB_CFB_FILLRECT |
| 862 | select FB_CFB_COPYAREA | 866 | select FB_CFB_COPYAREA |
| @@ -1729,7 +1733,8 @@ config FB_68328 · 866 unmodified lines | |||
| 1729 | 1733 | ||
| 1730 | config FB_PXA168 | 1734 | config FB_PXA168 |
| 1731 | tristate "PXA168/910 LCD framebuffer support" | 1735 | tristate "PXA168/910 LCD framebuffer support" |
| 1732 | depends on FB && (CPU_PXA168 || CPU_PXA910) | 1736 | depends on FB && HAVE_CLK && HAS_IOMEM |
| 1737 | depends on CPU_PXA168 || CPU_PXA910 || COMPILE_TEST | ||
| 1733 | select FB_CFB_FILLRECT | 1738 | select FB_CFB_FILLRECT |
| 1734 | select FB_CFB_COPYAREA | 1739 | select FB_CFB_COPYAREA |
| 1735 | select FB_CFB_IMAGEBLIT | 1740 | select FB_CFB_IMAGEBLIT |
| @@ -1873,7 +1878,8 @@ config FB_TMIO_ACCELL · 137 unmodified lines | |||
| 1873 | 1878 | ||
| 1874 | config FB_S3C | 1879 | config FB_S3C |
| 1875 | tristate "Samsung S3C framebuffer support" | 1880 | tristate "Samsung S3C framebuffer support" |
| 1876 | depends on FB && (CPU_S3C2416 || ARCH_S3C64XX) | 1881 | depends on FB && HAVE_CLK && HAS_IOMEM |
| 1882 | depends on (CPU_S3C2416 || ARCH_S3C64XX) || COMPILE_TEST | ||
| 1877 | select FB_CFB_FILLRECT | 1883 | select FB_CFB_FILLRECT |
| 1878 | select FB_CFB_COPYAREA | 1884 | select FB_CFB_COPYAREA |
| 1879 | select FB_CFB_IMAGEBLIT | 1885 | select FB_CFB_IMAGEBLIT |
| @@ -2055,7 +2061,8 @@ config FB_SH7760 · 175 unmodified lines | |||
| 2055 | 2061 | ||
| 2056 | config FB_DA8XX | 2062 | config FB_DA8XX |
| 2057 | tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" | 2063 | tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" |
| 2058 | depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX) | 2064 | depends on FB && HAVE_CLK && HAS_IOMEM |
| 2065 | depends on ARCH_DAVINCI_DA8XX || SOC_AM33XX || COMPILE_TEST | ||
| 2059 | select FB_CFB_FILLRECT | 2066 | select FB_CFB_FILLRECT |
| 2060 | select FB_CFB_COPYAREA | 2067 | select FB_CFB_COPYAREA |
| 2061 | select FB_CFB_IMAGEBLIT | 2068 | select FB_CFB_IMAGEBLIT |
| @@ -2172,7 +2179,7 @@ config FB_EP93XX · 110 unmodified lines | |||
| 2172 | 2179 | ||
| 2173 | config FB_PRE_INIT_FB | 2180 | config FB_PRE_INIT_FB |
| 2174 | bool "Don't reinitialize, use bootloader's GDC/Display configuration" | 2181 | bool "Don't reinitialize, use bootloader's GDC/Display configuration" |
| 2175 | depends on FB && (FB_MB862XX_LIME || FB_MXS) | 2182 | depends on FB && FB_MB862XX_LIME |
| 2176 | ---help--- | 2183 | ---help--- |
| 2177 | Select this option if display contents should be inherited as set by | 2184 | Select this option if display contents should be inherited as set by |
| 2178 | the bootloader. | 2185 | the bootloader. |
| @@ -2213,17 +2220,6 @@ config FB_JZ4740 · 34 unmodified lines | |||
| 2213 | help | 2220 | help |
| 2214 | Framebuffer support for the JZ4740 SoC. | 2221 | Framebuffer support for the JZ4740 SoC. |
| 2215 | 2222 | ||
| 2216 | config FB_MXS | ||
| 2217 | tristate "MXS LCD framebuffer support" | ||
| 2218 | depends on FB && (ARCH_MXS || ARCH_MXC) | ||
| 2219 | select FB_CFB_FILLRECT | ||
| 2220 | select FB_CFB_COPYAREA | ||
| 2221 | select FB_CFB_IMAGEBLIT | ||
| 2222 | select FB_MODE_HELPERS | ||
| 2223 | select VIDEOMODE_HELPERS | ||
| 2224 | help | ||
| 2225 | Framebuffer support for the MXS SoC. | ||
| 2226 | |||
| 2227 | config FB_PUV3_UNIGFX | 2223 | config FB_PUV3_UNIGFX |
| 2228 | tristate "PKUnity v3 Unigfx framebuffer support" | 2224 | tristate "PKUnity v3 Unigfx framebuffer support" |
| 2229 | depends on FB && UNICORE32 && ARCH_PUV3 | 2225 | depends on FB && UNICORE32 && ARCH_PUV3 |
| @@ -131,7 +131,6 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o · 130 unmodified lines | |||
| 131 | obj-$(CONFIG_FB_OF) += offb.o | 131 | obj-$(CONFIG_FB_OF) += offb.o |
| 132 | obj-$(CONFIG_FB_MX3) += mx3fb.o | 132 | obj-$(CONFIG_FB_MX3) += mx3fb.o |
| 133 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o | 133 | obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o |
| 134 | obj-$(CONFIG_FB_MXS) += mxsfb.o | ||
| 135 | obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o | 134 | obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o |
| 136 | obj-$(CONFIG_FB_SIMPLE) += simplefb.o | 135 | obj-$(CONFIG_FB_SIMPLE) += simplefb.o |
| 137 | 136 | ||
| @@ -3554,10 +3554,8 @@ static int __init amifb_probe(struct platform_device *pdev) · 3553 unmodified lines | |||
| 3554 | custom.dmacon = DMAF_ALL | DMAF_MASTER; | 3554 | custom.dmacon = DMAF_ALL | DMAF_MASTER; |
| 3555 | 3555 | ||
| 3556 | info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev); | 3556 | info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev); |
| 3557 | if (!info) { | 3557 | if (!info) |
| 3558 | dev_err(&pdev->dev, "framebuffer_alloc failed\n"); | ||
| 3559 | return -ENOMEM; | 3558 | return -ENOMEM; |
| 3560 | } | ||
| 3561 | 3559 | ||
| 3562 | strcpy(info->fix.id, "Amiga "); | 3560 | strcpy(info->fix.id, "Amiga "); |
| 3563 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | 3561 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
| @@ -954,10 +954,8 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 953 unmodified lines | |||
| 954 | 954 | ||
| 955 | /* Allocate and fill driver data structure */ | 955 | /* Allocate and fill driver data structure */ |
| 956 | info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev)); | 956 | info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev)); |
| 957 | if (! info) { | 957 | if (!info) |
| 958 | dev_err(&(dev->dev), "cannot allocate memory\n"); | ||
| 959 | return -ENOMEM; | 958 | return -ENOMEM; |
| 960 | } | ||
| 961 | 959 | ||
| 962 | par = info->par; | 960 | par = info->par; |
| 963 | mutex_init(&par->open_lock); | 961 | mutex_init(&par->open_lock); |
| @@ -77,29 +77,8 @@ · 76 unmodified lines | |||
| 77 | #define SWITCH_SND7 0x80 | 77 | #define SWITCH_SND7 0x80 |
| 78 | #define SWITCH_NONE 0x00 | 78 | #define SWITCH_NONE 0x00 |
| 79 | 79 | ||
| 80 | |||
| 81 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) | 80 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) |
| 82 | 81 | ||
| 83 | /* | ||
| 84 | * Interface to the world | ||
| 85 | */ | ||
| 86 | |||
| 87 | static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); | ||
| 88 | static int atafb_set_par(struct fb_info *info); | ||
| 89 | static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
| 90 | unsigned int blue, unsigned int transp, | ||
| 91 | struct fb_info *info); | ||
| 92 | static int atafb_blank(int blank, struct fb_info *info); | ||
| 93 | static int atafb_pan_display(struct fb_var_screeninfo *var, | ||
| 94 | struct fb_info *info); | ||
| 95 | static void atafb_fillrect(struct fb_info *info, | ||
| 96 | const struct fb_fillrect *rect); | ||
| 97 | static void atafb_copyarea(struct fb_info *info, | ||
| 98 | const struct fb_copyarea *region); | ||
| 99 | static void atafb_imageblit(struct fb_info *info, const struct fb_image *image); | ||
| 100 | static int atafb_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 101 | unsigned long arg); | ||
| 102 | |||
| 103 | 82 | ||
| 104 | static int default_par; /* default resolution (0=none) */ | 83 | static int default_par; /* default resolution (0=none) */ |
| 105 | 84 | ||
| @@ -673,7 +673,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) · 672 unmodified lines | |||
| 673 | lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); | 673 | lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0); |
| 674 | 674 | ||
| 675 | /* Disable all interrupts */ | 675 | /* Disable all interrupts */ |
| 676 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 676 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0U); |
| 677 | /* Enable FIFO & DMA errors */ | 677 | /* Enable FIFO & DMA errors */ |
| 678 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); | 678 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); |
| 679 | 679 | ||
| @@ -950,7 +950,7 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo) · 270 unmodified lines | |||
| 950 | struct fb_videomode fb_vm; | 950 | struct fb_videomode fb_vm; |
| 951 | struct gpio_desc *gpiod; | 951 | struct gpio_desc *gpiod; |
| 952 | struct videomode vm; | 952 | struct videomode vm; |
| 953 | int ret = -ENOENT; | 953 | int ret; |
| 954 | int i; | 954 | int i; |
| 955 | 955 | ||
| 956 | sinfo->config = (struct atmel_lcdfb_config*) | 956 | sinfo->config = (struct atmel_lcdfb_config*) |
| @@ -1053,10 +1053,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) · 96 unmodified lines | |||
| 1053 | 1053 | ||
| 1054 | ret = -ENOMEM; | 1054 | ret = -ENOMEM; |
| 1055 | info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); | 1055 | info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev); |
| 1056 | if (!info) { | 1056 | if (!info) |
| 1057 | dev_err(dev, "cannot allocate memory\n"); | ||
| 1058 | goto out; | 1057 | goto out; |
| 1059 | } | ||
| 1060 | 1058 | ||
| 1061 | sinfo = info->par; | 1059 | sinfo = info->par; |
| 1062 | sinfo->pdev = pdev; | 1060 | sinfo->pdev = pdev; |
| @@ -1291,7 +1289,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) · 228 unmodified lines | |||
| 1291 | * We don't want to handle interrupts while the clock is | 1289 | * We don't want to handle interrupts while the clock is |
| 1292 | * stopped. It may take forever. | 1290 | * stopped. It may take forever. |
| 1293 | */ | 1291 | */ |
| 1294 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 1292 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0U); |
| 1295 | 1293 | ||
| 1296 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR); | 1294 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR); |
| 1297 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); | 1295 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); |
| @@ -2103,10 +2103,9 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 2102 unmodified lines | |||
| 2103 | 2103 | ||
| 2104 | /* We have the resources. Now virtualize them */ | 2104 | /* We have the resources. Now virtualize them */ |
| 2105 | info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev); | 2105 | info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev); |
| 2106 | if (info == NULL) { | 2106 | if (!info) |
| 2107 | printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n"); | ||
| 2108 | goto err_free_mmio; | 2107 | goto err_free_mmio; |
| 2109 | } | 2108 | |
| 2110 | par = info->par; | 2109 | par = info->par; |
| 2111 | 2110 | ||
| 2112 | info->pseudo_palette = par->pseudo_palette; | 2111 | info->pseudo_palette = par->pseudo_palette; |
| @@ -2350,70 +2349,6 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) · 237 unmodified lines | |||
| 2350 | return -EINVAL; | 2349 | return -EINVAL; |
| 2351 | } | 2350 | } |
| 2352 | 2351 | ||
| 2353 | #if 0 | ||
| 2354 | /* | ||
| 2355 | * Accelerated functions | ||
| 2356 | */ | ||
| 2357 | |||
| 2358 | static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty, | ||
| 2359 | u_int width, u_int height, | ||
| 2360 | struct fb_info_aty128 *par) | ||
| 2361 | { | ||
| 2362 | u32 save_dp_datatype, save_dp_cntl, dstval; | ||
| 2363 | |||
| 2364 | if (!width || !height) | ||
| 2365 | return; | ||
| 2366 | |||
| 2367 | dstval = depth_to_dst(par->current_par.crtc.depth); | ||
| 2368 | if (dstval == DST_24BPP) { | ||
| 2369 | srcx *= 3; | ||
| 2370 | dstx *= 3; | ||
| 2371 | width *= 3; | ||
| 2372 | } else if (dstval == -EINVAL) { | ||
| 2373 | printk("aty128fb: invalid depth or RGBA\n"); | ||
| 2374 | return; | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | wait_for_fifo(2, par); | ||
| 2378 | save_dp_datatype = aty_ld_le32(DP_DATATYPE); | ||
| 2379 | save_dp_cntl = aty_ld_le32(DP_CNTL); | ||
| 2380 | |||
| 2381 | wait_for_fifo(6, par); | ||
| 2382 | aty_st_le32(SRC_Y_X, (srcy << 16) | srcx); | ||
| 2383 | aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT); | ||
| 2384 | aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); | ||
| 2385 | aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR); | ||
| 2386 | |||
| 2387 | aty_st_le32(DST_Y_X, (dsty << 16) | dstx); | ||
| 2388 | aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width); | ||
| 2389 | |||
| 2390 | par->blitter_may_be_busy = 1; | ||
| 2391 | |||
| 2392 | wait_for_fifo(2, par); | ||
| 2393 | aty_st_le32(DP_DATATYPE, save_dp_datatype); | ||
| 2394 | aty_st_le32(DP_CNTL, save_dp_cntl); | ||
| 2395 | } | ||
| 2396 | |||
| 2397 | |||
| 2398 | /* | ||
| 2399 | * Text mode accelerated functions | ||
| 2400 | */ | ||
| 2401 | |||
| 2402 | static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, | ||
| 2403 | int dx, int height, int width) | ||
| 2404 | { | ||
| 2405 | sx *= fontwidth(p); | ||
| 2406 | sy *= fontheight(p); | ||
| 2407 | dx *= fontwidth(p); | ||
| 2408 | dy *= fontheight(p); | ||
| 2409 | width *= fontwidth(p); | ||
| 2410 | height *= fontheight(p); | ||
| 2411 | |||
| 2412 | aty128_rectcopy(sx, sy, dx, dy, width, height, | ||
| 2413 | (struct fb_info_aty128 *)p->fb_info); | ||
| 2414 | } | ||
| 2415 | #endif /* 0 */ | ||
| 2416 | |||
| 2417 | static void aty128_set_suspend(struct aty128fb_par *par, int suspend) | 2352 | static void aty128_set_suspend(struct aty128fb_par *par, int suspend) |
| 2418 | { | 2353 | { |
| 2419 | u32 pmgt; | 2354 | u32 pmgt; |
| @@ -3550,10 +3550,9 @@ static int atyfb_pci_probe(struct pci_dev *pdev, · 3549 unmodified lines | |||
| 3550 | 3550 | ||
| 3551 | /* Allocate framebuffer */ | 3551 | /* Allocate framebuffer */ |
| 3552 | info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev); | 3552 | info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev); |
| 3553 | if (!info) { | 3553 | if (!info) |
| 3554 | PRINTKE("atyfb_pci_probe() can't alloc fb_info\n"); | ||
| 3555 | return -ENOMEM; | 3554 | return -ENOMEM; |
| 3556 | } | 3555 | |
| 3557 | par = info->par; | 3556 | par = info->par; |
| 3558 | par->bus_type = PCI; | 3557 | par->bus_type = PCI; |
| 3559 | info->fix = atyfb_fix; | 3558 | info->fix = atyfb_fix; |
| @@ -3643,10 +3642,9 @@ static int __init atyfb_atari_probe(void) · 83 unmodified lines | |||
| 3643 | } | 3642 | } |
| 3644 | 3643 | ||
| 3645 | info = framebuffer_alloc(sizeof(struct atyfb_par), NULL); | 3644 | info = framebuffer_alloc(sizeof(struct atyfb_par), NULL); |
| 3646 | if (!info) { | 3645 | if (!info) |
| 3647 | PRINTKE("atyfb_atari_probe() can't alloc fb_info\n"); | ||
| 3648 | return -ENOMEM; | 3646 | return -ENOMEM; |
| 3649 | } | 3647 | |
| 3650 | par = info->par; | 3648 | par = info->par; |
| 3651 | 3649 | ||
| 3652 | info->fix = atyfb_fix; | 3650 | info->fix = atyfb_fix; |
| @@ -3916,8 +3914,7 @@ static int atyfb_reboot_notify(struct notifier_block *nb, · 263 unmodified lines | |||
| 3916 | if (!reboot_info) | 3914 | if (!reboot_info) |
| 3917 | goto out; | 3915 | goto out; |
| 3918 | 3916 | ||
| 3919 | if (!lock_fb_info(reboot_info)) | 3917 | lock_fb_info(reboot_info); |
| 3920 | goto out; | ||
| 3921 | 3918 | ||
| 3922 | par = reboot_info->par; | 3919 | par = reboot_info->par; |
| 3923 | 3920 | ||
| @@ -2294,8 +2294,6 @@ static int radeonfb_pci_register(struct pci_dev *pdev, · 2293 unmodified lines | |||
| 2294 | 2294 | ||
| 2295 | info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev); | 2295 | info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev); |
| 2296 | if (!info) { | 2296 | if (!info) { |
| 2297 | printk (KERN_ERR "radeonfb (%s): could not allocate memory\n", | ||
| 2298 | pci_name(pdev)); | ||
| 2299 | ret = -ENOMEM; | 2297 | ret = -ENOMEM; |
| 2300 | goto err_disable; | 2298 | goto err_disable; |
| 2301 | } | 2299 | } |
| @@ -147,6 +147,7 @@ struct au1200_lcd_iodata_t { · 146 unmodified lines | |||
| 147 | struct au1200fb_device { | 147 | struct au1200fb_device { |
| 148 | struct fb_info *fb_info; /* FB driver info record */ | 148 | struct fb_info *fb_info; /* FB driver info record */ |
| 149 | struct au1200fb_platdata *pd; | 149 | struct au1200fb_platdata *pd; |
| 150 | struct device *dev; | ||
| 150 | 151 | ||
| 151 | int plane; | 152 | int plane; |
| 152 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 153 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
| @@ -1232,10 +1233,8 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) · 1079 unmodified lines | |||
| 1232 | { | 1233 | { |
| 1233 | struct au1200fb_device *fbdev = info->par; | 1234 | struct au1200fb_device *fbdev = info->par; |
| 1234 | 1235 | ||
| 1235 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 1236 | return dma_mmap_attrs(fbdev->dev, vma, fbdev->fb_mem, fbdev->fb_phys, |
| 1236 | pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ | 1237 | fbdev->fb_len, DMA_ATTR_NON_CONSISTENT); |
| 1237 | |||
| 1238 | return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len); | ||
| 1239 | } | 1238 | } |
| 1240 | 1239 | ||
| 1241 | static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | 1240 | static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) |
| @@ -1647,7 +1646,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) · 405 unmodified lines | |||
| 1647 | struct au1200fb_device *fbdev; | 1646 | struct au1200fb_device *fbdev; |
| 1648 | struct au1200fb_platdata *pd; | 1647 | struct au1200fb_platdata *pd; |
| 1649 | struct fb_info *fbi = NULL; | 1648 | struct fb_info *fbi = NULL; |
| 1650 | unsigned long page; | ||
| 1651 | int bpp, plane, ret, irq; | 1649 | int bpp, plane, ret, irq; |
| 1652 | 1650 | ||
| 1653 | print_info("" DRIVER_DESC ""); | 1651 | print_info("" DRIVER_DESC ""); |
| @@ -1685,6 +1683,7 @@ static int au1200fb_drv_probe(struct platform_device *dev) · 31 unmodified lines | |||
| 1685 | fbdev = fbi->par; | 1683 | fbdev = fbi->par; |
| 1686 | fbdev->fb_info = fbi; | 1684 | fbdev->fb_info = fbi; |
| 1687 | fbdev->pd = pd; | 1685 | fbdev->pd = pd; |
| 1686 | fbdev->dev = &dev->dev; | ||
| 1688 | 1687 | ||
| 1689 | fbdev->plane = plane; | 1688 | fbdev->plane = plane; |
| 1690 | 1689 | ||
| @@ -1702,16 +1701,6 @@ static int au1200fb_drv_probe(struct platform_device *dev) · 11 unmodified lines | |||
| 1702 | goto failed; | 1701 | goto failed; |
| 1703 | } | 1702 | } |
| 1704 | 1703 | ||
| 1705 | /* | ||
| 1706 | * Set page reserved so that mmap will work. This is necessary | ||
| 1707 | * since we'll be remapping normal memory. | ||
| 1708 | */ | ||
| 1709 | for (page = (unsigned long)fbdev->fb_phys; | ||
| 1710 | page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + | ||
| 1711 | fbdev->fb_len); | ||
| 1712 | page += PAGE_SIZE) { | ||
| 1713 | SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ | ||
| 1714 | } | ||
| 1715 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); | 1704 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); |
| 1716 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | 1705 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); |
| 1717 | 1706 | ||
| @@ -366,7 +366,6 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) · 365 unmodified lines | |||
| 366 | 366 | ||
| 367 | p = framebuffer_alloc(0, &dp->dev); | 367 | p = framebuffer_alloc(0, &dp->dev); |
| 368 | if (p == NULL) { | 368 | if (p == NULL) { |
| 369 | dev_err(&dp->dev, "Cannot allocate framebuffer structure\n"); | ||
| 370 | rc = -ENOMEM; | 369 | rc = -ENOMEM; |
| 371 | goto err_disable; | 370 | goto err_disable; |
| 372 | } | 371 | } |
| @@ -2093,7 +2093,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, · 2092 unmodified lines | |||
| 2093 | 2093 | ||
| 2094 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); | 2094 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); |
| 2095 | if (!info) { | 2095 | if (!info) { |
| 2096 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); | ||
| 2097 | ret = -ENOMEM; | 2096 | ret = -ENOMEM; |
| 2098 | goto err_out; | 2097 | goto err_out; |
| 2099 | } | 2098 | } |
| @@ -2206,10 +2205,8 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, · 106 unmodified lines | |||
| 2206 | struct cirrusfb_info *cinfo; | 2205 | struct cirrusfb_info *cinfo; |
| 2207 | 2206 | ||
| 2208 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); | 2207 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); |
| 2209 | if (!info) { | 2208 | if (!info) |
| 2210 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); | ||
| 2211 | return -ENOMEM; | 2209 | return -ENOMEM; |
| 2212 | } | ||
| 2213 | 2210 | ||
| 2214 | zcl = (const struct zorrocl *)ent->driver_data; | 2211 | zcl = (const struct zorrocl *)ent->driver_data; |
| 2215 | btype = zcl->type; | 2212 | btype = zcl->type; |
| @@ -182,7 +182,7 @@ int init_module(void) · 181 unmodified lines | |||
| 182 | int ret = -ENXIO; | 182 | int ret = -ENXIO; |
| 183 | 183 | ||
| 184 | dp = of_find_node_by_name(NULL, "control"); | 184 | dp = of_find_node_by_name(NULL, "control"); |
| 185 | if (dp != 0 && !control_of_init(dp)) | 185 | if (dp && !control_of_init(dp)) |
| 186 | ret = 0; | 186 | ret = 0; |
| 187 | of_node_put(dp); | 187 | of_node_put(dp); |
| 188 | 188 | ||
| @@ -580,7 +580,7 @@ static int __init control_init(void) · 391 unmodified lines | |||
| 580 | control_setup(option); | 580 | control_setup(option); |
| 581 | 581 | ||
| 582 | dp = of_find_node_by_name(NULL, "control"); | 582 | dp = of_find_node_by_name(NULL, "control"); |
| 583 | if (dp != 0 && !control_of_init(dp)) | 583 | if (dp && !control_of_init(dp)) |
| 584 | ret = 0; | 584 | ret = 0; |
| 585 | of_node_put(dp); | 585 | of_node_put(dp); |
| 586 | 586 | ||
| @@ -683,8 +683,8 @@ static int __init control_of_init(struct device_node *dp) · 96 unmodified lines | |||
| 683 | return -ENXIO; | 683 | return -ENXIO; |
| 684 | } | 684 | } |
| 685 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 685 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 686 | if (p == 0) | 686 | if (!p) |
| 687 | return -ENXIO; | 687 | return -ENOMEM; |
| 688 | control_fb = p; /* save it for cleanups */ | 688 | control_fb = p; /* save it for cleanups */ |
| 689 | 689 | ||
| 690 | /* Map in frame buffer and registers */ | 690 | /* Map in frame buffer and registers */ |
| @@ -285,11 +285,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) · 284 unmodified lines | |||
| 285 | goto out; | 285 | goto out; |
| 286 | } | 286 | } |
| 287 | umap.start = cmap->start; | 287 | umap.start = cmap->start; |
| 288 | if (!lock_fb_info(info)) { | 288 | lock_fb_info(info); |
| 289 | rc = -ENODEV; | ||
| 290 | goto out; | ||
| 291 | } | ||
| 292 | |||
| 293 | rc = fb_set_cmap(&umap, info); | 289 | rc = fb_set_cmap(&umap, info); |
| 294 | unlock_fb_info(info); | 290 | unlock_fb_info(info); |
| 295 | out: | 291 | out: |
| @@ -76,6 +76,7 @@ · 75 unmodified lines | |||
| 76 | #include <linux/init.h> | 76 | #include <linux/init.h> |
| 77 | #include <linux/interrupt.h> | 77 | #include <linux/interrupt.h> |
| 78 | #include <linux/crc32.h> /* For counting font checksums */ | 78 | #include <linux/crc32.h> /* For counting font checksums */ |
| 79 | #include <linux/uaccess.h> | ||
| 79 | #include <asm/fb.h> | 80 | #include <asm/fb.h> |
| 80 | #include <asm/irq.h> | 81 | #include <asm/irq.h> |
| 81 | 82 | ||
| @@ -87,13 +88,32 @@ · 5 unmodified lines | |||
| 87 | # define DPRINTK(fmt, args...) | 88 | # define DPRINTK(fmt, args...) |
| 88 | #endif | 89 | #endif |
| 89 | 90 | ||
| 91 | /* | ||
| 92 | * FIXME: Locking | ||
| 93 | * | ||
| 94 | * - fbcon state itself is protected by the console_lock, and the code does a | ||
| 95 | * pretty good job at making sure that lock is held everywhere it's needed. | ||
| 96 | * | ||
| 97 | * - access to the registered_fb array is entirely unprotected. This should use | ||
| 98 | * proper object lifetime handling, i.e. get/put_fb_info. This also means | ||
| 99 | * switching from indices to proper pointers for fb_info everywhere. | ||
| 100 | * | ||
| 101 | * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it | ||
| 102 | * means concurrent access to the same fbdev from both fbcon and userspace | ||
| 103 | * will blow up. To fix this all fbcon calls from fbmem.c need to be moved out | ||
| 104 | * of fb_lock/unlock protected sections, since otherwise we'll recurse and | ||
| 105 | * deadlock eventually. Aside: Due to these deadlock issues the fbdev code in | ||
| 106 | * fbmem.c cannot use locking asserts, and there's lots of callers which get | ||
| 107 | * the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too. | ||
| 108 | */ | ||
| 109 | |||
| 90 | enum { | 110 | enum { |
| 91 | FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ | 111 | FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ |
| 92 | FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ | 112 | FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ |
| 93 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ | 113 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ |
| 94 | }; | 114 | }; |
| 95 | 115 | ||
| 96 | static struct display fb_display[MAX_NR_CONSOLES]; | 116 | static struct fbcon_display fb_display[MAX_NR_CONSOLES]; |
| 97 | 117 | ||
| 98 | static signed char con2fb_map[MAX_NR_CONSOLES]; | 118 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
| 99 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; | 119 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
| @@ -112,7 +132,6 @@ static int softback_lines; · 12 unmodified lines | |||
| 112 | static int first_fb_vc; | 132 | static int first_fb_vc; |
| 113 | static int last_fb_vc = MAX_NR_CONSOLES - 1; | 133 | static int last_fb_vc = MAX_NR_CONSOLES - 1; |
| 114 | static int fbcon_is_default = 1; | 134 | static int fbcon_is_default = 1; |
| 115 | static int fbcon_has_exited; | ||
| 116 | static int primary_device = -1; | 135 | static int primary_device = -1; |
| 117 | static int fbcon_has_console_bind; | 136 | static int fbcon_has_console_bind; |
| 118 | 137 | ||
| @@ -185,11 +204,11 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count); · 66 unmodified lines | |||
| 185 | static __inline__ void ywrap_down(struct vc_data *vc, int count); | 204 | static __inline__ void ywrap_down(struct vc_data *vc, int count); |
| 186 | static __inline__ void ypan_up(struct vc_data *vc, int count); | 205 | static __inline__ void ypan_up(struct vc_data *vc, int count); |
| 187 | static __inline__ void ypan_down(struct vc_data *vc, int count); | 206 | static __inline__ void ypan_down(struct vc_data *vc, int count); |
| 188 | static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, | 207 | static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, |
| 189 | int dy, int dx, int height, int width, u_int y_break); | 208 | int dy, int dx, int height, int width, u_int y_break); |
| 190 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | 209 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
| 191 | int unit); | 210 | int unit); |
| 192 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, | 211 | static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, |
| 193 | int line, int count, int dy); | 212 | int line, int count, int dy); |
| 194 | static void fbcon_modechanged(struct fb_info *info); | 213 | static void fbcon_modechanged(struct fb_info *info); |
| 195 | static void fbcon_set_all_vcs(struct fb_info *info); | 214 | static void fbcon_set_all_vcs(struct fb_info *info); |
| @@ -220,7 +239,7 @@ static void fbcon_rotate(struct fb_info *info, u32 rotate) · 24 unmodified lines | |||
| 220 | fb_info = registered_fb[con2fb_map[ops->currcon]]; | 239 | fb_info = registered_fb[con2fb_map[ops->currcon]]; |
| 221 | 240 | ||
| 222 | if (info == fb_info) { | 241 | if (info == fb_info) { |
| 223 | struct display *p = &fb_display[ops->currcon]; | 242 | struct fbcon_display *p = &fb_display[ops->currcon]; |
| 224 | 243 | ||
| 225 | if (rotate < 4) | 244 | if (rotate < 4) |
| 226 | p->con_rotate = rotate; | 245 | p->con_rotate = rotate; |
| @@ -235,7 +254,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate) · 8 unmodified lines | |||
| 235 | { | 254 | { |
| 236 | struct fbcon_ops *ops = info->fbcon_par; | 255 | struct fbcon_ops *ops = info->fbcon_par; |
| 237 | struct vc_data *vc; | 256 | struct vc_data *vc; |
| 238 | struct display *p; | 257 | struct fbcon_display *p; |
| 239 | int i; | 258 | int i; |
| 240 | 259 | ||
| 241 | if (!ops || ops->currcon < 0 || rotate > 3) | 260 | if (!ops || ops->currcon < 0 || rotate > 3) |
| @@ -900,7 +919,7 @@ static int set_con2fb_map(int unit, int newidx, int user) · 658 unmodified lines | |||
| 900 | * Low Level Operations | 919 | * Low Level Operations |
| 901 | */ | 920 | */ |
| 902 | /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */ | 921 | /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */ |
| 903 | static int var_to_display(struct display *disp, | 922 | static int var_to_display(struct fbcon_display *disp, |
| 904 | struct fb_var_screeninfo *var, | 923 | struct fb_var_screeninfo *var, |
| 905 | struct fb_info *info) | 924 | struct fb_info *info) |
| 906 | { | 925 | { |
| @@ -925,7 +944,7 @@ static int var_to_display(struct display *disp, · 18 unmodified lines | |||
| 925 | } | 944 | } |
| 926 | 945 | ||
| 927 | static void display_to_var(struct fb_var_screeninfo *var, | 946 | static void display_to_var(struct fb_var_screeninfo *var, |
| 928 | struct display *disp) | 947 | struct fbcon_display *disp) |
| 929 | { | 948 | { |
| 930 | fb_videomode_to_var(var, disp->mode); | 949 | fb_videomode_to_var(var, disp->mode); |
| 931 | var->xres_virtual = disp->xres_virtual; | 950 | var->xres_virtual = disp->xres_virtual; |
| @@ -946,7 +965,7 @@ static void display_to_var(struct fb_var_screeninfo *var, · 14 unmodified lines | |||
| 946 | static const char *fbcon_startup(void) | 965 | static const char *fbcon_startup(void) |
| 947 | { | 966 | { |
| 948 | const char *display_desc = "frame buffer device"; | 967 | const char *display_desc = "frame buffer device"; |
| 949 | struct display *p = &fb_display[fg_console]; | 968 | struct fbcon_display *p = &fb_display[fg_console]; |
| 950 | struct vc_data *vc = vc_cons[fg_console].d; | 969 | struct vc_data *vc = vc_cons[fg_console].d; |
| 951 | const struct font_desc *font = NULL; | 970 | const struct font_desc *font = NULL; |
| 952 | struct module *owner; | 971 | struct module *owner; |
| @@ -1050,23 +1069,26 @@ static const char *fbcon_startup(void) · 97 unmodified lines | |||
| 1050 | info->var.bits_per_pixel); | 1069 | info->var.bits_per_pixel); |
| 1051 | 1070 | ||
| 1052 | fbcon_add_cursor_timer(info); | 1071 | fbcon_add_cursor_timer(info); |
| 1053 | fbcon_has_exited = 0; | ||
| 1054 | return display_desc; | 1072 | return display_desc; |
| 1055 | } | 1073 | } |
| 1056 | 1074 | ||
| 1057 | static void fbcon_init(struct vc_data *vc, int init) | 1075 | static void fbcon_init(struct vc_data *vc, int init) |
| 1058 | { | 1076 | { |
| 1059 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1077 | struct fb_info *info; |
| 1060 | struct fbcon_ops *ops; | 1078 | struct fbcon_ops *ops; |
| 1061 | struct vc_data **default_mode = vc->vc_display_fg; | 1079 | struct vc_data **default_mode = vc->vc_display_fg; |
| 1062 | struct vc_data *svc = *default_mode; | 1080 | struct vc_data *svc = *default_mode; |
| 1063 | struct display *t, *p = &fb_display[vc->vc_num]; | 1081 | struct fbcon_display *t, *p = &fb_display[vc->vc_num]; |
| 1064 | int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; | 1082 | int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; |
| 1065 | int cap, ret; | 1083 | int cap, ret; |
| 1066 | 1084 | ||
| 1067 | if (info_idx == -1 || info == NULL) | 1085 | if (WARN_ON(info_idx == -1)) |
| 1068 | return; | 1086 | return; |
| 1069 | 1087 | ||
| 1088 | if (con2fb_map[vc->vc_num] == -1) | ||
| 1089 | con2fb_map[vc->vc_num] = info_idx; | ||
| 1090 | |||
| 1091 | info = registered_fb[con2fb_map[vc->vc_num]]; | ||
| 1070 | cap = info->flags; | 1092 | cap = info->flags; |
| 1071 | 1093 | ||
| 1072 | if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) | 1094 | if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) |
| @@ -1203,7 +1225,7 @@ static void fbcon_init(struct vc_data *vc, int init) · 130 unmodified lines | |||
| 1203 | ops->p = &fb_display[fg_console]; | 1225 | ops->p = &fb_display[fg_console]; |
| 1204 | } | 1226 | } |
| 1205 | 1227 | ||
| 1206 | static void fbcon_free_font(struct display *p, bool freefont) | 1228 | static void fbcon_free_font(struct fbcon_display *p, bool freefont) |
| 1207 | { | 1229 | { |
| 1208 | if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) | 1230 | if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) |
| 1209 | kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); | 1231 | kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); |
| @@ -1215,7 +1237,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set); · 5 unmodified lines | |||
| 1215 | 1237 | ||
| 1216 | static void fbcon_deinit(struct vc_data *vc) | 1238 | static void fbcon_deinit(struct vc_data *vc) |
| 1217 | { | 1239 | { |
| 1218 | struct display *p = &fb_display[vc->vc_num]; | 1240 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1219 | struct fb_info *info; | 1241 | struct fb_info *info; |
| 1220 | struct fbcon_ops *ops; | 1242 | struct fbcon_ops *ops; |
| 1221 | int idx; | 1243 | int idx; |
| @@ -1288,7 +1310,7 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, · 66 unmodified lines | |||
| 1288 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1310 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1289 | struct fbcon_ops *ops = info->fbcon_par; | 1311 | struct fbcon_ops *ops = info->fbcon_par; |
| 1290 | 1312 | ||
| 1291 | struct display *p = &fb_display[vc->vc_num]; | 1313 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1292 | u_int y_break; | 1314 | u_int y_break; |
| 1293 | 1315 | ||
| 1294 | if (fbcon_is_inactive(vc, info)) | 1316 | if (fbcon_is_inactive(vc, info)) |
| @@ -1324,7 +1346,7 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, · 29 unmodified lines | |||
| 1324 | int count, int ypos, int xpos) | 1346 | int count, int ypos, int xpos) |
| 1325 | { | 1347 | { |
| 1326 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1348 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1327 | struct display *p = &fb_display[vc->vc_num]; | 1349 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1328 | struct fbcon_ops *ops = info->fbcon_par; | 1350 | struct fbcon_ops *ops = info->fbcon_par; |
| 1329 | 1351 | ||
| 1330 | if (!fbcon_is_inactive(vc, info)) | 1352 | if (!fbcon_is_inactive(vc, info)) |
| @@ -1388,7 +1410,7 @@ static int scrollback_current = 0; · 57 unmodified lines | |||
| 1388 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | 1410 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
| 1389 | int unit) | 1411 | int unit) |
| 1390 | { | 1412 | { |
| 1391 | struct display *p, *t; | 1413 | struct fbcon_display *p, *t; |
| 1392 | struct vc_data **default_mode, *vc; | 1414 | struct vc_data **default_mode, *vc; |
| 1393 | struct vc_data *svc; | 1415 | struct vc_data *svc; |
| 1394 | struct fbcon_ops *ops = info->fbcon_par; | 1416 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -1457,7 +1479,7 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) · 62 unmodified lines | |||
| 1457 | { | 1479 | { |
| 1458 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1480 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1459 | struct fbcon_ops *ops = info->fbcon_par; | 1481 | struct fbcon_ops *ops = info->fbcon_par; |
| 1460 | struct display *p = &fb_display[vc->vc_num]; | 1482 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1461 | 1483 | ||
| 1462 | p->yscroll += count; | 1484 | p->yscroll += count; |
| 1463 | if (p->yscroll >= p->vrows) /* Deal with wrap */ | 1485 | if (p->yscroll >= p->vrows) /* Deal with wrap */ |
| @@ -1476,7 +1498,7 @@ static __inline__ void ywrap_down(struct vc_data *vc, int count) · 12 unmodified lines | |||
| 1476 | { | 1498 | { |
| 1477 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1499 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1478 | struct fbcon_ops *ops = info->fbcon_par; | 1500 | struct fbcon_ops *ops = info->fbcon_par; |
| 1479 | struct display *p = &fb_display[vc->vc_num]; | 1501 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1480 | 1502 | ||
| 1481 | p->yscroll -= count; | 1503 | p->yscroll -= count; |
| 1482 | if (p->yscroll < 0) /* Deal with wrap */ | 1504 | if (p->yscroll < 0) /* Deal with wrap */ |
| @@ -1494,7 +1516,7 @@ static __inline__ void ywrap_down(struct vc_data *vc, int count) · 11 unmodified lines | |||
| 1494 | static __inline__ void ypan_up(struct vc_data *vc, int count) | 1516 | static __inline__ void ypan_up(struct vc_data *vc, int count) |
| 1495 | { | 1517 | { |
| 1496 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1518 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1497 | struct display *p = &fb_display[vc->vc_num]; | 1519 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1498 | struct fbcon_ops *ops = info->fbcon_par; | 1520 | struct fbcon_ops *ops = info->fbcon_par; |
| 1499 | 1521 | ||
| 1500 | p->yscroll += count; | 1522 | p->yscroll += count; |
| @@ -1519,7 +1541,7 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) · 18 unmodified lines | |||
| 1519 | { | 1541 | { |
| 1520 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1542 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1521 | struct fbcon_ops *ops = info->fbcon_par; | 1543 | struct fbcon_ops *ops = info->fbcon_par; |
| 1522 | struct display *p = &fb_display[vc->vc_num]; | 1544 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1523 | 1545 | ||
| 1524 | p->yscroll += count; | 1546 | p->yscroll += count; |
| 1525 | 1547 | ||
| @@ -1542,7 +1564,7 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) · 16 unmodified lines | |||
| 1542 | static __inline__ void ypan_down(struct vc_data *vc, int count) | 1564 | static __inline__ void ypan_down(struct vc_data *vc, int count) |
| 1543 | { | 1565 | { |
| 1544 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1566 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1545 | struct display *p = &fb_display[vc->vc_num]; | 1567 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1546 | struct fbcon_ops *ops = info->fbcon_par; | 1568 | struct fbcon_ops *ops = info->fbcon_par; |
| 1547 | 1569 | ||
| 1548 | p->yscroll -= count; | 1570 | p->yscroll -= count; |
| @@ -1567,7 +1589,7 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) · 18 unmodified lines | |||
| 1567 | { | 1589 | { |
| 1568 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1590 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1569 | struct fbcon_ops *ops = info->fbcon_par; | 1591 | struct fbcon_ops *ops = info->fbcon_par; |
| 1570 | struct display *p = &fb_display[vc->vc_num]; | 1592 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1571 | 1593 | ||
| 1572 | p->yscroll -= count; | 1594 | p->yscroll -= count; |
| 1573 | 1595 | ||
| @@ -1587,7 +1609,7 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) · 13 unmodified lines | |||
| 1587 | scrollback_current = 0; | 1609 | scrollback_current = 0; |
| 1588 | } | 1610 | } |
| 1589 | 1611 | ||
| 1590 | static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, | 1612 | static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p, |
| 1591 | long delta) | 1613 | long delta) |
| 1592 | { | 1614 | { |
| 1593 | int count = vc->vc_rows; | 1615 | int count = vc->vc_rows; |
| @@ -1680,7 +1702,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, · 86 unmodified lines | |||
| 1680 | } | 1702 | } |
| 1681 | } | 1703 | } |
| 1682 | 1704 | ||
| 1683 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, | 1705 | static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, |
| 1684 | int line, int count, int dy) | 1706 | int line, int count, int dy) |
| 1685 | { | 1707 | { |
| 1686 | unsigned short *s = (unsigned short *) | 1708 | unsigned short *s = (unsigned short *) |
| @@ -1715,7 +1737,7 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p, · 28 unmodified lines | |||
| 1715 | } | 1737 | } |
| 1716 | 1738 | ||
| 1717 | static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, | 1739 | static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, |
| 1718 | struct display *p, int line, int count, int ycount) | 1740 | struct fbcon_display *p, int line, int count, int ycount) |
| 1719 | { | 1741 | { |
| 1720 | int offset = ycount * vc->vc_cols; | 1742 | int offset = ycount * vc->vc_cols; |
| 1721 | unsigned short *d = (unsigned short *) | 1743 | unsigned short *d = (unsigned short *) |
| @@ -1764,7 +1786,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, · 42 unmodified lines | |||
| 1764 | } | 1786 | } |
| 1765 | } | 1787 | } |
| 1766 | 1788 | ||
| 1767 | static void fbcon_redraw(struct vc_data *vc, struct display *p, | 1789 | static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, |
| 1768 | int line, int count, int offset) | 1790 | int line, int count, int offset) |
| 1769 | { | 1791 | { |
| 1770 | unsigned short *d = (unsigned short *) | 1792 | unsigned short *d = (unsigned short *) |
| @@ -1848,7 +1870,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 77 unmodified lines | |||
| 1848 | enum con_scroll dir, unsigned int count) | 1870 | enum con_scroll dir, unsigned int count) |
| 1849 | { | 1871 | { |
| 1850 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 1872 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 1851 | struct display *p = &fb_display[vc->vc_num]; | 1873 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 1852 | int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; | 1874 | int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; |
| 1853 | 1875 | ||
| 1854 | if (fbcon_is_inactive(vc, info)) | 1876 | if (fbcon_is_inactive(vc, info)) |
| @@ -2052,7 +2074,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, · 197 unmodified lines | |||
| 2052 | int height, int width) | 2074 | int height, int width) |
| 2053 | { | 2075 | { |
| 2054 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2076 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 2055 | struct display *p = &fb_display[vc->vc_num]; | 2077 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 2056 | 2078 | ||
| 2057 | if (fbcon_is_inactive(vc, info)) | 2079 | if (fbcon_is_inactive(vc, info)) |
| 2058 | return; | 2080 | return; |
| @@ -2071,7 +2093,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, · 12 unmodified lines | |||
| 2071 | p->vrows - p->yscroll); | 2093 | p->vrows - p->yscroll); |
| 2072 | } | 2094 | } |
| 2073 | 2095 | ||
| 2074 | static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, | 2096 | static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, |
| 2075 | int dy, int dx, int height, int width, u_int y_break) | 2097 | int dy, int dx, int height, int width, u_int y_break) |
| 2076 | { | 2098 | { |
| 2077 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2099 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| @@ -2113,7 +2135,7 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s · 35 unmodified lines | |||
| 2113 | height, width); | 2135 | height, width); |
| 2114 | } | 2136 | } |
| 2115 | 2137 | ||
| 2116 | static void updatescrollmode(struct display *p, | 2138 | static void updatescrollmode(struct fbcon_display *p, |
| 2117 | struct fb_info *info, | 2139 | struct fb_info *info, |
| 2118 | struct vc_data *vc) | 2140 | struct vc_data *vc) |
| 2119 | { | 2141 | { |
| @@ -2165,7 +2187,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, · 45 unmodified lines | |||
| 2165 | { | 2187 | { |
| 2166 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2188 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 2167 | struct fbcon_ops *ops = info->fbcon_par; | 2189 | struct fbcon_ops *ops = info->fbcon_par; |
| 2168 | struct display *p = &fb_display[vc->vc_num]; | 2190 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 2169 | struct fb_var_screeninfo var = info->var; | 2191 | struct fb_var_screeninfo var = info->var; |
| 2170 | int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; | 2192 | int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; |
| 2171 | 2193 | ||
| @@ -2210,7 +2232,7 @@ static int fbcon_switch(struct vc_data *vc) · 38 unmodified lines | |||
| 2210 | { | 2232 | { |
| 2211 | struct fb_info *info, *old_info = NULL; | 2233 | struct fb_info *info, *old_info = NULL; |
| 2212 | struct fbcon_ops *ops; | 2234 | struct fbcon_ops *ops; |
| 2213 | struct display *p = &fb_display[vc->vc_num]; | 2235 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 2214 | struct fb_var_screeninfo var; | 2236 | struct fb_var_screeninfo var; |
| 2215 | int i, ret, prev_console, charcnt = 256; | 2237 | int i, ret, prev_console, charcnt = 256; |
| 2216 | 2238 | ||
| @@ -2348,8 +2370,6 @@ static int fbcon_switch(struct vc_data *vc) · 131 unmodified lines | |||
| 2348 | static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, | 2370 | static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, |
| 2349 | int blank) | 2371 | int blank) |
| 2350 | { | 2372 | { |
| 2351 | struct fb_event event; | ||
| 2352 | |||
| 2353 | if (blank) { | 2373 | if (blank) { |
| 2354 | unsigned short charmask = vc->vc_hi_font_mask ? | 2374 | unsigned short charmask = vc->vc_hi_font_mask ? |
| 2355 | 0x1ff : 0xff; | 2375 | 0x1ff : 0xff; |
| @@ -2360,14 +2380,6 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, · 4 unmodified lines | |||
| 2360 | fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); | 2380 | fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); |
| 2361 | vc->vc_video_erase_char = oldc; | 2381 | vc->vc_video_erase_char = oldc; |
| 2362 | } | 2382 | } |
| 2363 | |||
| 2364 | |||
| 2365 | if (!lock_fb_info(info)) | ||
| 2366 | return; | ||
| 2367 | event.info = info; | ||
| 2368 | event.data = ␣ | ||
| 2369 | fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); | ||
| 2370 | unlock_fb_info(info); | ||
| 2371 | } | 2383 | } |
| 2372 | 2384 | ||
| 2373 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) | 2385 | static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) |
| @@ -2394,9 +2406,8 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) · 20 unmodified lines | |||
| 2394 | fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); | 2406 | fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); |
| 2395 | ops->cursor_flash = (!blank); | 2407 | ops->cursor_flash = (!blank); |
| 2396 | 2408 | ||
| 2397 | if (!(info->flags & FBINFO_MISC_USEREVENT)) | 2409 | if (fb_blank(info, blank)) |
| 2398 | if (fb_blank(info, blank)) | 2410 | fbcon_generic_blank(vc, info, blank); |
| 2399 | fbcon_generic_blank(vc, info, blank); | ||
| 2400 | } | 2411 | } |
| 2401 | 2412 | ||
| 2402 | if (!blank) | 2413 | if (!blank) |
| @@ -2553,7 +2564,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, · 150 unmodified lines | |||
| 2553 | { | 2564 | { |
| 2554 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2565 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 2555 | struct fbcon_ops *ops = info->fbcon_par; | 2566 | struct fbcon_ops *ops = info->fbcon_par; |
| 2556 | struct display *p = &fb_display[vc->vc_num]; | 2567 | struct fbcon_display *p = &fb_display[vc->vc_num]; |
| 2557 | int resize; | 2568 | int resize; |
| 2558 | int cnt; | 2569 | int cnt; |
| 2559 | char *old_data = NULL; | 2570 | char *old_data = NULL; |
| @@ -2601,7 +2612,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, · 41 unmodified lines | |||
| 2601 | 2612 | ||
| 2602 | static int fbcon_copy_font(struct vc_data *vc, int con) | 2613 | static int fbcon_copy_font(struct vc_data *vc, int con) |
| 2603 | { | 2614 | { |
| 2604 | struct display *od = &fb_display[con]; | 2615 | struct fbcon_display *od = &fb_display[con]; |
| 2605 | struct console_font *f = &vc->vc_font; | 2616 | struct console_font *f = &vc->vc_font; |
| 2606 | 2617 | ||
| 2607 | if (od->fontdata == f->data) | 2618 | if (od->fontdata == f->data) |
| @@ -2826,7 +2837,7 @@ static void fbcon_scrolldelta(struct vc_data *vc, int lines) · 218 unmodified lines | |||
| 2826 | { | 2837 | { |
| 2827 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; | 2838 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; |
| 2828 | struct fbcon_ops *ops = info->fbcon_par; | 2839 | struct fbcon_ops *ops = info->fbcon_par; |
| 2829 | struct display *disp = &fb_display[fg_console]; | 2840 | struct fbcon_display *disp = &fb_display[fg_console]; |
| 2830 | int offset, limit, scrollback_old; | 2841 | int offset, limit, scrollback_old; |
| 2831 | 2842 | ||
| 2832 | if (softback_top) { | 2843 | if (softback_top) { |
| @@ -2918,7 +2929,7 @@ static int fbcon_set_origin(struct vc_data *vc) · 85 unmodified lines | |||
| 2918 | return 0; | 2929 | return 0; |
| 2919 | } | 2930 | } |
| 2920 | 2931 | ||
| 2921 | static void fbcon_suspended(struct fb_info *info) | 2932 | void fbcon_suspended(struct fb_info *info) |
| 2922 | { | 2933 | { |
| 2923 | struct vc_data *vc = NULL; | 2934 | struct vc_data *vc = NULL; |
| 2924 | struct fbcon_ops *ops = info->fbcon_par; | 2935 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2931,7 +2942,7 @@ static void fbcon_suspended(struct fb_info *info) · 6 unmodified lines | |||
| 2931 | fbcon_cursor(vc, CM_ERASE); | 2942 | fbcon_cursor(vc, CM_ERASE); |
| 2932 | } | 2943 | } |
| 2933 | 2944 | ||
| 2934 | static void fbcon_resumed(struct fb_info *info) | 2945 | void fbcon_resumed(struct fb_info *info) |
| 2935 | { | 2946 | { |
| 2936 | struct vc_data *vc; | 2947 | struct vc_data *vc; |
| 2937 | struct fbcon_ops *ops = info->fbcon_par; | 2948 | struct fbcon_ops *ops = info->fbcon_par; |
| @@ -2947,7 +2958,7 @@ static void fbcon_modechanged(struct fb_info *info) · 9 unmodified lines | |||
| 2947 | { | 2958 | { |
| 2948 | struct fbcon_ops *ops = info->fbcon_par; | 2959 | struct fbcon_ops *ops = info->fbcon_par; |
| 2949 | struct vc_data *vc; | 2960 | struct vc_data *vc; |
| 2950 | struct display *p; | 2961 | struct fbcon_display *p; |
| 2951 | int rows, cols; | 2962 | int rows, cols; |
| 2952 | 2963 | ||
| 2953 | if (!ops || ops->currcon < 0) | 2964 | if (!ops || ops->currcon < 0) |
| @@ -2987,7 +2998,7 @@ static void fbcon_set_all_vcs(struct fb_info *info) · 33 unmodified lines | |||
| 2987 | { | 2998 | { |
| 2988 | struct fbcon_ops *ops = info->fbcon_par; | 2999 | struct fbcon_ops *ops = info->fbcon_par; |
| 2989 | struct vc_data *vc; | 3000 | struct vc_data *vc; |
| 2990 | struct display *p; | 3001 | struct fbcon_display *p; |
| 2991 | int i, rows, cols, fg = -1; | 3002 | int i, rows, cols, fg = -1; |
| 2992 | 3003 | ||
| 2993 | if (!ops || ops->currcon < 0) | 3004 | if (!ops || ops->currcon < 0) |
| @@ -3018,11 +3029,21 @@ static void fbcon_set_all_vcs(struct fb_info *info) · 24 unmodified lines | |||
| 3018 | fbcon_modechanged(info); | 3029 | fbcon_modechanged(info); |
| 3019 | } | 3030 | } |
| 3020 | 3031 | ||
| 3021 | static int fbcon_mode_deleted(struct fb_info *info, | 3032 | |
| 3022 | struct fb_videomode *mode) | 3033 | void fbcon_update_vcs(struct fb_info *info, bool all) |
| 3034 | { | ||
| 3035 | if (all) | ||
| 3036 | fbcon_set_all_vcs(info); | ||
| 3037 | else | ||
| 3038 | fbcon_modechanged(info); | ||
| 3039 | } | ||
| 3040 | EXPORT_SYMBOL(fbcon_update_vcs); | ||
| 3041 | |||
| 3042 | int fbcon_mode_deleted(struct fb_info *info, | ||
| 3043 | struct fb_videomode *mode) | ||
| 3023 | { | 3044 | { |
| 3024 | struct fb_info *fb_info; | 3045 | struct fb_info *fb_info; |
| 3025 | struct display *p; | 3046 | struct fbcon_display *p; |
| 3026 | int i, j, found = 0; | 3047 | int i, j, found = 0; |
| 3027 | 3048 | ||
| 3028 | /* before deletion, ensure that mode is not in use */ | 3049 | /* before deletion, ensure that mode is not in use */ |
| @@ -3045,7 +3066,7 @@ static int fbcon_mode_deleted(struct fb_info *info, · 16 unmodified lines | |||
| 3045 | } | 3066 | } |
| 3046 | 3067 | ||
| 3047 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING | 3068 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING |
| 3048 | static int fbcon_unbind(void) | 3069 | static void fbcon_unbind(void) |
| 3049 | { | 3070 | { |
| 3050 | int ret; | 3071 | int ret; |
| 3051 | 3072 | ||
| @@ -3054,25 +3075,21 @@ static int fbcon_unbind(void) · 2 unmodified lines | |||
| 3054 | 3075 | ||
| 3055 | if (!ret) | 3076 | if (!ret) |
| 3056 | fbcon_has_console_bind = 0; | 3077 | fbcon_has_console_bind = 0; |
| 3057 | |||
| 3058 | return ret; | ||
| 3059 | } | 3078 | } |
| 3060 | #else | 3079 | #else |
| 3061 | static inline int fbcon_unbind(void) | 3080 | static inline void fbcon_unbind(void) {} |
| 3062 | { | ||
| 3063 | return -EINVAL; | ||
| 3064 | } | ||
| 3065 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ | 3081 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ |
| 3066 | 3082 | ||
| 3067 | /* called with console_lock held */ | 3083 | /* called with console_lock held */ |
| 3068 | static int fbcon_fb_unbind(int idx) | 3084 | void fbcon_fb_unbind(struct fb_info *info) |
| 3069 | { | 3085 | { |
| 3070 | int i, new_idx = -1, ret = 0; | 3086 | int i, new_idx = -1, ret = 0; |
| 3087 | int idx = info->node; | ||
| 3071 | 3088 | ||
| 3072 | WARN_CONSOLE_UNLOCKED(); | 3089 | WARN_CONSOLE_UNLOCKED(); |
| 3073 | 3090 | ||
| 3074 | if (!fbcon_has_console_bind) | 3091 | if (!fbcon_has_console_bind) |
| 3075 | return 0; | 3092 | return; |
| 3076 | 3093 | ||
| 3077 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3094 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
| 3078 | if (con2fb_map[i] != idx && | 3095 | if (con2fb_map[i] != idx && |
| @@ -3105,26 +3122,24 @@ static int fbcon_fb_unbind(int idx) · 26 unmodified lines | |||
| 3105 | idx, 0); | 3122 | idx, 0); |
| 3106 | if (ret) { | 3123 | if (ret) { |
| 3107 | con2fb_map[i] = idx; | 3124 | con2fb_map[i] = idx; |
| 3108 | return ret; | 3125 | return; |
| 3109 | } | 3126 | } |
| 3110 | } | 3127 | } |
| 3111 | } | 3128 | } |
| 3112 | } | 3129 | } |
| 3113 | ret = fbcon_unbind(); | 3130 | fbcon_unbind(); |
| 3114 | } | 3131 | } |
| 3115 | |||
| 3116 | return ret; | ||
| 3117 | } | 3132 | } |
| 3118 | 3133 | ||
| 3119 | /* called with console_lock held */ | 3134 | /* called with console_lock held */ |
| 3120 | static int fbcon_fb_unregistered(struct fb_info *info) | 3135 | void fbcon_fb_unregistered(struct fb_info *info) |
| 3121 | { | 3136 | { |
| 3122 | int i, idx; | 3137 | int i, idx; |
| 3123 | 3138 | ||
| 3124 | WARN_CONSOLE_UNLOCKED(); | 3139 | WARN_CONSOLE_UNLOCKED(); |
| 3125 | 3140 | ||
| 3126 | if (deferred_takeover) | 3141 | if (deferred_takeover) |
| 3127 | return 0; | 3142 | return; |
| 3128 | 3143 | ||
| 3129 | idx = info->node; | 3144 | idx = info->node; |
| 3130 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3145 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
| @@ -3153,21 +3168,18 @@ static int fbcon_fb_unregistered(struct fb_info *info) · 22 unmodified lines | |||
| 3153 | 3168 | ||
| 3154 | if (!num_registered_fb) | 3169 | if (!num_registered_fb) |
| 3155 | do_unregister_con_driver(&fb_con); | 3170 | do_unregister_con_driver(&fb_con); |
| 3156 | |||
| 3157 | return 0; | ||
| 3158 | } | 3171 | } |
| 3159 | 3172 | ||
| 3160 | /* called with console_lock held */ | 3173 | void fbcon_remap_all(struct fb_info *info) |
| 3161 | static void fbcon_remap_all(int idx) | ||
| 3162 | { | 3174 | { |
| 3163 | int i; | 3175 | int i, idx = info->node; |
| 3164 | |||
| 3165 | WARN_CONSOLE_UNLOCKED(); | ||
| 3166 | 3176 | ||
| 3177 | console_lock(); | ||
| 3167 | if (deferred_takeover) { | 3178 | if (deferred_takeover) { |
| 3168 | for (i = first_fb_vc; i <= last_fb_vc; i++) | 3179 | for (i = first_fb_vc; i <= last_fb_vc; i++) |
| 3169 | con2fb_map_boot[i] = idx; | 3180 | con2fb_map_boot[i] = idx; |
| 3170 | fbcon_map_override(); | 3181 | fbcon_map_override(); |
| 3182 | console_unlock(); | ||
| 3171 | return; | 3183 | return; |
| 3172 | } | 3184 | } |
| 3173 | 3185 | ||
| @@ -3180,6 +3192,7 @@ static void fbcon_remap_all(int idx) · 6 unmodified lines | |||
| 3180 | first_fb_vc + 1, last_fb_vc + 1); | 3192 | first_fb_vc + 1, last_fb_vc + 1); |
| 3181 | info_idx = idx; | 3193 | info_idx = idx; |
| 3182 | } | 3194 | } |
| 3195 | console_unlock(); | ||
| 3183 | } | 3196 | } |
| 3184 | 3197 | ||
| 3185 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY | 3198 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY |
| @@ -3213,7 +3226,7 @@ static inline void fbcon_select_primary(struct fb_info *info) · 27 unmodified lines | |||
| 3213 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ | 3226 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ |
| 3214 | 3227 | ||
| 3215 | /* called with console_lock held */ | 3228 | /* called with console_lock held */ |
| 3216 | static int fbcon_fb_registered(struct fb_info *info) | 3229 | int fbcon_fb_registered(struct fb_info *info) |
| 3217 | { | 3230 | { |
| 3218 | int ret = 0, i, idx; | 3231 | int ret = 0, i, idx; |
| 3219 | 3232 | ||
| @@ -3247,7 +3260,7 @@ static int fbcon_fb_registered(struct fb_info *info) · 27 unmodified lines | |||
| 3247 | return ret; | 3260 | return ret; |
| 3248 | } | 3261 | } |
| 3249 | 3262 | ||
| 3250 | static void fbcon_fb_blanked(struct fb_info *info, int blank) | 3263 | void fbcon_fb_blanked(struct fb_info *info, int blank) |
| 3251 | { | 3264 | { |
| 3252 | struct fbcon_ops *ops = info->fbcon_par; | 3265 | struct fbcon_ops *ops = info->fbcon_par; |
| 3253 | struct vc_data *vc; | 3266 | struct vc_data *vc; |
| @@ -3269,7 +3282,7 @@ static void fbcon_fb_blanked(struct fb_info *info, int blank) · 15 unmodified lines | |||
| 3269 | ops->blank_state = blank; | 3282 | ops->blank_state = blank; |
| 3270 | } | 3283 | } |
| 3271 | 3284 | ||
| 3272 | static void fbcon_new_modelist(struct fb_info *info) | 3285 | void fbcon_new_modelist(struct fb_info *info) |
| 3273 | { | 3286 | { |
| 3274 | int i; | 3287 | int i; |
| 3275 | struct vc_data *vc; | 3288 | struct vc_data *vc; |
| @@ -3290,11 +3303,11 @@ static void fbcon_new_modelist(struct fb_info *info) · 14 unmodified lines | |||
| 3290 | } | 3303 | } |
| 3291 | } | 3304 | } |
| 3292 | 3305 | ||
| 3293 | static void fbcon_get_requirement(struct fb_info *info, | 3306 | void fbcon_get_requirement(struct fb_info *info, |
| 3294 | struct fb_blit_caps *caps) | 3307 | struct fb_blit_caps *caps) |
| 3295 | { | 3308 | { |
| 3296 | struct vc_data *vc; | 3309 | struct vc_data *vc; |
| 3297 | struct display *p; | 3310 | struct fbcon_display *p; |
| 3298 | 3311 | ||
| 3299 | if (caps->flags) { | 3312 | if (caps->flags) { |
| 3300 | int i, charcnt; | 3313 | int i, charcnt; |
| @@ -3326,80 +3339,47 @@ static void fbcon_get_requirement(struct fb_info *info, · 25 unmodified lines | |||
| 3326 | } | 3339 | } |
| 3327 | } | 3340 | } |
| 3328 | 3341 | ||
| 3329 | static int fbcon_event_notify(struct notifier_block *self, | 3342 | int fbcon_set_con2fb_map_ioctl(void __user *argp) |
| 3330 | unsigned long action, void *data) | ||
| 3331 | { | 3343 | { |
| 3332 | struct fb_event *event = data; | 3344 | struct fb_con2fbmap con2fb; |
| 3333 | struct fb_info *info = event->info; | 3345 | int ret; |
| 3334 | struct fb_videomode *mode; | ||
| 3335 | struct fb_con2fbmap *con2fb; | ||
| 3336 | struct fb_blit_caps *caps; | ||
| 3337 | int idx, ret = 0; | ||
| 3338 | |||
| 3339 | /* | ||
| 3340 | * ignore all events except driver registration and deregistration | ||
| 3341 | * if fbcon is not active | ||
| 3342 | */ | ||
| 3343 | if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED || | ||
| 3344 | action == FB_EVENT_FB_UNREGISTERED)) | ||
| 3345 | goto done; | ||
| 3346 | 3346 | ||
| 3347 | switch(action) { | 3347 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
| 3348 | case FB_EVENT_SUSPEND: | 3348 | return -EFAULT; |
| 3349 | fbcon_suspended(info); | 3349 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
| 3350 | break; | 3350 | return -EINVAL; |
| 3351 | case FB_EVENT_RESUME: | 3351 | if (con2fb.framebuffer >= FB_MAX) |
| 3352 | fbcon_resumed(info); | 3352 | return -EINVAL; |
| 3353 | break; | 3353 | if (!registered_fb[con2fb.framebuffer]) |
| 3354 | case FB_EVENT_MODE_CHANGE: | 3354 | request_module("fb%d", con2fb.framebuffer); |
| 3355 | fbcon_modechanged(info); | 3355 | if (!registered_fb[con2fb.framebuffer]) { |
| 3356 | break; | 3356 | return -EINVAL; |
| 3357 | case FB_EVENT_MODE_CHANGE_ALL: | ||
| 3358 | fbcon_set_all_vcs(info); | ||
| 3359 | break; | ||
| 3360 | case FB_EVENT_MODE_DELETE: | ||
| 3361 | mode = event->data; | ||
| 3362 | ret = fbcon_mode_deleted(info, mode); | ||
| 3363 | break; | ||
| 3364 | case FB_EVENT_FB_UNBIND: | ||
| 3365 | idx = info->node; | ||
| 3366 | ret = fbcon_fb_unbind(idx); | ||
| 3367 | break; | ||
| 3368 | case FB_EVENT_FB_REGISTERED: | ||
| 3369 | ret = fbcon_fb_registered(info); | ||
| 3370 | break; | ||
| 3371 | case FB_EVENT_FB_UNREGISTERED: | ||
| 3372 | ret = fbcon_fb_unregistered(info); | ||
| 3373 | break; | ||
| 3374 | case FB_EVENT_SET_CONSOLE_MAP: | ||
| 3375 | /* called with console lock held */ | ||
| 3376 | con2fb = event->data; | ||
| 3377 | ret = set_con2fb_map(con2fb->console - 1, | ||
| 3378 | con2fb->framebuffer, 1); | ||
| 3379 | break; | ||
| 3380 | case FB_EVENT_GET_CONSOLE_MAP: | ||
| 3381 | con2fb = event->data; | ||
| 3382 | con2fb->framebuffer = con2fb_map[con2fb->console - 1]; | ||
| 3383 | break; | ||
| 3384 | case FB_EVENT_BLANK: | ||
| 3385 | fbcon_fb_blanked(info, *(int *)event->data); | ||
| 3386 | break; | ||
| 3387 | case FB_EVENT_NEW_MODELIST: | ||
| 3388 | fbcon_new_modelist(info); | ||
| 3389 | break; | ||
| 3390 | case FB_EVENT_GET_REQ: | ||
| 3391 | caps = event->data; | ||
| 3392 | fbcon_get_requirement(info, caps); | ||
| 3393 | break; | ||
| 3394 | case FB_EVENT_REMAP_ALL_CONSOLE: | ||
| 3395 | idx = info->node; | ||
| 3396 | fbcon_remap_all(idx); | ||
| 3397 | break; | ||
| 3398 | } | 3357 | } |
| 3399 | done: | 3358 | |
| 3359 | console_lock(); | ||
| 3360 | ret = set_con2fb_map(con2fb.console - 1, | ||
| 3361 | con2fb.framebuffer, 1); | ||
| 3362 | console_unlock(); | ||
| 3363 | |||
| 3400 | return ret; | 3364 | return ret; |
| 3401 | } | 3365 | } |
| 3402 | 3366 | ||
| 3367 | int fbcon_get_con2fb_map_ioctl(void __user *argp) | ||
| 3368 | { | ||
| 3369 | struct fb_con2fbmap con2fb; | ||
| 3370 | |||
| 3371 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | ||
| 3372 | return -EFAULT; | ||
| 3373 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | ||
| 3374 | return -EINVAL; | ||
| 3375 | |||
| 3376 | console_lock(); | ||
| 3377 | con2fb.framebuffer = con2fb_map[con2fb.console - 1]; | ||
| 3378 | console_unlock(); | ||
| 3379 | |||
| 3380 | return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | ||
| 3381 | } | ||
| 3382 | |||
| 3403 | /* | 3383 | /* |
| 3404 | * The console `switch' structure for the frame buffer based console | 3384 | * The console `switch' structure for the frame buffer based console |
| 3405 | */ | 3385 | */ |
| @@ -3431,10 +3411,6 @@ static const struct consw fb_con = { · 25 unmodified lines | |||
| 3431 | .con_debug_leave = fbcon_debug_leave, | 3411 | .con_debug_leave = fbcon_debug_leave, |
| 3432 | }; | 3412 | }; |
| 3433 | 3413 | ||
| 3434 | static struct notifier_block fbcon_event_notifier = { | ||
| 3435 | .notifier_call = fbcon_event_notify, | ||
| 3436 | }; | ||
| 3437 | |||
| 3438 | static ssize_t store_rotate(struct device *device, | 3414 | static ssize_t store_rotate(struct device *device, |
| 3439 | struct device_attribute *attr, const char *buf, | 3415 | struct device_attribute *attr, const char *buf, |
| 3440 | size_t count) | 3416 | size_t count) |
| @@ -3443,9 +3419,6 @@ static ssize_t store_rotate(struct device *device, · 2 unmodified lines | |||
| 3443 | int rotate, idx; | 3419 | int rotate, idx; |
| 3444 | char **last = NULL; | 3420 | char **last = NULL; |
| 3445 | 3421 | ||
| 3446 | if (fbcon_has_exited) | ||
| 3447 | return count; | ||
| 3448 | |||
| 3449 | console_lock(); | 3422 | console_lock(); |
| 3450 | idx = con2fb_map[fg_console]; | 3423 | idx = con2fb_map[fg_console]; |
| 3451 | 3424 | ||
| @@ -3468,9 +3441,6 @@ static ssize_t store_rotate_all(struct device *device, · 16 unmodified lines | |||
| 3468 | int rotate, idx; | 3441 | int rotate, idx; |
| 3469 | char **last = NULL; | 3442 | char **last = NULL; |
| 3470 | 3443 | ||
| 3471 | if (fbcon_has_exited) | ||
| 3472 | return count; | ||
| 3473 | |||
| 3474 | console_lock(); | 3444 | console_lock(); |
| 3475 | idx = con2fb_map[fg_console]; | 3445 | idx = con2fb_map[fg_console]; |
| 3476 | 3446 | ||
| @@ -3491,9 +3461,6 @@ static ssize_t show_rotate(struct device *device, · 14 unmodified lines | |||
| 3491 | struct fb_info *info; | 3461 | struct fb_info *info; |
| 3492 | int rotate = 0, idx; | 3462 | int rotate = 0, idx; |
| 3493 | 3463 | ||
| 3494 | if (fbcon_has_exited) | ||
| 3495 | return 0; | ||
| 3496 | |||
| 3497 | console_lock(); | 3464 | console_lock(); |
| 3498 | idx = con2fb_map[fg_console]; | 3465 | idx = con2fb_map[fg_console]; |
| 3499 | 3466 | ||
| @@ -3514,9 +3481,6 @@ static ssize_t show_cursor_blink(struct device *device, · 14 unmodified lines | |||
| 3514 | struct fbcon_ops *ops; | 3481 | struct fbcon_ops *ops; |
| 3515 | int idx, blink = -1; | 3482 | int idx, blink = -1; |
| 3516 | 3483 | ||
| 3517 | if (fbcon_has_exited) | ||
| 3518 | return 0; | ||
| 3519 | |||
| 3520 | console_lock(); | 3484 | console_lock(); |
| 3521 | idx = con2fb_map[fg_console]; | 3485 | idx = con2fb_map[fg_console]; |
| 3522 | 3486 | ||
| @@ -3543,9 +3507,6 @@ static ssize_t store_cursor_blink(struct device *device, · 20 unmodified lines | |||
| 3543 | int blink, idx; | 3507 | int blink, idx; |
| 3544 | char **last = NULL; | 3508 | char **last = NULL; |
| 3545 | 3509 | ||
| 3546 | if (fbcon_has_exited) | ||
| 3547 | return count; | ||
| 3548 | |||
| 3549 | console_lock(); | 3510 | console_lock(); |
| 3550 | idx = con2fb_map[fg_console]; | 3511 | idx = con2fb_map[fg_console]; |
| 3551 | 3512 | ||
| @@ -3668,9 +3629,6 @@ static void fbcon_exit(void) · 116 unmodified lines | |||
| 3668 | struct fb_info *info; | 3629 | struct fb_info *info; |
| 3669 | int i, j, mapped; | 3630 | int i, j, mapped; |
| 3670 | 3631 | ||
| 3671 | if (fbcon_has_exited) | ||
| 3672 | return; | ||
| 3673 | |||
| 3674 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER | 3632 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER |
| 3675 | if (deferred_takeover) { | 3633 | if (deferred_takeover) { |
| 3676 | dummycon_unregister_output_notifier(&fbcon_output_nb); | 3634 | dummycon_unregister_output_notifier(&fbcon_output_nb); |
| @@ -3695,7 +3653,7 @@ static void fbcon_exit(void) · 18 unmodified lines | |||
| 3695 | for (j = first_fb_vc; j <= last_fb_vc; j++) { | 3653 | for (j = first_fb_vc; j <= last_fb_vc; j++) { |
| 3696 | if (con2fb_map[j] == i) { | 3654 | if (con2fb_map[j] == i) { |
| 3697 | mapped = 1; | 3655 | mapped = 1; |
| 3698 | break; | 3656 | con2fb_map[j] = -1; |
| 3699 | } | 3657 | } |
| 3700 | } | 3658 | } |
| 3701 | 3659 | ||
| @@ -3718,8 +3676,6 @@ static void fbcon_exit(void) · 16 unmodified lines | |||
| 3718 | info->queue.func = NULL; | 3676 | info->queue.func = NULL; |
| 3719 | } | 3677 | } |
| 3720 | } | 3678 | } |
| 3721 | |||
| 3722 | fbcon_has_exited = 1; | ||
| 3723 | } | 3679 | } |
| 3724 | 3680 | ||
| 3725 | void __init fb_console_init(void) | 3681 | void __init fb_console_init(void) |
| @@ -3727,7 +3683,6 @@ void __init fb_console_init(void) · 1 unmodified line | |||
| 3727 | int i; | 3683 | int i; |
| 3728 | 3684 | ||
| 3729 | console_lock(); | 3685 | console_lock(); |
| 3730 | fb_register_client(&fbcon_event_notifier); | ||
| 3731 | fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, | 3686 | fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, |
| 3732 | "fbcon"); | 3687 | "fbcon"); |
| 3733 | 3688 | ||
| @@ -3763,7 +3718,6 @@ static void __exit fbcon_deinit_device(void) · 29 unmodified lines | |||
| 3763 | void __exit fb_console_exit(void) | 3718 | void __exit fb_console_exit(void) |
| 3764 | { | 3719 | { |
| 3765 | console_lock(); | 3720 | console_lock(); |
| 3766 | fb_unregister_client(&fbcon_event_notifier); | ||
| 3767 | fbcon_deinit_device(); | 3721 | fbcon_deinit_device(); |
| 3768 | device_destroy(fb_class, MKDEV(0, 0)); | 3722 | device_destroy(fb_class, MKDEV(0, 0)); |
| 3769 | fbcon_exit(); | 3723 | fbcon_exit(); |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | |||
| 25 | * low-level frame buffer device | 25 | * low-level frame buffer device |
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | struct display { | 28 | struct fbcon_display { |
| 29 | /* Filled in by the low-level console driver */ | 29 | /* Filled in by the low-level console driver */ |
| 30 | const u_char *fontdata; | 30 | const u_char *fontdata; |
| 31 | int userfont; /* != 0 if fontdata kmalloc()ed */ | 31 | int userfont; /* != 0 if fontdata kmalloc()ed */ |
| @@ -68,7 +68,7 @@ struct fbcon_ops { · 36 unmodified lines | |||
| 68 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ | 68 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ |
| 69 | struct timer_list cursor_timer; /* Cursor timer */ | 69 | struct timer_list cursor_timer; /* Cursor timer */ |
| 70 | struct fb_cursor cursor_state; | 70 | struct fb_cursor cursor_state; |
| 71 | struct display *p; | 71 | struct fbcon_display *p; |
| 72 | struct fb_info *info; | 72 | struct fb_info *info; |
| 73 | int currcon; /* Current VC. */ | 73 | int currcon; /* Current VC. */ |
| 74 | int cur_blink_jiffies; | 74 | int cur_blink_jiffies; |
| @@ -225,7 +225,7 @@ extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); · 150 unmodified lines | |||
| 225 | #define FBCON_ATTRIBUTE_REVERSE 2 | 225 | #define FBCON_ATTRIBUTE_REVERSE 2 |
| 226 | #define FBCON_ATTRIBUTE_BOLD 4 | 226 | #define FBCON_ATTRIBUTE_BOLD 4 |
| 227 | 227 | ||
| 228 | static inline int real_y(struct display *p, int ypos) | 228 | static inline int real_y(struct fbcon_display *p, int ypos) |
| 229 | { | 229 | { |
| 230 | int rows = p->vrows; | 230 | int rows = p->vrows; |
| 231 | 231 | ||
| @@ -80,17 +80,6 @@ static void put_fb_info(struct fb_info *fb_info) · 79 unmodified lines | |||
| 80 | fb_info->fbops->fb_destroy(fb_info); | 80 | fb_info->fbops->fb_destroy(fb_info); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | int lock_fb_info(struct fb_info *info) | ||
| 84 | { | ||
| 85 | mutex_lock(&info->lock); | ||
| 86 | if (!info->fbops) { | ||
| 87 | mutex_unlock(&info->lock); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | EXPORT_SYMBOL(lock_fb_info); | ||
| 93 | |||
| 94 | /* | 83 | /* |
| 95 | * Helpers | 84 | * Helpers |
| 96 | */ | 85 | */ |
| @@ -943,16 +932,13 @@ EXPORT_SYMBOL(fb_pan_display); · 846 unmodified lines | |||
| 943 | static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, | 932 | static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, |
| 944 | u32 activate) | 933 | u32 activate) |
| 945 | { | 934 | { |
| 946 | struct fb_event event; | ||
| 947 | struct fb_blit_caps caps, fbcaps; | 935 | struct fb_blit_caps caps, fbcaps; |
| 948 | int err = 0; | 936 | int err = 0; |
| 949 | 937 | ||
| 950 | memset(&caps, 0, sizeof(caps)); | 938 | memset(&caps, 0, sizeof(caps)); |
| 951 | memset(&fbcaps, 0, sizeof(fbcaps)); | 939 | memset(&fbcaps, 0, sizeof(fbcaps)); |
| 952 | caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; | 940 | caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; |
| 953 | event.info = info; | 941 | fbcon_get_requirement(info, &caps); |
| 954 | event.data = ∩︀ | ||
| 955 | fb_notifier_call_chain(FB_EVENT_GET_REQ, &event); | ||
| 956 | info->fbops->fb_get_caps(info, &fbcaps, var); | 942 | info->fbops->fb_get_caps(info, &fbcaps, var); |
| 957 | 943 | ||
| 958 | if (((fbcaps.x ^ caps.x) & caps.x) || | 944 | if (((fbcaps.x ^ caps.x) & caps.x) || |
| @@ -968,6 +954,10 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) · 9 unmodified lines | |||
| 968 | { | 954 | { |
| 969 | int flags = info->flags; | 955 | int flags = info->flags; |
| 970 | int ret = 0; | 956 | int ret = 0; |
| 957 | u32 activate; | ||
| 958 | struct fb_var_screeninfo old_var; | ||
| 959 | struct fb_videomode mode; | ||
| 960 | struct fb_event event; | ||
| 971 | 961 | ||
| 972 | if (var->activate & FB_ACTIVATE_INV_MODE) { | 962 | if (var->activate & FB_ACTIVATE_INV_MODE) { |
| 973 | struct fb_videomode mode1, mode2; | 963 | struct fb_videomode mode1, mode2; |
| @@ -977,100 +967,90 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) · 3 unmodified lines | |||
| 977 | /* make sure we don't delete the videomode of current var */ | 967 | /* make sure we don't delete the videomode of current var */ |
| 978 | ret = fb_mode_is_equal(&mode1, &mode2); | 968 | ret = fb_mode_is_equal(&mode1, &mode2); |
| 979 | 969 | ||
| 980 | if (!ret) { | 970 | if (!ret) |
| 981 | struct fb_event event; | 971 | fbcon_mode_deleted(info, &mode1); |
| 982 | |||
| 983 | event.info = info; | ||
| 984 | event.data = &mode1; | ||
| 985 | ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); | ||
| 986 | } | ||
| 987 | 972 | ||
| 988 | if (!ret) | 973 | if (!ret) |
| 989 | fb_delete_videomode(&mode1, &info->modelist); | 974 | fb_delete_videomode(&mode1, &info->modelist); |
| 990 | 975 | ||
| 991 | 976 | ||
| 992 | ret = (ret) ? -EINVAL : 0; | 977 | return ret ? -EINVAL : 0; |
| 993 | goto done; | ||
| 994 | } | 978 | } |
| 995 | 979 | ||
| 996 | if ((var->activate & FB_ACTIVATE_FORCE) || | 980 | if (!(var->activate & FB_ACTIVATE_FORCE) && |
| 997 | memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { | 981 | !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) |
| 998 | u32 activate = var->activate; | 982 | return 0; |
| 999 | 983 | ||
| 1000 | /* When using FOURCC mode, make sure the red, green, blue and | 984 | activate = var->activate; |
| 1001 | * transp fields are set to 0. | ||
| 1002 | */ | ||
| 1003 | if ((info->fix.capabilities & FB_CAP_FOURCC) && | ||
| 1004 | var->grayscale > 1) { | ||
| 1005 | if (var->red.offset || var->green.offset || | ||
| 1006 | var->blue.offset || var->transp.offset || | ||
| 1007 | var->red.length || var->green.length || | ||
| 1008 | var->blue.length || var->transp.length || | ||
| 1009 | var->red.msb_right || var->green.msb_right || | ||
| 1010 | var->blue.msb_right || var->transp.msb_right) | ||
| 1011 | return -EINVAL; | ||
| 1012 | } | ||
| 1013 | 985 | ||
| 1014 | if (!info->fbops->fb_check_var) { | 986 | /* When using FOURCC mode, make sure the red, green, blue and |
| 1015 | *var = info->var; | 987 | * transp fields are set to 0. |
| 1016 | goto done; | 988 | */ |
| 1017 | } | 989 | if ((info->fix.capabilities & FB_CAP_FOURCC) && |
| 990 | var->grayscale > 1) { | ||
| 991 | if (var->red.offset || var->green.offset || | ||
| 992 | var->blue.offset || var->transp.offset || | ||
| 993 | var->red.length || var->green.length || | ||
| 994 | var->blue.length || var->transp.length || | ||
| 995 | var->red.msb_right || var->green.msb_right || | ||
| 996 | var->blue.msb_right || var->transp.msb_right) | ||
| 997 | return -EINVAL; | ||
| 998 | } | ||
| 1018 | 999 | ||
| 1019 | ret = info->fbops->fb_check_var(var, info); | 1000 | if (!info->fbops->fb_check_var) { |
| 1001 | *var = info->var; | ||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1020 | 1004 | ||
| 1021 | if (ret) | 1005 | ret = info->fbops->fb_check_var(var, info); |
| 1022 | goto done; | ||
| 1023 | 1006 | ||
| 1024 | if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { | 1007 | if (ret) |
| 1025 | struct fb_var_screeninfo old_var; | 1008 | return ret; |
| 1026 | struct fb_videomode mode; | ||
| 1027 | 1009 | ||
| 1028 | if (info->fbops->fb_get_caps) { | 1010 | if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) |
| 1029 | ret = fb_check_caps(info, var, activate); | 1011 | return 0; |
| 1030 | 1012 | ||
| 1031 | if (ret) | 1013 | if (info->fbops->fb_get_caps) { |
| 1032 | goto done; | 1014 | ret = fb_check_caps(info, var, activate); |
| 1033 | } | ||
| 1034 | 1015 | ||
| 1035 | old_var = info->var; | 1016 | if (ret) |
| 1036 | info->var = *var; | 1017 | return ret; |
| 1018 | } | ||
| 1037 | 1019 | ||
| 1038 | if (info->fbops->fb_set_par) { | 1020 | old_var = info->var; |
| 1039 | ret = info->fbops->fb_set_par(info); | 1021 | info->var = *var; |
| 1040 | 1022 | ||
| 1041 | if (ret) { | 1023 | if (info->fbops->fb_set_par) { |
| 1042 | info->var = old_var; | 1024 | ret = info->fbops->fb_set_par(info); |
| 1043 | printk(KERN_WARNING "detected " | ||
| 1044 | "fb_set_par error, " | ||
| 1045 | "error code: %d\n", ret); | ||
| 1046 | goto done; | ||
| 1047 | } | ||
| 1048 | } | ||
| 1049 | 1025 | ||
| 1050 | fb_pan_display(info, &info->var); | 1026 | if (ret) { |
| 1051 | fb_set_cmap(&info->cmap, info); | 1027 | info->var = old_var; |
| 1052 | fb_var_to_videomode(&mode, &info->var); | 1028 | printk(KERN_WARNING "detected " |
| 1029 | "fb_set_par error, " | ||
| 1030 | "error code: %d\n", ret); | ||
| 1031 | return ret; | ||
| 1032 | } | ||
| 1033 | } | ||
| 1053 | 1034 | ||
| 1054 | if (info->modelist.prev && info->modelist.next && | 1035 | fb_pan_display(info, &info->var); |
| 1055 | !list_empty(&info->modelist)) | 1036 | fb_set_cmap(&info->cmap, info); |
| 1056 | ret = fb_add_videomode(&mode, &info->modelist); | 1037 | fb_var_to_videomode(&mode, &info->var); |
| 1057 | 1038 | ||
| 1058 | if (!ret && (flags & FBINFO_MISC_USEREVENT)) { | 1039 | if (info->modelist.prev && info->modelist.next && |
| 1059 | struct fb_event event; | 1040 | !list_empty(&info->modelist)) |
| 1060 | int evnt = (activate & FB_ACTIVATE_ALL) ? | 1041 | ret = fb_add_videomode(&mode, &info->modelist); |
| 1061 | FB_EVENT_MODE_CHANGE_ALL : | ||
| 1062 | FB_EVENT_MODE_CHANGE; | ||
| 1063 | 1042 | ||
| 1064 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1043 | if (ret) |
| 1065 | event.info = info; | 1044 | return ret; |
| 1066 | event.data = &mode; | ||
| 1067 | fb_notifier_call_chain(evnt, &event); | ||
| 1068 | } | ||
| 1069 | } | ||
| 1070 | } | ||
| 1071 | 1045 | ||
| 1072 | done: | 1046 | event.info = info; |
| 1073 | return ret; | 1047 | event.data = &mode; |
| 1048 | fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); | ||
| 1049 | |||
| 1050 | if (flags & FBINFO_MISC_USEREVENT) | ||
| 1051 | fbcon_update_vcs(info, activate & FB_ACTIVATE_ALL); | ||
| 1052 | |||
| 1053 | return 0; | ||
| 1074 | } | 1054 | } |
| 1075 | EXPORT_SYMBOL(fb_set_var); | 1055 | EXPORT_SYMBOL(fb_set_var); |
| 1076 | 1056 | ||
| @@ -1112,17 +1092,14 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 35 unmodified lines | |||
| 1112 | struct fb_ops *fb; | 1092 | struct fb_ops *fb; |
| 1113 | struct fb_var_screeninfo var; | 1093 | struct fb_var_screeninfo var; |
| 1114 | struct fb_fix_screeninfo fix; | 1094 | struct fb_fix_screeninfo fix; |
| 1115 | struct fb_con2fbmap con2fb; | ||
| 1116 | struct fb_cmap cmap_from; | 1095 | struct fb_cmap cmap_from; |
| 1117 | struct fb_cmap_user cmap; | 1096 | struct fb_cmap_user cmap; |
| 1118 | struct fb_event event; | ||
| 1119 | void __user *argp = (void __user *)arg; | 1097 | void __user *argp = (void __user *)arg; |
| 1120 | long ret = 0; | 1098 | long ret = 0; |
| 1121 | 1099 | ||
| 1122 | switch (cmd) { | 1100 | switch (cmd) { |
| 1123 | case FBIOGET_VSCREENINFO: | 1101 | case FBIOGET_VSCREENINFO: |
| 1124 | if (!lock_fb_info(info)) | 1102 | lock_fb_info(info); |
| 1125 | return -ENODEV; | ||
| 1126 | var = info->var; | 1103 | var = info->var; |
| 1127 | unlock_fb_info(info); | 1104 | unlock_fb_info(info); |
| 1128 | 1105 | ||
| @@ -1132,10 +1109,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 3 unmodified lines | |||
| 1132 | if (copy_from_user(&var, argp, sizeof(var))) | 1109 | if (copy_from_user(&var, argp, sizeof(var))) |
| 1133 | return -EFAULT; | 1110 | return -EFAULT; |
| 1134 | console_lock(); | 1111 | console_lock(); |
| 1135 | if (!lock_fb_info(info)) { | 1112 | lock_fb_info(info); |
| 1136 | console_unlock(); | ||
| 1137 | return -ENODEV; | ||
| 1138 | } | ||
| 1139 | info->flags |= FBINFO_MISC_USEREVENT; | 1113 | info->flags |= FBINFO_MISC_USEREVENT; |
| 1140 | ret = fb_set_var(info, &var); | 1114 | ret = fb_set_var(info, &var); |
| 1141 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1115 | info->flags &= ~FBINFO_MISC_USEREVENT; |
| @@ -1145,8 +1119,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 3 unmodified lines | |||
| 1145 | ret = -EFAULT; | 1119 | ret = -EFAULT; |
| 1146 | break; | 1120 | break; |
| 1147 | case FBIOGET_FSCREENINFO: | 1121 | case FBIOGET_FSCREENINFO: |
| 1148 | if (!lock_fb_info(info)) | 1122 | lock_fb_info(info); |
| 1149 | return -ENODEV; | ||
| 1150 | fix = info->fix; | 1123 | fix = info->fix; |
| 1151 | if (info->flags & FBINFO_HIDE_SMEM_START) | 1124 | if (info->flags & FBINFO_HIDE_SMEM_START) |
| 1152 | fix.smem_start = 0; | 1125 | fix.smem_start = 0; |
| @@ -1162,8 +1135,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 9 unmodified lines | |||
| 1162 | case FBIOGETCMAP: | 1135 | case FBIOGETCMAP: |
| 1163 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1136 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
| 1164 | return -EFAULT; | 1137 | return -EFAULT; |
| 1165 | if (!lock_fb_info(info)) | 1138 | lock_fb_info(info); |
| 1166 | return -ENODEV; | ||
| 1167 | cmap_from = info->cmap; | 1139 | cmap_from = info->cmap; |
| 1168 | unlock_fb_info(info); | 1140 | unlock_fb_info(info); |
| 1169 | ret = fb_cmap_to_user(&cmap_from, &cmap); | 1141 | ret = fb_cmap_to_user(&cmap_from, &cmap); |
| @@ -1172,10 +1144,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 2 unmodified lines | |||
| 1172 | if (copy_from_user(&var, argp, sizeof(var))) | 1144 | if (copy_from_user(&var, argp, sizeof(var))) |
| 1173 | return -EFAULT; | 1145 | return -EFAULT; |
| 1174 | console_lock(); | 1146 | console_lock(); |
| 1175 | if (!lock_fb_info(info)) { | 1147 | lock_fb_info(info); |
| 1176 | console_unlock(); | ||
| 1177 | return -ENODEV; | ||
| 1178 | } | ||
| 1179 | ret = fb_pan_display(info, &var); | 1148 | ret = fb_pan_display(info, &var); |
| 1180 | unlock_fb_info(info); | 1149 | unlock_fb_info(info); |
| 1181 | console_unlock(); | 1150 | console_unlock(); |
| @@ -1186,58 +1155,22 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, · 4 unmodified lines | |||
| 1186 | ret = -EINVAL; | 1155 | ret = -EINVAL; |
| 1187 | break; | 1156 | break; |
| 1188 | case FBIOGET_CON2FBMAP: | 1157 | case FBIOGET_CON2FBMAP: |
| 1189 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1158 | ret = fbcon_get_con2fb_map_ioctl(argp); |
| 1190 | return -EFAULT; | ||
| 1191 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | ||
| 1192 | return -EINVAL; | ||
| 1193 | con2fb.framebuffer = -1; | ||
| 1194 | event.data = &con2fb; | ||
| 1195 | if (!lock_fb_info(info)) | ||
| 1196 | return -ENODEV; | ||
| 1197 | event.info = info; | ||
| 1198 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); | ||
| 1199 | unlock_fb_info(info); | ||
| 1200 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | ||
| 1201 | break; | 1159 | break; |
| 1202 | case FBIOPUT_CON2FBMAP: | 1160 | case FBIOPUT_CON2FBMAP: |
| 1203 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1161 | ret = fbcon_set_con2fb_map_ioctl(argp); |
| 1204 | return -EFAULT; | ||
| 1205 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | ||
| 1206 | return -EINVAL; | ||
| 1207 | if (con2fb.framebuffer >= FB_MAX) | ||
| 1208 | return -EINVAL; | ||
| 1209 | if (!registered_fb[con2fb.framebuffer]) | ||
| 1210 | request_module("fb%d", con2fb.framebuffer); | ||
| 1211 | if (!registered_fb[con2fb.framebuffer]) { | ||
| 1212 | ret = -EINVAL; | ||
| 1213 | break; | ||
| 1214 | } | ||
| 1215 | event.data = &con2fb; | ||
| 1216 | console_lock(); | ||
| 1217 | if (!lock_fb_info(info)) { | ||
| 1218 | console_unlock(); | ||
| 1219 | return -ENODEV; | ||
| 1220 | } | ||
| 1221 | event.info = info; | ||
| 1222 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); | ||
| 1223 | unlock_fb_info(info); | ||
| 1224 | console_unlock(); | ||
| 1225 | break; | 1162 | break; |
| 1226 | case FBIOBLANK: | 1163 | case FBIOBLANK: |
| 1227 | console_lock(); | 1164 | console_lock(); |
| 1228 | if (!lock_fb_info(info)) { | 1165 | lock_fb_info(info); |
| 1229 | console_unlock(); | ||
| 1230 | return -ENODEV; | ||
| 1231 | } | ||
| 1232 | info->flags |= FBINFO_MISC_USEREVENT; | ||
| 1233 | ret = fb_blank(info, arg); | 1166 | ret = fb_blank(info, arg); |
| 1234 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1167 | /* might again call into fb_blank */ |
| 1168 | fbcon_fb_blanked(info, arg); | ||
| 1235 | unlock_fb_info(info); | 1169 | unlock_fb_info(info); |
| 1236 | console_unlock(); | 1170 | console_unlock(); |
| 1237 | break; | 1171 | break; |
| 1238 | default: | 1172 | default: |
| 1239 | if (!lock_fb_info(info)) | 1173 | lock_fb_info(info); |
| 1240 | return -ENODEV; | ||
| 1241 | fb = info->fbops; | 1174 | fb = info->fbops; |
| 1242 | if (fb->fb_ioctl) | 1175 | if (fb->fb_ioctl) |
| 1243 | ret = fb->fb_ioctl(info, cmd, arg); | 1176 | ret = fb->fb_ioctl(info, cmd, arg); |
| @@ -1357,8 +1290,7 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, · 113 unmodified lines | |||
| 1357 | { | 1290 | { |
| 1358 | struct fb_fix_screeninfo fix; | 1291 | struct fb_fix_screeninfo fix; |
| 1359 | 1292 | ||
| 1360 | if (!lock_fb_info(info)) | 1293 | lock_fb_info(info); |
| 1361 | return -ENODEV; | ||
| 1362 | fix = info->fix; | 1294 | fix = info->fix; |
| 1363 | if (info->flags & FBINFO_HIDE_SMEM_START) | 1295 | if (info->flags & FBINFO_HIDE_SMEM_START) |
| 1364 | fix.smem_start = 0; | 1296 | fix.smem_start = 0; |
| @@ -1418,8 +1350,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) · 53 unmodified lines | |||
| 1418 | if (!info) | 1350 | if (!info) |
| 1419 | return -ENODEV; | 1351 | return -ENODEV; |
| 1420 | fb = info->fbops; | 1352 | fb = info->fbops; |
| 1421 | if (!fb) | ||
| 1422 | return -ENODEV; | ||
| 1423 | mutex_lock(&info->mm_lock); | 1353 | mutex_lock(&info->mm_lock); |
| 1424 | if (fb->fb_mmap) { | 1354 | if (fb->fb_mmap) { |
| 1425 | int res; | 1355 | int res; |
| @@ -1483,7 +1413,7 @@ __releases(&info->lock) · 57 unmodified lines | |||
| 1483 | if (IS_ERR(info)) | 1413 | if (IS_ERR(info)) |
| 1484 | return PTR_ERR(info); | 1414 | return PTR_ERR(info); |
| 1485 | 1415 | ||
| 1486 | mutex_lock(&info->lock); | 1416 | lock_fb_info(info); |
| 1487 | if (!try_module_get(info->fbops->owner)) { | 1417 | if (!try_module_get(info->fbops->owner)) { |
| 1488 | res = -ENODEV; | 1418 | res = -ENODEV; |
| 1489 | goto out; | 1419 | goto out; |
| @@ -1499,7 +1429,7 @@ __releases(&info->lock) · 9 unmodified lines | |||
| 1499 | fb_deferred_io_open(info, inode, file); | 1429 | fb_deferred_io_open(info, inode, file); |
| 1500 | #endif | 1430 | #endif |
| 1501 | out: | 1431 | out: |
| 1502 | mutex_unlock(&info->lock); | 1432 | unlock_fb_info(info); |
| 1503 | if (res) | 1433 | if (res) |
| 1504 | put_fb_info(info); | 1434 | put_fb_info(info); |
| 1505 | return res; | 1435 | return res; |
| @@ -1512,11 +1442,11 @@ __releases(&info->lock) · 6 unmodified lines | |||
| 1512 | { | 1442 | { |
| 1513 | struct fb_info * const info = file->private_data; | 1443 | struct fb_info * const info = file->private_data; |
| 1514 | 1444 | ||
| 1515 | mutex_lock(&info->lock); | 1445 | lock_fb_info(info); |
| 1516 | if (info->fbops->fb_release) | 1446 | if (info->fbops->fb_release) |
| 1517 | info->fbops->fb_release(info,1); | 1447 | info->fbops->fb_release(info,1); |
| 1518 | module_put(info->fbops->owner); | 1448 | module_put(info->fbops->owner); |
| 1519 | mutex_unlock(&info->lock); | 1449 | unlock_fb_info(info); |
| 1520 | put_fb_info(info); | 1450 | put_fb_info(info); |
| 1521 | return 0; | 1451 | return 0; |
| 1522 | } | 1452 | } |
| @@ -1621,13 +1551,13 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, · 98 unmodified lines | |||
| 1621 | return false; | 1551 | return false; |
| 1622 | } | 1552 | } |
| 1623 | 1553 | ||
| 1624 | static int do_unregister_framebuffer(struct fb_info *fb_info); | 1554 | static void do_unregister_framebuffer(struct fb_info *fb_info); |
| 1625 | 1555 | ||
| 1626 | #define VGA_FB_PHYS 0xA0000 | 1556 | #define VGA_FB_PHYS 0xA0000 |
| 1627 | static int do_remove_conflicting_framebuffers(struct apertures_struct *a, | 1557 | static void do_remove_conflicting_framebuffers(struct apertures_struct *a, |
| 1628 | const char *name, bool primary) | 1558 | const char *name, bool primary) |
| 1629 | { | 1559 | { |
| 1630 | int i, ret; | 1560 | int i; |
| 1631 | 1561 | ||
| 1632 | /* check all firmware fbs and kick off if the base addr overlaps */ | 1562 | /* check all firmware fbs and kick off if the base addr overlaps */ |
| 1633 | for_each_registered_fb(i) { | 1563 | for_each_registered_fb(i) { |
| @@ -1643,13 +1573,9 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a, · 9 unmodified lines | |||
| 1643 | 1573 | ||
| 1644 | printk(KERN_INFO "fb%d: switching to %s from %s\n", | 1574 | printk(KERN_INFO "fb%d: switching to %s from %s\n", |
| 1645 | i, name, registered_fb[i]->fix.id); | 1575 | i, name, registered_fb[i]->fix.id); |
| 1646 | ret = do_unregister_framebuffer(registered_fb[i]); | 1576 | do_unregister_framebuffer(registered_fb[i]); |
| 1647 | if (ret) | ||
| 1648 | return ret; | ||
| 1649 | } | 1577 | } |
| 1650 | } | 1578 | } |
| 1651 | |||
| 1652 | return 0; | ||
| 1653 | } | 1579 | } |
| 1654 | 1580 | ||
| 1655 | static bool lockless_register_fb; | 1581 | static bool lockless_register_fb; |
| @@ -1660,17 +1586,14 @@ MODULE_PARM_DESC(lockless_register_fb, · 4 unmodified lines | |||
| 1660 | static int do_register_framebuffer(struct fb_info *fb_info) | 1586 | static int do_register_framebuffer(struct fb_info *fb_info) |
| 1661 | { | 1587 | { |
| 1662 | int i, ret; | 1588 | int i, ret; |
| 1663 | struct fb_event event; | ||
| 1664 | struct fb_videomode mode; | 1589 | struct fb_videomode mode; |
| 1665 | 1590 | ||
| 1666 | if (fb_check_foreignness(fb_info)) | 1591 | if (fb_check_foreignness(fb_info)) |
| 1667 | return -ENOSYS; | 1592 | return -ENOSYS; |
| 1668 | 1593 | ||
| 1669 | ret = do_remove_conflicting_framebuffers(fb_info->apertures, | 1594 | do_remove_conflicting_framebuffers(fb_info->apertures, |
| 1670 | fb_info->fix.id, | 1595 | fb_info->fix.id, |
| 1671 | fb_is_primary_device(fb_info)); | 1596 | fb_is_primary_device(fb_info)); |
| 1672 | if (ret) | ||
| 1673 | return ret; | ||
| 1674 | 1597 | ||
| 1675 | if (num_registered_fb == FB_MAX) | 1598 | if (num_registered_fb == FB_MAX) |
| 1676 | return -ENXIO; | 1599 | return -ENXIO; |
| @@ -1723,20 +1646,22 @@ static int do_register_framebuffer(struct fb_info *fb_info) · 46 unmodified lines | |||
| 1723 | fb_add_videomode(&mode, &fb_info->modelist); | 1646 | fb_add_videomode(&mode, &fb_info->modelist); |
| 1724 | registered_fb[i] = fb_info; | 1647 | registered_fb[i] = fb_info; |
| 1725 | 1648 | ||
| 1726 | event.info = fb_info; | 1649 | #ifdef CONFIG_GUMSTIX_AM200EPD |
| 1650 | { | ||
| 1651 | struct fb_event event; | ||
| 1652 | event.info = fb_info; | ||
| 1653 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); | ||
| 1654 | } | ||
| 1655 | #endif | ||
| 1656 | |||
| 1727 | if (!lockless_register_fb) | 1657 | if (!lockless_register_fb) |
| 1728 | console_lock(); | 1658 | console_lock(); |
| 1729 | else | 1659 | else |
| 1730 | atomic_inc(&ignore_console_lock_warning); | 1660 | atomic_inc(&ignore_console_lock_warning); |
| 1731 | if (!lock_fb_info(fb_info)) { | 1661 | lock_fb_info(fb_info); |
| 1732 | ret = -ENODEV; | 1662 | ret = fbcon_fb_registered(fb_info); |
| 1733 | goto unlock_console; | ||
| 1734 | } | ||
| 1735 | ret = 0; | ||
| 1736 | |||
| 1737 | fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); | ||
| 1738 | unlock_fb_info(fb_info); | 1663 | unlock_fb_info(fb_info); |
| 1739 | unlock_console: | 1664 | |
| 1740 | if (!lockless_register_fb) | 1665 | if (!lockless_register_fb) |
| 1741 | console_unlock(); | 1666 | console_unlock(); |
| 1742 | else | 1667 | else |
| @@ -1744,44 +1669,44 @@ unlock_console: · 1 unmodified line | |||
| 1744 | return ret; | 1669 | return ret; |
| 1745 | } | 1670 | } |
| 1746 | 1671 | ||
| 1747 | static int unbind_console(struct fb_info *fb_info) | 1672 | static void unbind_console(struct fb_info *fb_info) |
| 1748 | { | 1673 | { |
| 1749 | struct fb_event event; | ||
| 1750 | int ret; | ||
| 1751 | int i = fb_info->node; | 1674 | int i = fb_info->node; |
| 1752 | 1675 | ||
| 1753 | if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) | 1676 | if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) |
| 1754 | return -EINVAL; | 1677 | return; |
| 1755 | 1678 | ||
| 1756 | console_lock(); | 1679 | console_lock(); |
| 1757 | if (!lock_fb_info(fb_info)) { | 1680 | lock_fb_info(fb_info); |
| 1758 | console_unlock(); | 1681 | fbcon_fb_unbind(fb_info); |
| 1759 | return -ENODEV; | ||
| 1760 | } | ||
| 1761 | |||
| 1762 | event.info = fb_info; | ||
| 1763 | ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); | ||
| 1764 | unlock_fb_info(fb_info); | 1682 | unlock_fb_info(fb_info); |
| 1765 | console_unlock(); | 1683 | console_unlock(); |
| 1766 | |||
| 1767 | return ret; | ||
| 1768 | } | 1684 | } |
| 1769 | 1685 | ||
| 1770 | static int __unlink_framebuffer(struct fb_info *fb_info); | 1686 | void unlink_framebuffer(struct fb_info *fb_info) |
| 1771 | |||
| 1772 | static int do_unregister_framebuffer(struct fb_info *fb_info) | ||
| 1773 | { | 1687 | { |
| 1774 | struct fb_event event; | 1688 | int i; |
| 1775 | int ret; | 1689 | |
| 1690 | i = fb_info->node; | ||
| 1691 | if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) | ||
| 1692 | return; | ||
| 1776 | 1693 | ||
| 1777 | ret = unbind_console(fb_info); | 1694 | if (!fb_info->dev) |
| 1695 | return; | ||
| 1778 | 1696 | ||
| 1779 | if (ret) | 1697 | device_destroy(fb_class, MKDEV(FB_MAJOR, i)); |
| 1780 | return -EINVAL; | ||
| 1781 | 1698 | ||
| 1782 | pm_vt_switch_unregister(fb_info->dev); | 1699 | pm_vt_switch_unregister(fb_info->dev); |
| 1783 | 1700 | ||
| 1784 | __unlink_framebuffer(fb_info); | 1701 | unbind_console(fb_info); |
| 1702 | |||
| 1703 | fb_info->dev = NULL; | ||
| 1704 | } | ||
| 1705 | EXPORT_SYMBOL(unlink_framebuffer); | ||
| 1706 | |||
| 1707 | static void do_unregister_framebuffer(struct fb_info *fb_info) | ||
| 1708 | { | ||
| 1709 | unlink_framebuffer(fb_info); | ||
| 1785 | if (fb_info->pixmap.addr && | 1710 | if (fb_info->pixmap.addr && |
| 1786 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) | 1711 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) |
| 1787 | kfree(fb_info->pixmap.addr); | 1712 | kfree(fb_info->pixmap.addr); |
| @@ -1789,46 +1714,21 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) · 1 unmodified line | |||
| 1789 | registered_fb[fb_info->node] = NULL; | 1714 | registered_fb[fb_info->node] = NULL; |
| 1790 | num_registered_fb--; | 1715 | num_registered_fb--; |
| 1791 | fb_cleanup_device(fb_info); | 1716 | fb_cleanup_device(fb_info); |
| 1792 | event.info = fb_info; | 1717 | #ifdef CONFIG_GUMSTIX_AM200EPD |
| 1718 | { | ||
| 1719 | struct fb_event event; | ||
| 1720 | event.info = fb_info; | ||
| 1721 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); | ||
| 1722 | } | ||
| 1723 | #endif | ||
| 1793 | console_lock(); | 1724 | console_lock(); |
| 1794 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); | 1725 | fbcon_fb_unregistered(fb_info); |
| 1795 | console_unlock(); | 1726 | console_unlock(); |
| 1796 | 1727 | ||
| 1797 | /* this may free fb info */ | 1728 | /* this may free fb info */ |
| 1798 | put_fb_info(fb_info); | 1729 | put_fb_info(fb_info); |
| 1799 | return 0; | ||
| 1800 | } | 1730 | } |
| 1801 | 1731 | ||
| 1802 | static int __unlink_framebuffer(struct fb_info *fb_info) | ||
| 1803 | { | ||
| 1804 | int i; | ||
| 1805 | |||
| 1806 | i = fb_info->node; | ||
| 1807 | if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) | ||
| 1808 | return -EINVAL; | ||
| 1809 | |||
| 1810 | if (fb_info->dev) { | ||
| 1811 | device_destroy(fb_class, MKDEV(FB_MAJOR, i)); | ||
| 1812 | fb_info->dev = NULL; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | return 0; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | int unlink_framebuffer(struct fb_info *fb_info) | ||
| 1819 | { | ||
| 1820 | int ret; | ||
| 1821 | |||
| 1822 | ret = __unlink_framebuffer(fb_info); | ||
| 1823 | if (ret) | ||
| 1824 | return ret; | ||
| 1825 | |||
| 1826 | unbind_console(fb_info); | ||
| 1827 | |||
| 1828 | return 0; | ||
| 1829 | } | ||
| 1830 | EXPORT_SYMBOL(unlink_framebuffer); | ||
| 1831 | |||
| 1832 | /** | 1732 | /** |
| 1833 | * remove_conflicting_framebuffers - remove firmware-configured framebuffers | 1733 | * remove_conflicting_framebuffers - remove firmware-configured framebuffers |
| 1834 | * @a: memory range, users of which are to be removed | 1734 | * @a: memory range, users of which are to be removed |
| @@ -1842,7 +1742,6 @@ EXPORT_SYMBOL(unlink_framebuffer); · 7 unmodified lines | |||
| 1842 | int remove_conflicting_framebuffers(struct apertures_struct *a, | 1742 | int remove_conflicting_framebuffers(struct apertures_struct *a, |
| 1843 | const char *name, bool primary) | 1743 | const char *name, bool primary) |
| 1844 | { | 1744 | { |
| 1845 | int ret; | ||
| 1846 | bool do_free = false; | 1745 | bool do_free = false; |
| 1847 | 1746 | ||
| 1848 | if (!a) { | 1747 | if (!a) { |
| @@ -1856,13 +1755,13 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, · 7 unmodified lines | |||
| 1856 | } | 1755 | } |
| 1857 | 1756 | ||
| 1858 | mutex_lock(®istration_lock); | 1757 | mutex_lock(®istration_lock); |
| 1859 | ret = do_remove_conflicting_framebuffers(a, name, primary); | 1758 | do_remove_conflicting_framebuffers(a, name, primary); |
| 1860 | mutex_unlock(®istration_lock); | 1759 | mutex_unlock(®istration_lock); |
| 1861 | 1760 | ||
| 1862 | if (do_free) | 1761 | if (do_free) |
| 1863 | kfree(a); | 1762 | kfree(a); |
| 1864 | 1763 | ||
| 1865 | return ret; | 1764 | return 0; |
| 1866 | } | 1765 | } |
| 1867 | EXPORT_SYMBOL(remove_conflicting_framebuffers); | 1766 | EXPORT_SYMBOL(remove_conflicting_framebuffers); |
| 1868 | 1767 | ||
| @@ -1959,16 +1858,12 @@ EXPORT_SYMBOL(register_framebuffer); · 90 unmodified lines | |||
| 1959 | * that the driver implements fb_open() and fb_release() to | 1858 | * that the driver implements fb_open() and fb_release() to |
| 1960 | * check that no processes are using the device. | 1859 | * check that no processes are using the device. |
| 1961 | */ | 1860 | */ |
| 1962 | int | 1861 | void |
| 1963 | unregister_framebuffer(struct fb_info *fb_info) | 1862 | unregister_framebuffer(struct fb_info *fb_info) |
| 1964 | { | 1863 | { |
| 1965 | int ret; | ||
| 1966 | |||
| 1967 | mutex_lock(®istration_lock); | 1864 | mutex_lock(®istration_lock); |
| 1968 | ret = do_unregister_framebuffer(fb_info); | 1865 | do_unregister_framebuffer(fb_info); |
| 1969 | mutex_unlock(®istration_lock); | 1866 | mutex_unlock(®istration_lock); |
| 1970 | |||
| 1971 | return ret; | ||
| 1972 | } | 1867 | } |
| 1973 | EXPORT_SYMBOL(unregister_framebuffer); | 1868 | EXPORT_SYMBOL(unregister_framebuffer); |
| 1974 | 1869 | ||
| @@ -1983,15 +1878,14 @@ EXPORT_SYMBOL(unregister_framebuffer); · 8 unmodified lines | |||
| 1983 | */ | 1878 | */ |
| 1984 | void fb_set_suspend(struct fb_info *info, int state) | 1879 | void fb_set_suspend(struct fb_info *info, int state) |
| 1985 | { | 1880 | { |
| 1986 | struct fb_event event; | 1881 | WARN_CONSOLE_UNLOCKED(); |
| 1987 | 1882 | ||
| 1988 | event.info = info; | ||
| 1989 | if (state) { | 1883 | if (state) { |
| 1990 | fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); | 1884 | fbcon_suspended(info); |
| 1991 | info->state = FBINFO_STATE_SUSPENDED; | 1885 | info->state = FBINFO_STATE_SUSPENDED; |
| 1992 | } else { | 1886 | } else { |
| 1993 | info->state = FBINFO_STATE_RUNNING; | 1887 | info->state = FBINFO_STATE_RUNNING; |
| 1994 | fb_notifier_call_chain(FB_EVENT_RESUME, &event); | 1888 | fbcon_resumed(info); |
| 1995 | } | 1889 | } |
| 1996 | } | 1890 | } |
| 1997 | EXPORT_SYMBOL(fb_set_suspend); | 1891 | EXPORT_SYMBOL(fb_set_suspend); |
| @@ -2059,7 +1953,6 @@ subsys_initcall(fbmem_init); · 61 unmodified lines | |||
| 2059 | 1953 | ||
| 2060 | int fb_new_modelist(struct fb_info *info) | 1954 | int fb_new_modelist(struct fb_info *info) |
| 2061 | { | 1955 | { |
| 2062 | struct fb_event event; | ||
| 2063 | struct fb_var_screeninfo var = info->var; | 1956 | struct fb_var_screeninfo var = info->var; |
| 2064 | struct list_head *pos, *n; | 1957 | struct list_head *pos, *n; |
| 2065 | struct fb_modelist *modelist; | 1958 | struct fb_modelist *modelist; |
| @@ -2079,14 +1972,12 @@ int fb_new_modelist(struct fb_info *info) · 13 unmodified lines | |||
| 2079 | } | 1972 | } |
| 2080 | } | 1973 | } |
| 2081 | 1974 | ||
| 2082 | err = 1; | 1975 | if (list_empty(&info->modelist)) |
| 1976 | return 1; | ||
| 2083 | 1977 | ||
| 2084 | if (!list_empty(&info->modelist)) { | 1978 | fbcon_new_modelist(info); |
| 2085 | event.info = info; | ||
| 2086 | err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); | ||
| 2087 | } | ||
| 2088 | 1979 | ||
| 2089 | return err; | 1980 | return 0; |
| 2090 | } | 1981 | } |
| 2091 | 1982 | ||
| 2092 | MODULE_LICENSE("GPL"); | 1983 | MODULE_LICENSE("GPL"); |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
| 17 | #include <linux/fbcon.h> | ||
| 17 | #include <linux/console.h> | 18 | #include <linux/console.h> |
| 18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 19 | 20 | ||
| @@ -175,10 +176,7 @@ static ssize_t store_modes(struct device *device, · 155 unmodified lines | |||
| 175 | return -EINVAL; | 176 | return -EINVAL; |
| 176 | 177 | ||
| 177 | console_lock(); | 178 | console_lock(); |
| 178 | if (!lock_fb_info(fb_info)) { | 179 | lock_fb_info(fb_info); |
| 179 | console_unlock(); | ||
| 180 | return -ENODEV; | ||
| 181 | } | ||
| 182 | 180 | ||
| 183 | list_splice(&fb_info->modelist, &old_list); | 181 | list_splice(&fb_info->modelist, &old_list); |
| 184 | fb_videomode_to_modelist((const struct fb_videomode *)buf, i, | 182 | fb_videomode_to_modelist((const struct fb_videomode *)buf, i, |
| @@ -304,12 +302,13 @@ static ssize_t store_blank(struct device *device, · 119 unmodified lines | |||
| 304 | { | 302 | { |
| 305 | struct fb_info *fb_info = dev_get_drvdata(device); | 303 | struct fb_info *fb_info = dev_get_drvdata(device); |
| 306 | char *last = NULL; | 304 | char *last = NULL; |
| 307 | int err; | 305 | int err, arg; |
| 308 | 306 | ||
| 307 | arg = simple_strtoul(buf, &last, 0); | ||
| 309 | console_lock(); | 308 | console_lock(); |
| 310 | fb_info->flags |= FBINFO_MISC_USEREVENT; | 309 | err = fb_blank(fb_info, arg); |
| 311 | err = fb_blank(fb_info, simple_strtoul(buf, &last, 0)); | 310 | /* might again call into fb_blank */ |
| 312 | fb_info->flags &= ~FBINFO_MISC_USEREVENT; | 311 | fbcon_fb_blanked(fb_info, arg); |
| 313 | console_unlock(); | 312 | console_unlock(); |
| 314 | if (err < 0) | 313 | if (err < 0) |
| 315 | return err; | 314 | return err; |
| @@ -405,10 +404,7 @@ static ssize_t store_fbstate(struct device *device, · 89 unmodified lines | |||
| 405 | state = simple_strtoul(buf, &last, 0); | 404 | state = simple_strtoul(buf, &last, 0); |
| 406 | 405 | ||
| 407 | console_lock(); | 406 | console_lock(); |
| 408 | if (!lock_fb_info(fb_info)) { | 407 | lock_fb_info(fb_info); |
| 409 | console_unlock(); | ||
| 410 | return -ENODEV; | ||
| 411 | } | ||
| 412 | 408 | ||
| 413 | fb_set_suspend(fb_info, (int)state); | 409 | fb_set_suspend(fb_info, (int)state); |
| 414 | 410 | ||
| @@ -58,7 +58,6 @@ · 57 unmodified lines | |||
| 58 | struct cfb_info { | 58 | struct cfb_info { |
| 59 | struct fb_info fb; | 59 | struct fb_info fb; |
| 60 | struct display_switch *dispsw; | 60 | struct display_switch *dispsw; |
| 61 | struct display *display; | ||
| 62 | unsigned char __iomem *region; | 61 | unsigned char __iomem *region; |
| 63 | unsigned char __iomem *regs; | 62 | unsigned char __iomem *regs; |
| 64 | u_int id; | 63 | u_int id; |
| @@ -1638,10 +1637,6 @@ static void cyberpro_common_resume(struct cfb_info *cfb) · 1573 unmodified lines | |||
| 1638 | cyber2000fb_set_par(&cfb->fb); | 1637 | cyber2000fb_set_par(&cfb->fb); |
| 1639 | } | 1638 | } |
| 1640 | 1639 | ||
| 1641 | /* | ||
| 1642 | * PCI specific support. | ||
| 1643 | */ | ||
| 1644 | #ifdef CONFIG_PCI | ||
| 1645 | /* | 1640 | /* |
| 1646 | * We need to wake up the CyberPro, and make sure its in linear memory | 1641 | * We need to wake up the CyberPro, and make sure its in linear memory |
| 1647 | * mode. Unfortunately, this is specific to the platform and card that | 1642 | * mode. Unfortunately, this is specific to the platform and card that |
| @@ -1858,7 +1853,6 @@ static struct pci_driver cyberpro_driver = { · 210 unmodified lines | |||
| 1858 | .resume = cyberpro_pci_resume, | 1853 | .resume = cyberpro_pci_resume, |
| 1859 | .id_table = cyberpro_pci_table | 1854 | .id_table = cyberpro_pci_table |
| 1860 | }; | 1855 | }; |
| 1861 | #endif | ||
| 1862 | 1856 | ||
| 1863 | /* | 1857 | /* |
| 1864 | * I don't think we can use the "module_init" stuff here because | 1858 | * I don't think we can use the "module_init" stuff here because |
| @@ -1387,7 +1387,6 @@ static int fb_probe(struct platform_device *device) · 1386 unmodified lines | |||
| 1387 | da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), | 1387 | da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), |
| 1388 | &device->dev); | 1388 | &device->dev); |
| 1389 | if (!da8xx_fb_info) { | 1389 | if (!da8xx_fb_info) { |
| 1390 | dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); | ||
| 1391 | ret = -ENOMEM; | 1390 | ret = -ENOMEM; |
| 1392 | goto err_pm_runtime_disable; | 1391 | goto err_pm_runtime_disable; |
| 1393 | } | 1392 | } |
| @@ -169,6 +169,11 @@ static void efifb_show_boot_graphics(struct fb_info *info) · 168 unmodified lines | |||
| 169 | return; | 169 | return; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | if (bgrt_tab.status & 0x06) { | ||
| 173 | pr_info("efifb: BGRT rotation bits set, not showing boot graphics\n"); | ||
| 174 | return; | ||
| 175 | } | ||
| 176 | |||
| 172 | /* Avoid flashing the logo if we're going to print std probe messages */ | 177 | /* Avoid flashing the logo if we're going to print std probe messages */ |
| 173 | if (console_loglevel > CONSOLE_LOGLEVEL_QUIET) | 178 | if (console_loglevel > CONSOLE_LOGLEVEL_QUIET) |
| 174 | return; | 179 | return; |
| @@ -448,7 +453,6 @@ static int efifb_probe(struct platform_device *dev) · 273 unmodified lines | |||
| 448 | 453 | ||
| 449 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); | 454 | info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); |
| 450 | if (!info) { | 455 | if (!info) { |
| 451 | pr_err("efifb: cannot allocate framebuffer\n"); | ||
| 452 | err = -ENOMEM; | 456 | err = -ENOMEM; |
| 453 | goto err_release_mem; | 457 | goto err_release_mem; |
| 454 | } | 458 | } |
| @@ -39,9 +39,7 @@ struct gbefb_par { · 38 unmodified lines | |||
| 39 | int valid; | 39 | int valid; |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | #ifdef CONFIG_SGI_IP32 | ||
| 43 | #define GBE_BASE 0x16000000 /* SGI O2 */ | 42 | #define GBE_BASE 0x16000000 /* SGI O2 */ |
| 44 | #endif | ||
| 45 | 43 | ||
| 46 | /* macro for fastest write-though access to the framebuffer */ | 44 | /* macro for fastest write-though access to the framebuffer */ |
| 47 | #ifdef CONFIG_MIPS | 45 | #ifdef CONFIG_MIPS |
| @@ -51,10 +49,6 @@ struct gbefb_par { · 3 unmodified lines | |||
| 51 | #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA) | 49 | #define pgprot_fb(_prot) (((_prot) & (~_CACHE_MASK)) | _CACHE_CACHABLE_NO_WA) |
| 52 | #endif | 50 | #endif |
| 53 | #endif | 51 | #endif |
| 54 | #ifdef CONFIG_X86 | ||
| 55 | #define pgprot_fb(_prot) (((_prot) & ~_PAGE_CACHE_MASK) | \ | ||
| 56 | cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS)) | ||
| 57 | #endif | ||
| 58 | 52 | ||
| 59 | /* | 53 | /* |
| 60 | * RAM we reserve for the frame buffer. This defines the maximum screen | 54 | * RAM we reserve for the frame buffer. This defines the maximum screen |
| @@ -279,7 +273,7 @@ static void gbe_turn_off(void) · 218 unmodified lines | |||
| 279 | val = 0; | 273 | val = 0; |
| 280 | SET_GBE_FIELD(VT_XY, FREEZE, val, 1); | 274 | SET_GBE_FIELD(VT_XY, FREEZE, val, 1); |
| 281 | gbe->vt_xy = val; | 275 | gbe->vt_xy = val; |
| 282 | udelay(10000); | 276 | mdelay(10); |
| 283 | for (i = 0; i < 10000; i++) { | 277 | for (i = 0; i < 10000; i++) { |
| 284 | val = gbe->vt_xy; | 278 | val = gbe->vt_xy; |
| 285 | if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1) | 279 | if (GET_GBE_FIELD(VT_XY, FREEZE, val) != 1) |
| @@ -294,7 +288,7 @@ static void gbe_turn_off(void) · 8 unmodified lines | |||
| 294 | val = gbe->dotclock; | 288 | val = gbe->dotclock; |
| 295 | SET_GBE_FIELD(DOTCLK, RUN, val, 0); | 289 | SET_GBE_FIELD(DOTCLK, RUN, val, 0); |
| 296 | gbe->dotclock = val; | 290 | gbe->dotclock = val; |
| 297 | udelay(10000); | 291 | mdelay(10); |
| 298 | for (i = 0; i < 10000; i++) { | 292 | for (i = 0; i < 10000; i++) { |
| 299 | val = gbe->dotclock; | 293 | val = gbe->dotclock; |
| 300 | if (GET_GBE_FIELD(DOTCLK, RUN, val)) | 294 | if (GET_GBE_FIELD(DOTCLK, RUN, val)) |
| @@ -331,7 +325,7 @@ static void gbe_turn_on(void) · 30 unmodified lines | |||
| 331 | val = gbe->dotclock; | 325 | val = gbe->dotclock; |
| 332 | SET_GBE_FIELD(DOTCLK, RUN, val, 1); | 326 | SET_GBE_FIELD(DOTCLK, RUN, val, 1); |
| 333 | gbe->dotclock = val; | 327 | gbe->dotclock = val; |
| 334 | udelay(10000); | 328 | mdelay(10); |
| 335 | for (i = 0; i < 10000; i++) { | 329 | for (i = 0; i < 10000; i++) { |
| 336 | val = gbe->dotclock; | 330 | val = gbe->dotclock; |
| 337 | if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1) | 331 | if (GET_GBE_FIELD(DOTCLK, RUN, val) != 1) |
| @@ -346,7 +340,7 @@ static void gbe_turn_on(void) · 8 unmodified lines | |||
| 346 | val = 0; | 340 | val = 0; |
| 347 | SET_GBE_FIELD(VT_XY, FREEZE, val, 0); | 341 | SET_GBE_FIELD(VT_XY, FREEZE, val, 0); |
| 348 | gbe->vt_xy = val; | 342 | gbe->vt_xy = val; |
| 349 | udelay(10000); | 343 | mdelay(10); |
| 350 | for (i = 0; i < 10000; i++) { | 344 | for (i = 0; i < 10000; i++) { |
| 351 | val = gbe->vt_xy; | 345 | val = gbe->vt_xy; |
| 352 | if (GET_GBE_FIELD(VT_XY, FREEZE, val)) | 346 | if (GET_GBE_FIELD(VT_XY, FREEZE, val)) |
| @@ -547,7 +541,7 @@ static void gbe_set_timing_info(struct gbe_timing_info *timing) · 194 unmodified lines | |||
| 547 | SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p); | 541 | SET_GBE_FIELD(DOTCLK, P, val, timing->pll_p); |
| 548 | SET_GBE_FIELD(DOTCLK, RUN, val, 0); /* do not start yet */ | 542 | SET_GBE_FIELD(DOTCLK, RUN, val, 0); /* do not start yet */ |
| 549 | gbe->dotclock = val; | 543 | gbe->dotclock = val; |
| 550 | udelay(10000); | 544 | mdelay(10); |
| 551 | 545 | ||
| 552 | /* setup pixel counter */ | 546 | /* setup pixel counter */ |
| 553 | val = 0; | 547 | val = 0; |
| @@ -1018,9 +1012,10 @@ static int gbefb_mmap(struct fb_info *info, · 464 unmodified lines | |||
| 1018 | 1012 | ||
| 1019 | /* remap using the fastest write-through mode on architecture */ | 1013 | /* remap using the fastest write-through mode on architecture */ |
| 1020 | /* try not polluting the cache when possible */ | 1014 | /* try not polluting the cache when possible */ |
| 1015 | #ifdef CONFIG_MIPS | ||
| 1021 | pgprot_val(vma->vm_page_prot) = | 1016 | pgprot_val(vma->vm_page_prot) = |
| 1022 | pgprot_fb(pgprot_val(vma->vm_page_prot)); | 1017 | pgprot_fb(pgprot_val(vma->vm_page_prot)); |
| 1023 | 1018 | #endif | |
| 1024 | /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ | 1019 | /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ |
| 1025 | 1020 | ||
| 1026 | /* look for the starting tile */ | 1021 | /* look for the starting tile */ |
| @@ -336,10 +336,8 @@ static int grvga_probe(struct platform_device *dev) · 335 unmodified lines | |||
| 336 | char *options = NULL, *mode_opt = NULL; | 336 | char *options = NULL, *mode_opt = NULL; |
| 337 | 337 | ||
| 338 | info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); | 338 | info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); |
| 339 | if (!info) { | 339 | if (!info) |
| 340 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
| 341 | return -ENOMEM; | 340 | return -ENOMEM; |
| 342 | } | ||
| 343 | 341 | ||
| 344 | /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>] | 342 | /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>] |
| 345 | * | 343 | * |
| @@ -643,10 +643,9 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 642 unmodified lines | |||
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev); | 645 | info = framebuffer_alloc(sizeof(struct gxt4500_par), &pdev->dev); |
| 646 | if (!info) { | 646 | if (!info) |
| 647 | dev_err(&pdev->dev, "gxt4500: cannot alloc FB info record\n"); | ||
| 648 | goto err_free_fb; | 647 | goto err_free_fb; |
| 649 | } | 648 | |
| 650 | par = info->par; | 649 | par = info->par; |
| 651 | cardtype = ent->driver_data; | 650 | cardtype = ent->driver_data; |
| 652 | par->refclk_ps = cardinfo[cardtype].refclk_ps; | 651 | par->refclk_ps = cardinfo[cardtype].refclk_ps; |
| @@ -762,10 +762,8 @@ static int hvfb_probe(struct hv_device *hdev, · 761 unmodified lines | |||
| 762 | int ret; | 762 | int ret; |
| 763 | 763 | ||
| 764 | info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device); | 764 | info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device); |
| 765 | if (!info) { | 765 | if (!info) |
| 766 | pr_err("No memory for framebuffer info\n"); | ||
| 767 | return -ENOMEM; | 766 | return -ENOMEM; |
| 768 | } | ||
| 769 | 767 | ||
| 770 | par = info->par; | 768 | par = info->par; |
| 771 | par->info = info; | 769 | par->info = info; |
| @@ -1006,10 +1006,8 @@ static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) · 1005 unmodified lines | |||
| 1006 | u8 *edid; | 1006 | u8 *edid; |
| 1007 | 1007 | ||
| 1008 | info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev)); | 1008 | info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev)); |
| 1009 | if (!info) { | 1009 | if (!info) |
| 1010 | dev_err(&(dev->dev), "cannot allocate framebuffer\n"); | ||
| 1011 | return -ENOMEM; | 1010 | return -ENOMEM; |
| 1012 | } | ||
| 1013 | 1011 | ||
| 1014 | par = info->par; | 1012 | par = info->par; |
| 1015 | mutex_init(&par->open_lock); | 1013 | mutex_init(&par->open_lock); |
| @@ -1477,11 +1477,8 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 1476 unmodified lines | |||
| 1477 | printk(KERN_ERR "imsttfb: no OF node for pci device\n"); | 1477 | printk(KERN_ERR "imsttfb: no OF node for pci device\n"); |
| 1478 | 1478 | ||
| 1479 | info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev); | 1479 | info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev); |
| 1480 | 1480 | if (!info) | |
| 1481 | if (!info) { | ||
| 1482 | printk(KERN_ERR "imsttfb: Can't allocate memory\n"); | ||
| 1483 | return -ENOMEM; | 1481 | return -ENOMEM; |
| 1484 | } | ||
| 1485 | 1482 | ||
| 1486 | par = info->par; | 1483 | par = info->par; |
| 1487 | 1484 | ||
| @@ -974,10 +974,9 @@ static int imxfb_probe(struct platform_device *pdev) · 973 unmodified lines | |||
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | fbi->map_size = PAGE_ALIGN(info->fix.smem_len); | 976 | fbi->map_size = PAGE_ALIGN(info->fix.smem_len); |
| 977 | info->screen_base = dma_alloc_wc(&pdev->dev, fbi->map_size, | 977 | info->screen_buffer = dma_alloc_wc(&pdev->dev, fbi->map_size, |
| 978 | &fbi->map_dma, GFP_KERNEL); | 978 | &fbi->map_dma, GFP_KERNEL); |
| 979 | 979 | if (!info->screen_buffer) { | |
| 980 | if (!info->screen_base) { | ||
| 981 | dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret); | 980 | dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret); |
| 982 | ret = -ENOMEM; | 981 | ret = -ENOMEM; |
| 983 | goto failed_map; | 982 | goto failed_map; |
| @@ -1046,7 +1045,7 @@ failed_cmap: · 62 unmodified lines | |||
| 1046 | if (pdata && pdata->exit) | 1045 | if (pdata && pdata->exit) |
| 1047 | pdata->exit(fbi->pdev); | 1046 | pdata->exit(fbi->pdev); |
| 1048 | failed_platform_init: | 1047 | failed_platform_init: |
| 1049 | dma_free_wc(&pdev->dev, fbi->map_size, info->screen_base, | 1048 | dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer, |
| 1050 | fbi->map_dma); | 1049 | fbi->map_dma); |
| 1051 | failed_map: | 1050 | failed_map: |
| 1052 | iounmap(fbi->regs); | 1051 | iounmap(fbi->regs); |
| @@ -1077,7 +1076,7 @@ static int imxfb_remove(struct platform_device *pdev) · 24 unmodified lines | |||
| 1077 | pdata = dev_get_platdata(&pdev->dev); | 1076 | pdata = dev_get_platdata(&pdev->dev); |
| 1078 | if (pdata && pdata->exit) | 1077 | if (pdata && pdata->exit) |
| 1079 | pdata->exit(fbi->pdev); | 1078 | pdata->exit(fbi->pdev); |
| 1080 | dma_free_wc(&pdev->dev, fbi->map_size, info->screen_base, | 1079 | dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer, |
| 1081 | fbi->map_dma); | 1080 | fbi->map_dma); |
| 1082 | iounmap(fbi->regs); | 1081 | iounmap(fbi->regs); |
| 1083 | release_mem_region(res->start, resource_size(res)); | 1082 | release_mem_region(res->start, resource_size(res)); |
| @@ -491,10 +491,9 @@ static int intelfb_pci_register(struct pci_dev *pdev, · 490 unmodified lines | |||
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev); | 493 | info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev); |
| 494 | if (!info) { | 494 | if (!info) |
| 495 | ERR_MSG("Could not allocate memory for intelfb_info.\n"); | 495 | return -ENOMEM; |
| 496 | return -ENODEV; | 496 | |
| 497 | } | ||
| 498 | if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) { | 497 | if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) { |
| 499 | ERR_MSG("Could not allocate cmap for intelfb_info.\n"); | 498 | ERR_MSG("Could not allocate cmap for intelfb_info.\n"); |
| 500 | goto err_out_cmap; | 499 | goto err_out_cmap; |
| @@ -457,7 +457,6 @@ static int jzfb_alloc_devmem(struct jzfb *jzfb) · 456 unmodified lines | |||
| 457 | { | 457 | { |
| 458 | int max_videosize = 0; | 458 | int max_videosize = 0; |
| 459 | struct fb_videomode *mode = jzfb->pdata->modes; | 459 | struct fb_videomode *mode = jzfb->pdata->modes; |
| 460 | void *page; | ||
| 461 | int i; | 460 | int i; |
| 462 | 461 | ||
| 463 | for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { | 462 | for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { |
| @@ -482,12 +481,6 @@ static int jzfb_alloc_devmem(struct jzfb *jzfb) · 18 unmodified lines | |||
| 482 | if (!jzfb->vidmem) | 481 | if (!jzfb->vidmem) |
| 483 | goto err_free_framedesc; | 482 | goto err_free_framedesc; |
| 484 | 483 | ||
| 485 | for (page = jzfb->vidmem; | ||
| 486 | page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size); | ||
| 487 | page += PAGE_SIZE) { | ||
| 488 | SetPageReserved(virt_to_page(page)); | ||
| 489 | } | ||
| 490 | |||
| 491 | jzfb->framedesc->next = jzfb->framedesc_phys; | 484 | jzfb->framedesc->next = jzfb->framedesc_phys; |
| 492 | jzfb->framedesc->addr = jzfb->vidmem_phys; | 485 | jzfb->framedesc->addr = jzfb->vidmem_phys; |
| 493 | jzfb->framedesc->id = 0xdeafbead; | 486 | jzfb->framedesc->id = 0xdeafbead; |
| @@ -535,10 +528,8 @@ static int jzfb_probe(struct platform_device *pdev) · 41 unmodified lines | |||
| 535 | } | 528 | } |
| 536 | 529 | ||
| 537 | fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); | 530 | fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); |
| 538 | if (!fb) { | 531 | if (!fb) |
| 539 | dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); | ||
| 540 | return -ENOMEM; | 532 | return -ENOMEM; |
| 541 | } | ||
| 542 | 533 | ||
| 543 | fb->fbops = &jzfb_ops; | 534 | fb->fbops = &jzfb_ops; |
| 544 | fb->flags = FBINFO_DEFAULT; | 535 | fb->flags = FBINFO_DEFAULT; |
| @@ -680,10 +680,8 @@ static int of_platform_mb862xx_probe(struct platform_device *ofdev) · 679 unmodified lines | |||
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); | 682 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); |
| 683 | if (info == NULL) { | 683 | if (!info) |
| 684 | dev_err(dev, "cannot allocate framebuffer\n"); | ||
| 685 | return -ENOMEM; | 684 | return -ENOMEM; |
| 686 | } | ||
| 687 | 685 | ||
| 688 | par = info->par; | 686 | par = info->par; |
| 689 | par->info = info; | 687 | par->info = info; |
| @@ -1005,7 +1003,6 @@ static int mb862xx_pci_probe(struct pci_dev *pdev, · 315 unmodified lines | |||
| 1005 | 1003 | ||
| 1006 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); | 1004 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); |
| 1007 | if (!info) { | 1005 | if (!info) { |
| 1008 | dev_err(dev, "framebuffer alloc failed\n"); | ||
| 1009 | ret = -ENOMEM; | 1006 | ret = -ENOMEM; |
| 1010 | goto dis_dev; | 1007 | goto dis_dev; |
| 1011 | } | 1008 | } |
| @@ -899,10 +899,8 @@ static int mbxfb_probe(struct platform_device *dev) · 898 unmodified lines | |||
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); | 901 | fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); |
| 902 | if (fbi == NULL) { | 902 | if (!fbi) |
| 903 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
| 904 | return -ENOMEM; | 903 | return -ENOMEM; |
| 905 | } | ||
| 906 | 904 | ||
| 907 | mfbi = fbi->par; | 905 | mfbi = fbi->par; |
| 908 | fbi->pseudo_palette = mfbi->pseudo_palette; | 906 | fbi->pseudo_palette = mfbi->pseudo_palette; |
| @@ -433,7 +433,7 @@ static int mmphw_probe(struct platform_device *pdev) · 432 unmodified lines | |||
| 433 | { | 433 | { |
| 434 | struct mmp_mach_plat_info *mi; | 434 | struct mmp_mach_plat_info *mi; |
| 435 | struct resource *res; | 435 | struct resource *res; |
| 436 | int ret, i, size, irq; | 436 | int ret, i, irq; |
| 437 | struct mmphw_path_plat *path_plat; | 437 | struct mmphw_path_plat *path_plat; |
| 438 | struct mmphw_ctrl *ctrl = NULL; | 438 | struct mmphw_ctrl *ctrl = NULL; |
| 439 | 439 | ||
| @@ -461,9 +461,9 @@ static int mmphw_probe(struct platform_device *pdev) · 21 unmodified lines | |||
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | /* allocate */ | 463 | /* allocate */ |
| 464 | size = sizeof(struct mmphw_ctrl) + sizeof(struct mmphw_path_plat) * | 464 | ctrl = devm_kzalloc(&pdev->dev, |
| 465 | mi->path_num; | 465 | struct_size(ctrl, path_plats, mi->path_num), |
| 466 | ctrl = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); | 466 | GFP_KERNEL); |
| 467 | if (!ctrl) { | 467 | if (!ctrl) { |
| 468 | ret = -ENOMEM; | 468 | ret = -ENOMEM; |
| 469 | goto failed; | 469 | goto failed; |
| @@ -1,1028 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2010 Juergen Beisert, Pengutronix | ||
| 4 | * | ||
| 5 | * This code is based on: | ||
| 6 | * Author: Vitaly Wool <vital@embeddedalley.com> | ||
| 7 | * | ||
| 8 | * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
| 9 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define DRIVER_NAME "mxsfb" | ||
| 13 | |||
| 14 | /** | ||
| 15 | * @file | ||
| 16 | * @brief LCDIF driver for i.MX23 and i.MX28 | ||
| 17 | * | ||
| 18 | * The LCDIF support four modes of operation | ||
| 19 | * - MPU interface (to drive smart displays) -> not supported yet | ||
| 20 | * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet | ||
| 21 | * - Dotclock interface (to drive LC displays with RGB data and sync signals) | ||
| 22 | * - DVI (to drive ITU-R BT656) -> not supported yet | ||
| 23 | * | ||
| 24 | * This driver depends on a correct setup of the pins used for this purpose | ||
| 25 | * (platform specific). | ||
| 26 | * | ||
| 27 | * For the developer: Don't forget to set the data bus width to the display | ||
| 28 | * in the imx_fb_videomode structure. You will else end up with ugly colours. | ||
| 29 | * If you fight against jitter you can vary the clock delay. This is a feature | ||
| 30 | * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give | ||
| 31 | * the required value in the imx_fb_videomode structure. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/of_device.h> | ||
| 37 | #include <linux/platform_device.h> | ||
| 38 | #include <linux/clk.h> | ||
| 39 | #include <linux/dma-mapping.h> | ||
| 40 | #include <linux/io.h> | ||
| 41 | #include <linux/fb.h> | ||
| 42 | #include <linux/regulator/consumer.h> | ||
| 43 | #include <video/of_display_timing.h> | ||
| 44 | #include <video/of_videomode.h> | ||
| 45 | #include <video/videomode.h> | ||
| 46 | |||
| 47 | #define REG_SET 4 | ||
| 48 | #define REG_CLR 8 | ||
| 49 | |||
| 50 | #define LCDC_CTRL 0x00 | ||
| 51 | #define LCDC_CTRL1 0x10 | ||
| 52 | #define LCDC_V4_CTRL2 0x20 | ||
| 53 | #define LCDC_V3_TRANSFER_COUNT 0x20 | ||
| 54 | #define LCDC_V4_TRANSFER_COUNT 0x30 | ||
| 55 | #define LCDC_V4_CUR_BUF 0x40 | ||
| 56 | #define LCDC_V4_NEXT_BUF 0x50 | ||
| 57 | #define LCDC_V3_CUR_BUF 0x30 | ||
| 58 | #define LCDC_V3_NEXT_BUF 0x40 | ||
| 59 | #define LCDC_TIMING 0x60 | ||
| 60 | #define LCDC_VDCTRL0 0x70 | ||
| 61 | #define LCDC_VDCTRL1 0x80 | ||
| 62 | #define LCDC_VDCTRL2 0x90 | ||
| 63 | #define LCDC_VDCTRL3 0xa0 | ||
| 64 | #define LCDC_VDCTRL4 0xb0 | ||
| 65 | #define LCDC_DVICTRL0 0xc0 | ||
| 66 | #define LCDC_DVICTRL1 0xd0 | ||
| 67 | #define LCDC_DVICTRL2 0xe0 | ||
| 68 | #define LCDC_DVICTRL3 0xf0 | ||
| 69 | #define LCDC_DVICTRL4 0x100 | ||
| 70 | #define LCDC_V4_DATA 0x180 | ||
| 71 | #define LCDC_V3_DATA 0x1b0 | ||
| 72 | #define LCDC_V4_DEBUG0 0x1d0 | ||
| 73 | #define LCDC_V3_DEBUG0 0x1f0 | ||
| 74 | |||
| 75 | #define CTRL_SFTRST (1 << 31) | ||
| 76 | #define CTRL_CLKGATE (1 << 30) | ||
| 77 | #define CTRL_BYPASS_COUNT (1 << 19) | ||
| 78 | #define CTRL_VSYNC_MODE (1 << 18) | ||
| 79 | #define CTRL_DOTCLK_MODE (1 << 17) | ||
| 80 | #define CTRL_DATA_SELECT (1 << 16) | ||
| 81 | #define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10) | ||
| 82 | #define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3) | ||
| 83 | #define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8) | ||
| 84 | #define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3) | ||
| 85 | #define CTRL_MASTER (1 << 5) | ||
| 86 | #define CTRL_DF16 (1 << 3) | ||
| 87 | #define CTRL_DF18 (1 << 2) | ||
| 88 | #define CTRL_DF24 (1 << 1) | ||
| 89 | #define CTRL_RUN (1 << 0) | ||
| 90 | |||
| 91 | #define CTRL1_FIFO_CLEAR (1 << 21) | ||
| 92 | #define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16) | ||
| 93 | #define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf) | ||
| 94 | |||
| 95 | #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) | ||
| 96 | #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) | ||
| 97 | #define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff) | ||
| 98 | #define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff) | ||
| 99 | |||
| 100 | |||
| 101 | #define VDCTRL0_ENABLE_PRESENT (1 << 28) | ||
| 102 | #define VDCTRL0_VSYNC_ACT_HIGH (1 << 27) | ||
| 103 | #define VDCTRL0_HSYNC_ACT_HIGH (1 << 26) | ||
| 104 | #define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25) | ||
| 105 | #define VDCTRL0_ENABLE_ACT_HIGH (1 << 24) | ||
| 106 | #define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) | ||
| 107 | #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) | ||
| 108 | #define VDCTRL0_HALF_LINE (1 << 19) | ||
| 109 | #define VDCTRL0_HALF_LINE_MODE (1 << 18) | ||
| 110 | #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) | ||
| 111 | #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) | ||
| 112 | |||
| 113 | #define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff) | ||
| 114 | #define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff) | ||
| 115 | |||
| 116 | #define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) | ||
| 117 | #define VDCTRL3_VSYNC_ONLY (1 << 28) | ||
| 118 | #define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16) | ||
| 119 | #define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff) | ||
| 120 | #define SET_VERT_WAIT_CNT(x) ((x) & 0xffff) | ||
| 121 | #define GET_VERT_WAIT_CNT(x) ((x) & 0xffff) | ||
| 122 | |||
| 123 | #define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */ | ||
| 124 | #define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */ | ||
| 125 | #define VDCTRL4_SYNC_SIGNALS_ON (1 << 18) | ||
| 126 | #define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff) | ||
| 127 | |||
| 128 | #define DEBUG0_HSYNC (1 < 26) | ||
| 129 | #define DEBUG0_VSYNC (1 < 25) | ||
| 130 | |||
| 131 | #define MIN_XRES 120 | ||
| 132 | #define MIN_YRES 120 | ||
| 133 | |||
| 134 | #define RED 0 | ||
| 135 | #define GREEN 1 | ||
| 136 | #define BLUE 2 | ||
| 137 | #define TRANSP 3 | ||
| 138 | |||
| 139 | #define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */ | ||
| 140 | #define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */ | ||
| 141 | #define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */ | ||
| 142 | #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */ | ||
| 143 | |||
| 144 | #define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6) | ||
| 145 | #define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negative edge sampling */ | ||
| 146 | |||
| 147 | enum mxsfb_devtype { | ||
| 148 | MXSFB_V3, | ||
| 149 | MXSFB_V4, | ||
| 150 | }; | ||
| 151 | |||
| 152 | /* CPU dependent register offsets */ | ||
| 153 | struct mxsfb_devdata { | ||
| 154 | unsigned transfer_count; | ||
| 155 | unsigned cur_buf; | ||
| 156 | unsigned next_buf; | ||
| 157 | unsigned debug0; | ||
| 158 | unsigned hs_wdth_mask; | ||
| 159 | unsigned hs_wdth_shift; | ||
| 160 | unsigned ipversion; | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct mxsfb_info { | ||
| 164 | struct platform_device *pdev; | ||
| 165 | struct clk *clk; | ||
| 166 | struct clk *clk_axi; | ||
| 167 | struct clk *clk_disp_axi; | ||
| 168 | void __iomem *base; /* registers */ | ||
| 169 | unsigned allocated_size; | ||
| 170 | int enabled; | ||
| 171 | unsigned ld_intf_width; | ||
| 172 | unsigned dotclk_delay; | ||
| 173 | const struct mxsfb_devdata *devdata; | ||
| 174 | u32 sync; | ||
| 175 | struct regulator *reg_lcd; | ||
| 176 | int pre_init; | ||
| 177 | }; | ||
| 178 | |||
| 179 | #define mxsfb_is_v3(host) (host->devdata->ipversion == 3) | ||
| 180 | #define mxsfb_is_v4(host) (host->devdata->ipversion == 4) | ||
| 181 | |||
| 182 | static const struct mxsfb_devdata mxsfb_devdata[] = { | ||
| 183 | [MXSFB_V3] = { | ||
| 184 | .transfer_count = LCDC_V3_TRANSFER_COUNT, | ||
| 185 | .cur_buf = LCDC_V3_CUR_BUF, | ||
| 186 | .next_buf = LCDC_V3_NEXT_BUF, | ||
| 187 | .debug0 = LCDC_V3_DEBUG0, | ||
| 188 | .hs_wdth_mask = 0xff, | ||
| 189 | .hs_wdth_shift = 24, | ||
| 190 | .ipversion = 3, | ||
| 191 | }, | ||
| 192 | [MXSFB_V4] = { | ||
| 193 | .transfer_count = LCDC_V4_TRANSFER_COUNT, | ||
| 194 | .cur_buf = LCDC_V4_CUR_BUF, | ||
| 195 | .next_buf = LCDC_V4_NEXT_BUF, | ||
| 196 | .debug0 = LCDC_V4_DEBUG0, | ||
| 197 | .hs_wdth_mask = 0x3fff, | ||
| 198 | .hs_wdth_shift = 18, | ||
| 199 | .ipversion = 4, | ||
| 200 | }, | ||
| 201 | }; | ||
| 202 | |||
| 203 | /* mask and shift depends on architecture */ | ||
| 204 | static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val) | ||
| 205 | { | ||
| 206 | return (val & host->devdata->hs_wdth_mask) << | ||
| 207 | host->devdata->hs_wdth_shift; | ||
| 208 | } | ||
| 209 | |||
| 210 | static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val) | ||
| 211 | { | ||
| 212 | return (val >> host->devdata->hs_wdth_shift) & | ||
| 213 | host->devdata->hs_wdth_mask; | ||
| 214 | } | ||
| 215 | |||
| 216 | static const struct fb_bitfield def_rgb565[] = { | ||
| 217 | [RED] = { | ||
| 218 | .offset = 11, | ||
| 219 | .length = 5, | ||
| 220 | }, | ||
| 221 | [GREEN] = { | ||
| 222 | .offset = 5, | ||
| 223 | .length = 6, | ||
| 224 | }, | ||
| 225 | [BLUE] = { | ||
| 226 | .offset = 0, | ||
| 227 | .length = 5, | ||
| 228 | }, | ||
| 229 | [TRANSP] = { /* no support for transparency */ | ||
| 230 | .length = 0, | ||
| 231 | } | ||
| 232 | }; | ||
| 233 | |||
| 234 | static const struct fb_bitfield def_rgb888[] = { | ||
| 235 | [RED] = { | ||
| 236 | .offset = 16, | ||
| 237 | .length = 8, | ||
| 238 | }, | ||
| 239 | [GREEN] = { | ||
| 240 | .offset = 8, | ||
| 241 | .length = 8, | ||
| 242 | }, | ||
| 243 | [BLUE] = { | ||
| 244 | .offset = 0, | ||
| 245 | .length = 8, | ||
| 246 | }, | ||
| 247 | [TRANSP] = { /* no support for transparency */ | ||
| 248 | .length = 0, | ||
| 249 | } | ||
| 250 | }; | ||
| 251 | |||
| 252 | static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf) | ||
| 253 | { | ||
| 254 | chan &= 0xffff; | ||
| 255 | chan >>= 16 - bf->length; | ||
| 256 | return chan << bf->offset; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int mxsfb_check_var(struct fb_var_screeninfo *var, | ||
| 260 | struct fb_info *fb_info) | ||
| 261 | { | ||
| 262 | struct mxsfb_info *host = fb_info->par; | ||
| 263 | const struct fb_bitfield *rgb = NULL; | ||
| 264 | |||
| 265 | if (var->xres < MIN_XRES) | ||
| 266 | var->xres = MIN_XRES; | ||
| 267 | if (var->yres < MIN_YRES) | ||
| 268 | var->yres = MIN_YRES; | ||
| 269 | |||
| 270 | var->xres_virtual = var->xres; | ||
| 271 | |||
| 272 | var->yres_virtual = var->yres; | ||
| 273 | |||
| 274 | switch (var->bits_per_pixel) { | ||
| 275 | case 16: | ||
| 276 | /* always expect RGB 565 */ | ||
| 277 | rgb = def_rgb565; | ||
| 278 | break; | ||
| 279 | case 32: | ||
| 280 | switch (host->ld_intf_width) { | ||
| 281 | case STMLCDIF_8BIT: | ||
| 282 | pr_debug("Unsupported LCD bus width mapping\n"); | ||
| 283 | break; | ||
| 284 | case STMLCDIF_16BIT: | ||
| 285 | case STMLCDIF_18BIT: | ||
| 286 | case STMLCDIF_24BIT: | ||
| 287 | /* real 24 bit */ | ||
| 288 | rgb = def_rgb888; | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | break; | ||
| 292 | default: | ||
| 293 | pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel); | ||
| 294 | return -EINVAL; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Copy the RGB parameters for this display | ||
| 299 | * from the machine specific parameters. | ||
| 300 | */ | ||
| 301 | var->red = rgb[RED]; | ||
| 302 | var->green = rgb[GREEN]; | ||
| 303 | var->blue = rgb[BLUE]; | ||
| 304 | var->transp = rgb[TRANSP]; | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static inline void mxsfb_enable_axi_clk(struct mxsfb_info *host) | ||
| 310 | { | ||
| 311 | if (host->clk_axi) | ||
| 312 | clk_prepare_enable(host->clk_axi); | ||
| 313 | } | ||
| 314 | |||
| 315 | static inline void mxsfb_disable_axi_clk(struct mxsfb_info *host) | ||
| 316 | { | ||
| 317 | if (host->clk_axi) | ||
| 318 | clk_disable_unprepare(host->clk_axi); | ||
| 319 | } | ||
| 320 | |||
| 321 | static void mxsfb_enable_controller(struct fb_info *fb_info) | ||
| 322 | { | ||
| 323 | struct mxsfb_info *host = fb_info->par; | ||
| 324 | u32 reg; | ||
| 325 | int ret; | ||
| 326 | |||
| 327 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | ||
| 328 | |||
| 329 | if (host->reg_lcd) { | ||
| 330 | ret = regulator_enable(host->reg_lcd); | ||
| 331 | if (ret) { | ||
| 332 | dev_err(&host->pdev->dev, | ||
| 333 | "lcd regulator enable failed: %d\n", ret); | ||
| 334 | return; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | if (host->clk_disp_axi) | ||
| 339 | clk_prepare_enable(host->clk_disp_axi); | ||
| 340 | clk_prepare_enable(host->clk); | ||
| 341 | clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U); | ||
| 342 | |||
| 343 | mxsfb_enable_axi_clk(host); | ||
| 344 | |||
| 345 | /* if it was disabled, re-enable the mode again */ | ||
| 346 | writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET); | ||
| 347 | |||
| 348 | /* enable the SYNC signals first, then the DMA engine */ | ||
| 349 | reg = readl(host->base + LCDC_VDCTRL4); | ||
| 350 | reg |= VDCTRL4_SYNC_SIGNALS_ON; | ||
| 351 | writel(reg, host->base + LCDC_VDCTRL4); | ||
| 352 | |||
| 353 | writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET); | ||
| 354 | |||
| 355 | host->enabled = 1; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void mxsfb_disable_controller(struct fb_info *fb_info) | ||
| 359 | { | ||
| 360 | struct mxsfb_info *host = fb_info->par; | ||
| 361 | unsigned loop; | ||
| 362 | u32 reg; | ||
| 363 | int ret; | ||
| 364 | |||
| 365 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | ||
| 366 | |||
| 367 | /* | ||
| 368 | * Even if we disable the controller here, it will still continue | ||
| 369 | * until its FIFOs are running out of data | ||
| 370 | */ | ||
| 371 | writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR); | ||
| 372 | |||
| 373 | loop = 1000; | ||
| 374 | while (loop) { | ||
| 375 | reg = readl(host->base + LCDC_CTRL); | ||
| 376 | if (!(reg & CTRL_RUN)) | ||
| 377 | break; | ||
| 378 | loop--; | ||
| 379 | } | ||
| 380 | |||
| 381 | reg = readl(host->base + LCDC_VDCTRL4); | ||
| 382 | writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); | ||
| 383 | |||
| 384 | mxsfb_disable_axi_clk(host); | ||
| 385 | |||
| 386 | clk_disable_unprepare(host->clk); | ||
| 387 | if (host->clk_disp_axi) | ||
| 388 | clk_disable_unprepare(host->clk_disp_axi); | ||
| 389 | |||
| 390 | host->enabled = 0; | ||
| 391 | |||
| 392 | if (host->reg_lcd) { | ||
| 393 | ret = regulator_disable(host->reg_lcd); | ||
| 394 | if (ret) | ||
| 395 | dev_err(&host->pdev->dev, | ||
| 396 | "lcd regulator disable failed: %d\n", ret); | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | static int mxsfb_set_par(struct fb_info *fb_info) | ||
| 401 | { | ||
| 402 | struct mxsfb_info *host = fb_info->par; | ||
| 403 | u32 ctrl, vdctrl0, vdctrl4; | ||
| 404 | int line_size, fb_size; | ||
| 405 | int reenable = 0; | ||
| 406 | |||
| 407 | line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); | ||
| 408 | fb_size = fb_info->var.yres_virtual * line_size; | ||
| 409 | |||
| 410 | if (fb_size > fb_info->fix.smem_len) | ||
| 411 | return -ENOMEM; | ||
| 412 | |||
| 413 | fb_info->fix.line_length = line_size; | ||
| 414 | |||
| 415 | if (host->pre_init) { | ||
| 416 | mxsfb_enable_controller(fb_info); | ||
| 417 | host->pre_init = 0; | ||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | |||
| 421 | /* | ||
| 422 | * It seems, you can't re-program the controller if it is still running. | ||
| 423 | * This may lead into shifted pictures (FIFO issue?). | ||
| 424 | * So, first stop the controller and drain its FIFOs | ||
| 425 | */ | ||
| 426 | if (host->enabled) { | ||
| 427 | reenable = 1; | ||
| 428 | mxsfb_disable_controller(fb_info); | ||
| 429 | } | ||
| 430 | |||
| 431 | mxsfb_enable_axi_clk(host); | ||
| 432 | |||
| 433 | /* clear the FIFOs */ | ||
| 434 | writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET); | ||
| 435 | |||
| 436 | ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER | | ||
| 437 | CTRL_SET_BUS_WIDTH(host->ld_intf_width); | ||
| 438 | |||
| 439 | switch (fb_info->var.bits_per_pixel) { | ||
| 440 | case 16: | ||
| 441 | dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n"); | ||
| 442 | ctrl |= CTRL_SET_WORD_LENGTH(0); | ||
| 443 | writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1); | ||
| 444 | break; | ||
| 445 | case 32: | ||
| 446 | dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n"); | ||
| 447 | ctrl |= CTRL_SET_WORD_LENGTH(3); | ||
| 448 | switch (host->ld_intf_width) { | ||
| 449 | case STMLCDIF_8BIT: | ||
| 450 | mxsfb_disable_axi_clk(host); | ||
| 451 | dev_err(&host->pdev->dev, | ||
| 452 | "Unsupported LCD bus width mapping\n"); | ||
| 453 | return -EINVAL; | ||
| 454 | case STMLCDIF_16BIT: | ||
| 455 | case STMLCDIF_18BIT: | ||
| 456 | case STMLCDIF_24BIT: | ||
| 457 | /* real 24 bit */ | ||
| 458 | break; | ||
| 459 | } | ||
| 460 | /* do not use packed pixels = one pixel per word instead */ | ||
| 461 | writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1); | ||
| 462 | break; | ||
| 463 | default: | ||
| 464 | mxsfb_disable_axi_clk(host); | ||
| 465 | dev_err(&host->pdev->dev, "Unhandled color depth of %u\n", | ||
| 466 | fb_info->var.bits_per_pixel); | ||
| 467 | return -EINVAL; | ||
| 468 | } | ||
| 469 | |||
| 470 | writel(ctrl, host->base + LCDC_CTRL); | ||
| 471 | |||
| 472 | writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) | | ||
| 473 | TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres), | ||
| 474 | host->base + host->devdata->transfer_count); | ||
| 475 | |||
| 476 | vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */ | ||
| 477 | VDCTRL0_VSYNC_PERIOD_UNIT | | ||
| 478 | VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | | ||
| 479 | VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len); | ||
| 480 | if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT) | ||
| 481 | vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH; | ||
| 482 | if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT) | ||
| 483 | vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; | ||
| 484 | if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT) | ||
| 485 | vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; | ||
| 486 | if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT) | ||
| 487 | vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING; | ||
| 488 | |||
| 489 | writel(vdctrl0, host->base + LCDC_VDCTRL0); | ||
| 490 | |||
| 491 | /* frame length in lines */ | ||
| 492 | writel(fb_info->var.upper_margin + fb_info->var.vsync_len + | ||
| 493 | fb_info->var.lower_margin + fb_info->var.yres, | ||
| 494 | host->base + LCDC_VDCTRL1); | ||
| 495 | |||
| 496 | /* line length in units of clocks or pixels */ | ||
| 497 | writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) | | ||
| 498 | VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin + | ||
| 499 | fb_info->var.hsync_len + fb_info->var.right_margin + | ||
| 500 | fb_info->var.xres), | ||
| 501 | host->base + LCDC_VDCTRL2); | ||
| 502 | |||
| 503 | writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin + | ||
| 504 | fb_info->var.hsync_len) | | ||
| 505 | SET_VERT_WAIT_CNT(fb_info->var.upper_margin + | ||
| 506 | fb_info->var.vsync_len), | ||
| 507 | host->base + LCDC_VDCTRL3); | ||
| 508 | |||
| 509 | vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres); | ||
| 510 | if (mxsfb_is_v4(host)) | ||
| 511 | vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay); | ||
| 512 | writel(vdctrl4, host->base + LCDC_VDCTRL4); | ||
| 513 | |||
| 514 | writel(fb_info->fix.smem_start + | ||
| 515 | fb_info->fix.line_length * fb_info->var.yoffset, | ||
| 516 | host->base + host->devdata->next_buf); | ||
| 517 | |||
| 518 | mxsfb_disable_axi_clk(host); | ||
| 519 | |||
| 520 | if (reenable) | ||
| 521 | mxsfb_enable_controller(fb_info); | ||
| 522 | |||
| 523 | return 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
| 527 | u_int transp, struct fb_info *fb_info) | ||
| 528 | { | ||
| 529 | unsigned int val; | ||
| 530 | int ret = -EINVAL; | ||
| 531 | |||
| 532 | /* | ||
| 533 | * If greyscale is true, then we convert the RGB value | ||
| 534 | * to greyscale no matter what visual we are using. | ||
| 535 | */ | ||
| 536 | if (fb_info->var.grayscale) | ||
| 537 | red = green = blue = (19595 * red + 38470 * green + | ||
| 538 | 7471 * blue) >> 16; | ||
| 539 | |||
| 540 | switch (fb_info->fix.visual) { | ||
| 541 | case FB_VISUAL_TRUECOLOR: | ||
| 542 | /* | ||
| 543 | * 12 or 16-bit True Colour. We encode the RGB value | ||
| 544 | * according to the RGB bitfield information. | ||
| 545 | */ | ||
| 546 | if (regno < 16) { | ||
| 547 | u32 *pal = fb_info->pseudo_palette; | ||
| 548 | |||
| 549 | val = chan_to_field(red, &fb_info->var.red); | ||
| 550 | val |= chan_to_field(green, &fb_info->var.green); | ||
| 551 | val |= chan_to_field(blue, &fb_info->var.blue); | ||
| 552 | |||
| 553 | pal[regno] = val; | ||
| 554 | ret = 0; | ||
| 555 | } | ||
| 556 | break; | ||
| 557 | |||
| 558 | case FB_VISUAL_STATIC_PSEUDOCOLOR: | ||
| 559 | case FB_VISUAL_PSEUDOCOLOR: | ||
| 560 | break; | ||
| 561 | } | ||
| 562 | |||
| 563 | return ret; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int mxsfb_blank(int blank, struct fb_info *fb_info) | ||
| 567 | { | ||
| 568 | struct mxsfb_info *host = fb_info->par; | ||
| 569 | |||
| 570 | switch (blank) { | ||
| 571 | case FB_BLANK_POWERDOWN: | ||
| 572 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 573 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 574 | case FB_BLANK_NORMAL: | ||
| 575 | if (host->enabled) | ||
| 576 | mxsfb_disable_controller(fb_info); | ||
| 577 | break; | ||
| 578 | |||
| 579 | case FB_BLANK_UNBLANK: | ||
| 580 | if (!host->enabled) | ||
| 581 | mxsfb_enable_controller(fb_info); | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | static int mxsfb_pan_display(struct fb_var_screeninfo *var, | ||
| 588 | struct fb_info *fb_info) | ||
| 589 | { | ||
| 590 | struct mxsfb_info *host = fb_info->par; | ||
| 591 | unsigned offset; | ||
| 592 | |||
| 593 | if (var->xoffset != 0) | ||
| 594 | return -EINVAL; | ||
| 595 | |||
| 596 | offset = fb_info->fix.line_length * var->yoffset; | ||
| 597 | |||
| 598 | mxsfb_enable_axi_clk(host); | ||
| 599 | |||
| 600 | /* update on next VSYNC */ | ||
| 601 | writel(fb_info->fix.smem_start + offset, | ||
| 602 | host->base + host->devdata->next_buf); | ||
| 603 | |||
| 604 | mxsfb_disable_axi_clk(host); | ||
| 605 | |||
| 606 | return 0; | ||
| 607 | } | ||
| 608 | |||
| 609 | static struct fb_ops mxsfb_ops = { | ||
| 610 | .owner = THIS_MODULE, | ||
| 611 | .fb_check_var = mxsfb_check_var, | ||
| 612 | .fb_set_par = mxsfb_set_par, | ||
| 613 | .fb_setcolreg = mxsfb_setcolreg, | ||
| 614 | .fb_blank = mxsfb_blank, | ||
| 615 | .fb_pan_display = mxsfb_pan_display, | ||
| 616 | .fb_fillrect = cfb_fillrect, | ||
| 617 | .fb_copyarea = cfb_copyarea, | ||
| 618 | .fb_imageblit = cfb_imageblit, | ||
| 619 | }; | ||
| 620 | |||
| 621 | static int mxsfb_restore_mode(struct fb_info *fb_info, | ||
| 622 | struct fb_videomode *vmode) | ||
| 623 | { | ||
| 624 | struct mxsfb_info *host = fb_info->par; | ||
| 625 | unsigned period; | ||
| 626 | unsigned long pa, fbsize; | ||
| 627 | int bits_per_pixel, ofs, ret = 0; | ||
| 628 | u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl; | ||
| 629 | |||
| 630 | mxsfb_enable_axi_clk(host); | ||
| 631 | |||
| 632 | /* Only restore the mode when the controller is running */ | ||
| 633 | ctrl = readl(host->base + LCDC_CTRL); | ||
| 634 | if (!(ctrl & CTRL_RUN)) { | ||
| 635 | ret = -EINVAL; | ||
| 636 | goto err; | ||
| 637 | } | ||
| 638 | |||
| 639 | vdctrl0 = readl(host->base + LCDC_VDCTRL0); | ||
| 640 | vdctrl2 = readl(host->base + LCDC_VDCTRL2); | ||
| 641 | vdctrl3 = readl(host->base + LCDC_VDCTRL3); | ||
| 642 | vdctrl4 = readl(host->base + LCDC_VDCTRL4); | ||
| 643 | |||
| 644 | transfer_count = readl(host->base + host->devdata->transfer_count); | ||
| 645 | |||
| 646 | vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count); | ||
| 647 | vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count); | ||
| 648 | |||
| 649 | switch (CTRL_GET_WORD_LENGTH(ctrl)) { | ||
| 650 | case 0: | ||
| 651 | bits_per_pixel = 16; | ||
| 652 | break; | ||
| 653 | case 3: | ||
| 654 | bits_per_pixel = 32; | ||
| 655 | break; | ||
| 656 | case 1: | ||
| 657 | default: | ||
| 658 | ret = -EINVAL; | ||
| 659 | goto err; | ||
| 660 | } | ||
| 661 | |||
| 662 | fb_info->var.bits_per_pixel = bits_per_pixel; | ||
| 663 | |||
| 664 | vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U); | ||
| 665 | vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2); | ||
| 666 | vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len; | ||
| 667 | vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - | ||
| 668 | vmode->hsync_len - vmode->left_margin - vmode->xres; | ||
| 669 | vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0); | ||
| 670 | period = readl(host->base + LCDC_VDCTRL1); | ||
| 671 | vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len; | ||
| 672 | vmode->lower_margin = period - vmode->vsync_len - | ||
| 673 | vmode->upper_margin - vmode->yres; | ||
| 674 | |||
| 675 | vmode->vmode = FB_VMODE_NONINTERLACED; | ||
| 676 | |||
| 677 | vmode->sync = 0; | ||
| 678 | if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH) | ||
| 679 | vmode->sync |= FB_SYNC_HOR_HIGH_ACT; | ||
| 680 | if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH) | ||
| 681 | vmode->sync |= FB_SYNC_VERT_HIGH_ACT; | ||
| 682 | |||
| 683 | pr_debug("Reconstructed video mode:\n"); | ||
| 684 | pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n", | ||
| 685 | vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin, | ||
| 686 | vmode->right_margin, vmode->vsync_len, vmode->upper_margin, | ||
| 687 | vmode->lower_margin); | ||
| 688 | pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock)); | ||
| 689 | |||
| 690 | host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl); | ||
| 691 | host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4); | ||
| 692 | |||
| 693 | fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3); | ||
| 694 | |||
| 695 | pa = readl(host->base + host->devdata->cur_buf); | ||
| 696 | fbsize = fb_info->fix.line_length * vmode->yres; | ||
| 697 | if (pa < fb_info->fix.smem_start) { | ||
| 698 | ret = -EINVAL; | ||
| 699 | goto err; | ||
| 700 | } | ||
| 701 | if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) { | ||
| 702 | ret = -EINVAL; | ||
| 703 | goto err; | ||
| 704 | } | ||
| 705 | ofs = pa - fb_info->fix.smem_start; | ||
| 706 | if (ofs) { | ||
| 707 | memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize); | ||
| 708 | writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf); | ||
| 709 | } | ||
| 710 | |||
| 711 | fb_info->fix.ypanstep = 1; | ||
| 712 | |||
| 713 | clk_prepare_enable(host->clk); | ||
| 714 | host->enabled = 1; | ||
| 715 | |||
| 716 | err: | ||
| 717 | if (ret) | ||
| 718 | mxsfb_disable_axi_clk(host); | ||
| 719 | |||
| 720 | return ret; | ||
| 721 | } | ||
| 722 | |||
| 723 | static int mxsfb_init_fbinfo_dt(struct fb_info *fb_info, | ||
| 724 | struct fb_videomode *vmode) | ||
| 725 | { | ||
| 726 | struct mxsfb_info *host = fb_info->par; | ||
| 727 | struct fb_var_screeninfo *var = &fb_info->var; | ||
| 728 | struct device *dev = &host->pdev->dev; | ||
| 729 | struct device_node *np = host->pdev->dev.of_node; | ||
| 730 | struct device_node *display_np; | ||
| 731 | struct videomode vm; | ||
| 732 | u32 width; | ||
| 733 | int ret; | ||
| 734 | |||
| 735 | display_np = of_parse_phandle(np, "display", 0); | ||
| 736 | if (!display_np) { | ||
| 737 | dev_err(dev, "failed to find display phandle\n"); | ||
| 738 | return -ENOENT; | ||
| 739 | } | ||
| 740 | |||
| 741 | ret = of_property_read_u32(display_np, "bus-width", &width); | ||
| 742 | if (ret < 0) { | ||
| 743 | dev_err(dev, "failed to get property bus-width\n"); | ||
| 744 | goto put_display_node; | ||
| 745 | } | ||
| 746 | |||
| 747 | switch (width) { | ||
| 748 | case 8: | ||
| 749 | host->ld_intf_width = STMLCDIF_8BIT; | ||
| 750 | break; | ||
| 751 | case 16: | ||
| 752 | host->ld_intf_width = STMLCDIF_16BIT; | ||
| 753 | break; | ||
| 754 | case 18: | ||
| 755 | host->ld_intf_width = STMLCDIF_18BIT; | ||
| 756 | break; | ||
| 757 | case 24: | ||
| 758 | host->ld_intf_width = STMLCDIF_24BIT; | ||
| 759 | break; | ||
| 760 | default: | ||
| 761 | dev_err(dev, "invalid bus-width value\n"); | ||
| 762 | ret = -EINVAL; | ||
| 763 | goto put_display_node; | ||
| 764 | } | ||
| 765 | |||
| 766 | ret = of_property_read_u32(display_np, "bits-per-pixel", | ||
| 767 | &var->bits_per_pixel); | ||
| 768 | if (ret < 0) { | ||
| 769 | dev_err(dev, "failed to get property bits-per-pixel\n"); | ||
| 770 | goto put_display_node; | ||
| 771 | } | ||
| 772 | |||
| 773 | ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE); | ||
| 774 | if (ret) { | ||
| 775 | dev_err(dev, "failed to get videomode from DT\n"); | ||
| 776 | goto put_display_node; | ||
| 777 | } | ||
| 778 | |||
| 779 | ret = fb_videomode_from_videomode(&vm, vmode); | ||
| 780 | if (ret < 0) | ||
| 781 | goto put_display_node; | ||
| 782 | |||
| 783 | if (vm.flags & DISPLAY_FLAGS_DE_HIGH) | ||
| 784 | host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; | ||
| 785 | |||
| 786 | /* | ||
| 787 | * The PIXDATA flags of the display_flags enum are controller | ||
| 788 | * centric, e.g. NEGEDGE means drive data on negative edge. | ||
| 789 | * However, the drivers flag is display centric: Sample the | ||
| 790 | * data on negative (falling) edge. Therefore, check for the | ||
| 791 | * POSEDGE flag: | ||
| 792 | * drive on positive edge => sample on negative edge | ||
| 793 | */ | ||
| 794 | if (vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) | ||
| 795 | host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT; | ||
| 796 | |||
| 797 | put_display_node: | ||
| 798 | of_node_put(display_np); | ||
| 799 | return ret; | ||
| 800 | } | ||
| 801 | |||
| 802 | static int mxsfb_init_fbinfo(struct fb_info *fb_info, | ||
| 803 | struct fb_videomode *vmode) | ||
| 804 | { | ||
| 805 | int ret; | ||
| 806 | struct mxsfb_info *host = fb_info->par; | ||
| 807 | struct device *dev = &host->pdev->dev; | ||
| 808 | struct fb_var_screeninfo *var = &fb_info->var; | ||
| 809 | dma_addr_t fb_phys; | ||
| 810 | void *fb_virt; | ||
| 811 | unsigned fb_size; | ||
| 812 | |||
| 813 | fb_info->fbops = &mxsfb_ops; | ||
| 814 | fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; | ||
| 815 | strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id)); | ||
| 816 | fb_info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 817 | fb_info->fix.ypanstep = 1; | ||
| 818 | fb_info->fix.visual = FB_VISUAL_TRUECOLOR, | ||
| 819 | fb_info->fix.accel = FB_ACCEL_NONE; | ||
| 820 | |||
| 821 | ret = mxsfb_init_fbinfo_dt(fb_info, vmode); | ||
| 822 | if (ret) | ||
| 823 | return ret; | ||
| 824 | |||
| 825 | var->nonstd = 0; | ||
| 826 | var->activate = FB_ACTIVATE_NOW; | ||
| 827 | var->accel_flags = 0; | ||
| 828 | var->vmode = FB_VMODE_NONINTERLACED; | ||
| 829 | |||
| 830 | /* Memory allocation for framebuffer */ | ||
| 831 | fb_size = SZ_2M; | ||
| 832 | fb_virt = dma_alloc_wc(dev, PAGE_ALIGN(fb_size), &fb_phys, GFP_KERNEL); | ||
| 833 | if (!fb_virt) | ||
| 834 | return -ENOMEM; | ||
| 835 | |||
| 836 | fb_info->fix.smem_start = fb_phys; | ||
| 837 | fb_info->screen_base = fb_virt; | ||
| 838 | fb_info->screen_size = fb_info->fix.smem_len = fb_size; | ||
| 839 | |||
| 840 | if (mxsfb_restore_mode(fb_info, vmode)) | ||
| 841 | memset(fb_virt, 0, fb_size); | ||
| 842 | |||
| 843 | return 0; | ||
| 844 | } | ||
| 845 | |||
| 846 | static void mxsfb_free_videomem(struct fb_info *fb_info) | ||
| 847 | { | ||
| 848 | struct mxsfb_info *host = fb_info->par; | ||
| 849 | struct device *dev = &host->pdev->dev; | ||
| 850 | |||
| 851 | dma_free_wc(dev, fb_info->screen_size, fb_info->screen_base, | ||
| 852 | fb_info->fix.smem_start); | ||
| 853 | } | ||
| 854 | |||
| 855 | static const struct platform_device_id mxsfb_devtype[] = { | ||
| 856 | { | ||
| 857 | .name = "imx23-fb", | ||
| 858 | .driver_data = MXSFB_V3, | ||
| 859 | }, { | ||
| 860 | .name = "imx28-fb", | ||
| 861 | .driver_data = MXSFB_V4, | ||
| 862 | }, { | ||
| 863 | /* sentinel */ | ||
| 864 | } | ||
| 865 | }; | ||
| 866 | MODULE_DEVICE_TABLE(platform, mxsfb_devtype); | ||
| 867 | |||
| 868 | static const struct of_device_id mxsfb_dt_ids[] = { | ||
| 869 | { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], }, | ||
| 870 | { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], }, | ||
| 871 | { /* sentinel */ } | ||
| 872 | }; | ||
| 873 | MODULE_DEVICE_TABLE(of, mxsfb_dt_ids); | ||
| 874 | |||
| 875 | static int mxsfb_probe(struct platform_device *pdev) | ||
| 876 | { | ||
| 877 | const struct of_device_id *of_id = | ||
| 878 | of_match_device(mxsfb_dt_ids, &pdev->dev); | ||
| 879 | struct resource *res; | ||
| 880 | struct mxsfb_info *host; | ||
| 881 | struct fb_info *fb_info; | ||
| 882 | struct fb_videomode *mode; | ||
| 883 | int ret; | ||
| 884 | |||
| 885 | if (of_id) | ||
| 886 | pdev->id_entry = of_id->data; | ||
| 887 | |||
| 888 | fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev); | ||
| 889 | if (!fb_info) { | ||
| 890 | dev_err(&pdev->dev, "Failed to allocate fbdev\n"); | ||
| 891 | return -ENOMEM; | ||
| 892 | } | ||
| 893 | |||
| 894 | mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode), | ||
| 895 | GFP_KERNEL); | ||
| 896 | if (mode == NULL) | ||
| 897 | return -ENOMEM; | ||
| 898 | |||
| 899 | host = fb_info->par; | ||
| 900 | |||
| 901 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 902 | host->base = devm_ioremap_resource(&pdev->dev, res); | ||
| 903 | if (IS_ERR(host->base)) { | ||
| 904 | ret = PTR_ERR(host->base); | ||
| 905 | goto fb_release; | ||
| 906 | } | ||
| 907 | |||
| 908 | host->pdev = pdev; | ||
| 909 | platform_set_drvdata(pdev, host); | ||
| 910 | |||
| 911 | host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; | ||
| 912 | |||
| 913 | host->clk = devm_clk_get(&host->pdev->dev, NULL); | ||
| 914 | if (IS_ERR(host->clk)) { | ||
| 915 | ret = PTR_ERR(host->clk); | ||
| 916 | goto fb_release; | ||
| 917 | } | ||
| 918 | |||
| 919 | host->clk_axi = devm_clk_get(&host->pdev->dev, "axi"); | ||
| 920 | if (IS_ERR(host->clk_axi)) | ||
| 921 | host->clk_axi = NULL; | ||
| 922 | |||
| 923 | host->clk_disp_axi = devm_clk_get(&host->pdev->dev, "disp_axi"); | ||
| 924 | if (IS_ERR(host->clk_disp_axi)) | ||
| 925 | host->clk_disp_axi = NULL; | ||
| 926 | |||
| 927 | host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd"); | ||
| 928 | if (IS_ERR(host->reg_lcd)) | ||
| 929 | host->reg_lcd = NULL; | ||
| 930 | |||
| 931 | #if defined(CONFIG_FB_PRE_INIT_FB) | ||
| 932 | host->pre_init = 1; | ||
| 933 | #endif | ||
| 934 | |||
| 935 | fb_info->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32), | ||
| 936 | GFP_KERNEL); | ||
| 937 | if (!fb_info->pseudo_palette) { | ||
| 938 | ret = -ENOMEM; | ||
| 939 | goto fb_release; | ||
| 940 | } | ||
| 941 | |||
| 942 | ret = mxsfb_init_fbinfo(fb_info, mode); | ||
| 943 | if (ret != 0) | ||
| 944 | goto fb_release; | ||
| 945 | |||
| 946 | fb_videomode_to_var(&fb_info->var, mode); | ||
| 947 | |||
| 948 | /* init the color fields */ | ||
| 949 | mxsfb_check_var(&fb_info->var, fb_info); | ||
| 950 | |||
| 951 | platform_set_drvdata(pdev, fb_info); | ||
| 952 | |||
| 953 | ret = register_framebuffer(fb_info); | ||
| 954 | if (ret != 0) { | ||
| 955 | dev_err(&pdev->dev,"Failed to register framebuffer\n"); | ||
| 956 | goto fb_destroy; | ||
| 957 | } | ||
| 958 | |||
| 959 | if (!host->enabled) { | ||
| 960 | mxsfb_enable_axi_clk(host); | ||
| 961 | writel(0, host->base + LCDC_CTRL); | ||
| 962 | mxsfb_disable_axi_clk(host); | ||
| 963 | mxsfb_set_par(fb_info); | ||
| 964 | mxsfb_enable_controller(fb_info); | ||
| 965 | } | ||
| 966 | |||
| 967 | host->pre_init = 0; | ||
| 968 | dev_info(&pdev->dev, "initialized\n"); | ||
| 969 | |||
| 970 | return 0; | ||
| 971 | |||
| 972 | fb_destroy: | ||
| 973 | if (host->enabled) | ||
| 974 | clk_disable_unprepare(host->clk); | ||
| 975 | fb_release: | ||
| 976 | framebuffer_release(fb_info); | ||
| 977 | |||
| 978 | return ret; | ||
| 979 | } | ||
| 980 | |||
| 981 | static int mxsfb_remove(struct platform_device *pdev) | ||
| 982 | { | ||
| 983 | struct fb_info *fb_info = platform_get_drvdata(pdev); | ||
| 984 | struct mxsfb_info *host = fb_info->par; | ||
| 985 | |||
| 986 | if (host->enabled) | ||
| 987 | mxsfb_disable_controller(fb_info); | ||
| 988 | |||
| 989 | unregister_framebuffer(fb_info); | ||
| 990 | mxsfb_free_videomem(fb_info); | ||
| 991 | |||
| 992 | framebuffer_release(fb_info); | ||
| 993 | |||
| 994 | return 0; | ||
| 995 | } | ||
| 996 | |||
| 997 | static void mxsfb_shutdown(struct platform_device *pdev) | ||
| 998 | { | ||
| 999 | struct fb_info *fb_info = platform_get_drvdata(pdev); | ||
| 1000 | struct mxsfb_info *host = fb_info->par; | ||
| 1001 | |||
| 1002 | mxsfb_enable_axi_clk(host); | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * Force stop the LCD controller as keeping it running during reboot | ||
| 1006 | * might interfere with the BootROM's boot mode pads sampling. | ||
| 1007 | */ | ||
| 1008 | writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); | ||
| 1009 | |||
| 1010 | mxsfb_disable_axi_clk(host); | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | static struct platform_driver mxsfb_driver = { | ||
| 1014 | .probe = mxsfb_probe, | ||
| 1015 | .remove = mxsfb_remove, | ||
| 1016 | .shutdown = mxsfb_shutdown, | ||
| 1017 | .id_table = mxsfb_devtype, | ||
| 1018 | .driver = { | ||
| 1019 | .name = DRIVER_NAME, | ||
| 1020 | .of_match_table = mxsfb_dt_ids, | ||
| 1021 | }, | ||
| 1022 | }; | ||
| 1023 | |||
| 1024 | module_platform_driver(mxsfb_driver); | ||
| 1025 | |||
| 1026 | MODULE_DESCRIPTION("Freescale mxs framebuffer driver"); | ||
| 1027 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | ||
| 1028 | MODULE_LICENSE("GPL"); | ||
| @@ -2122,14 +2122,7 @@ static void neofb_remove(struct pci_dev *dev) · 2121 unmodified lines | |||
| 2122 | DBG("neofb_remove"); | 2122 | DBG("neofb_remove"); |
| 2123 | 2123 | ||
| 2124 | if (info) { | 2124 | if (info) { |
| 2125 | /* | 2125 | unregister_framebuffer(info); |
| 2126 | * If unregister_framebuffer fails, then | ||
| 2127 | * we will be leaving hooks that could cause | ||
| 2128 | * oopsen laying around. | ||
| 2129 | */ | ||
| 2130 | if (unregister_framebuffer(info)) | ||
| 2131 | printk(KERN_WARNING | ||
| 2132 | "neofb: danger danger! Oopsen imminent!\n"); | ||
| 2133 | 2126 | ||
| 2134 | neo_unmap_video(info); | 2127 | neo_unmap_video(info); |
| 2135 | fb_destroy_modedb(info->monspecs.modedb); | 2128 | fb_destroy_modedb(info->monspecs.modedb); |
| @@ -1502,8 +1502,6 @@ static int planes_init(struct omapfb_device *fbdev) · 1501 unmodified lines | |||
| 1502 | fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct), | 1502 | fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct), |
| 1503 | fbdev->dev); | 1503 | fbdev->dev); |
| 1504 | if (fbi == NULL) { | 1504 | if (fbi == NULL) { |
| 1505 | dev_err(fbdev->dev, | ||
| 1506 | "unable to allocate memory for plane info\n"); | ||
| 1507 | planes_cleanup(fbdev); | 1505 | planes_cleanup(fbdev); |
| 1508 | return -ENOMEM; | 1506 | return -ENOMEM; |
| 1509 | } | 1507 | } |
| @@ -39,18 +39,6 @@ config FB_OMAP2_DSS_DPI · 38 unmodified lines | |||
| 39 | help | 39 | help |
| 40 | DPI Interface. This is the Parallel Display Interface. | 40 | DPI Interface. This is the Parallel Display Interface. |
| 41 | 41 | ||
| 42 | config FB_OMAP2_DSS_RFBI | ||
| 43 | bool "RFBI support" | ||
| 44 | depends on BROKEN | ||
| 45 | help | ||
| 46 | MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas | ||
| 47 | Instrument's terminology). | ||
| 48 | |||
| 49 | DBI is a bus between the host processor and a peripheral, | ||
| 50 | such as a display or a framebuffer chip. | ||
| 51 | |||
| 52 | See http://www.mipi.org/ for DBI specifications. | ||
| 53 | |||
| 54 | config FB_OMAP2_DSS_VENC | 42 | config FB_OMAP2_DSS_VENC |
| 55 | bool "VENC support" | 43 | bool "VENC support" |
| 56 | default y | 44 | default y |
| @@ -8,7 +8,6 @@ omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ · 7 unmodified lines | |||
| 8 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ | 8 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ |
| 9 | dispc-compat.o display-sysfs.o | 9 | dispc-compat.o display-sysfs.o |
| 10 | omapdss-$(CONFIG_FB_OMAP2_DSS_DPI) += dpi.o | 10 | omapdss-$(CONFIG_FB_OMAP2_DSS_DPI) += dpi.o |
| 11 | omapdss-$(CONFIG_FB_OMAP2_DSS_RFBI) += rfbi.o | ||
| 12 | omapdss-$(CONFIG_FB_OMAP2_DSS_VENC) += venc.o | 11 | omapdss-$(CONFIG_FB_OMAP2_DSS_VENC) += venc.o |
| 13 | omapdss-$(CONFIG_FB_OMAP2_DSS_SDI) += sdi.o | 12 | omapdss-$(CONFIG_FB_OMAP2_DSS_SDI) += sdi.o |
| 14 | omapdss-$(CONFIG_FB_OMAP2_DSS_DSI) += dsi.o | 13 | omapdss-$(CONFIG_FB_OMAP2_DSS_DSI) += dsi.o |
| @@ -207,9 +207,6 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = { · 206 unmodified lines | |||
| 207 | #ifdef CONFIG_FB_OMAP2_DSS_SDI | 207 | #ifdef CONFIG_FB_OMAP2_DSS_SDI |
| 208 | sdi_init_platform_driver, | 208 | sdi_init_platform_driver, |
| 209 | #endif | 209 | #endif |
| 210 | #ifdef CONFIG_FB_OMAP2_DSS_RFBI | ||
| 211 | rfbi_init_platform_driver, | ||
| 212 | #endif | ||
| 213 | #ifdef CONFIG_FB_OMAP2_DSS_VENC | 210 | #ifdef CONFIG_FB_OMAP2_DSS_VENC |
| 214 | venc_init_platform_driver, | 211 | venc_init_platform_driver, |
| 215 | #endif | 212 | #endif |
| @@ -231,9 +228,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) = { · 15 unmodified lines | |||
| 231 | #ifdef CONFIG_FB_OMAP2_DSS_VENC | 228 | #ifdef CONFIG_FB_OMAP2_DSS_VENC |
| 232 | venc_uninit_platform_driver, | 229 | venc_uninit_platform_driver, |
| 233 | #endif | 230 | #endif |
| 234 | #ifdef CONFIG_FB_OMAP2_DSS_RFBI | ||
| 235 | rfbi_uninit_platform_driver, | ||
| 236 | #endif | ||
| 237 | #ifdef CONFIG_FB_OMAP2_DSS_SDI | 231 | #ifdef CONFIG_FB_OMAP2_DSS_SDI |
| 238 | sdi_uninit_platform_driver, | 232 | sdi_uninit_platform_driver, |
| 239 | #endif | 233 | #endif |
| @@ -461,10 +461,6 @@ void hdmi4_uninit_platform_driver(void); · 460 unmodified lines | |||
| 461 | int hdmi5_init_platform_driver(void) __init; | 461 | int hdmi5_init_platform_driver(void) __init; |
| 462 | void hdmi5_uninit_platform_driver(void); | 462 | void hdmi5_uninit_platform_driver(void); |
| 463 | 463 | ||
| 464 | /* RFBI */ | ||
| 465 | int rfbi_init_platform_driver(void) __init; | ||
| 466 | void rfbi_uninit_platform_driver(void); | ||
| 467 | |||
| 468 | 464 | ||
| 469 | #ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS | 465 | #ifdef CONFIG_FB_OMAP2_DSS_COLLECT_IRQ_STATS |
| 470 | static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr) | 466 | static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr) |
| @@ -1,1067 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * linux/drivers/video/omap2/dss/rfbi.c | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009 Nokia Corporation | ||
| 6 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | ||
| 7 | * | ||
| 8 | * Some code and ideas taken from drivers/video/omap/ driver | ||
| 9 | * by Imre Deak. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define DSS_SUBSYS_NAME "RFBI" | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/dma-mapping.h> | ||
| 16 | #include <linux/export.h> | ||
| 17 | #include <linux/vmalloc.h> | ||
| 18 | #include <linux/clk.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/kfifo.h> | ||
| 22 | #include <linux/ktime.h> | ||
| 23 | #include <linux/hrtimer.h> | ||
| 24 | #include <linux/seq_file.h> | ||
| 25 | #include <linux/semaphore.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | #include <linux/pm_runtime.h> | ||
| 28 | #include <linux/component.h> | ||
| 29 | |||
| 30 | #include <video/omapfb_dss.h> | ||
| 31 | #include "dss.h" | ||
| 32 | |||
| 33 | struct rfbi_reg { u16 idx; }; | ||
| 34 | |||
| 35 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) | ||
| 36 | |||
| 37 | #define RFBI_REVISION RFBI_REG(0x0000) | ||
| 38 | #define RFBI_SYSCONFIG RFBI_REG(0x0010) | ||
| 39 | #define RFBI_SYSSTATUS RFBI_REG(0x0014) | ||
| 40 | #define RFBI_CONTROL RFBI_REG(0x0040) | ||
| 41 | #define RFBI_PIXEL_CNT RFBI_REG(0x0044) | ||
| 42 | #define RFBI_LINE_NUMBER RFBI_REG(0x0048) | ||
| 43 | #define RFBI_CMD RFBI_REG(0x004c) | ||
| 44 | #define RFBI_PARAM RFBI_REG(0x0050) | ||
| 45 | #define RFBI_DATA RFBI_REG(0x0054) | ||
| 46 | #define RFBI_READ RFBI_REG(0x0058) | ||
| 47 | #define RFBI_STATUS RFBI_REG(0x005c) | ||
| 48 | |||
| 49 | #define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18) | ||
| 50 | #define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18) | ||
| 51 | #define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18) | ||
| 52 | #define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18) | ||
| 53 | #define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18) | ||
| 54 | #define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18) | ||
| 55 | |||
| 56 | #define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) | ||
| 57 | #define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) | ||
| 58 | |||
| 59 | #define REG_FLD_MOD(idx, val, start, end) \ | ||
| 60 | rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) | ||
| 61 | |||
| 62 | enum omap_rfbi_cycleformat { | ||
| 63 | OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, | ||
| 64 | OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, | ||
| 65 | OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2, | ||
| 66 | OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3, | ||
| 67 | }; | ||
| 68 | |||
| 69 | enum omap_rfbi_datatype { | ||
| 70 | OMAP_DSS_RFBI_DATATYPE_12 = 0, | ||
| 71 | OMAP_DSS_RFBI_DATATYPE_16 = 1, | ||
| 72 | OMAP_DSS_RFBI_DATATYPE_18 = 2, | ||
| 73 | OMAP_DSS_RFBI_DATATYPE_24 = 3, | ||
| 74 | }; | ||
| 75 | |||
| 76 | enum omap_rfbi_parallelmode { | ||
| 77 | OMAP_DSS_RFBI_PARALLELMODE_8 = 0, | ||
| 78 | OMAP_DSS_RFBI_PARALLELMODE_9 = 1, | ||
| 79 | OMAP_DSS_RFBI_PARALLELMODE_12 = 2, | ||
| 80 | OMAP_DSS_RFBI_PARALLELMODE_16 = 3, | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int rfbi_convert_timings(struct rfbi_timings *t); | ||
| 84 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | ||
| 85 | |||
| 86 | static struct { | ||
| 87 | struct platform_device *pdev; | ||
| 88 | void __iomem *base; | ||
| 89 | |||
| 90 | unsigned long l4_khz; | ||
| 91 | |||
| 92 | enum omap_rfbi_datatype datatype; | ||
| 93 | enum omap_rfbi_parallelmode parallelmode; | ||
| 94 | |||
| 95 | enum omap_rfbi_te_mode te_mode; | ||
| 96 | int te_enabled; | ||
| 97 | |||
| 98 | void (*framedone_callback)(void *data); | ||
| 99 | void *framedone_callback_data; | ||
| 100 | |||
| 101 | struct omap_dss_device *dssdev[2]; | ||
| 102 | |||
| 103 | struct semaphore bus_lock; | ||
| 104 | |||
| 105 | struct omap_video_timings timings; | ||
| 106 | int pixel_size; | ||
| 107 | int data_lines; | ||
| 108 | struct rfbi_timings intf_timings; | ||
| 109 | |||
| 110 | struct omap_dss_device output; | ||
| 111 | } rfbi; | ||
| 112 | |||
| 113 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | ||
| 114 | { | ||
| 115 | __raw_writel(val, rfbi.base + idx.idx); | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline u32 rfbi_read_reg(const struct rfbi_reg idx) | ||
| 119 | { | ||
| 120 | return __raw_readl(rfbi.base + idx.idx); | ||
| 121 | } | ||
| 122 | |||
| 123 | static int rfbi_runtime_get(void) | ||
| 124 | { | ||
| 125 | int r; | ||
| 126 | |||
| 127 | DSSDBG("rfbi_runtime_get\n"); | ||
| 128 | |||
| 129 | r = pm_runtime_get_sync(&rfbi.pdev->dev); | ||
| 130 | WARN_ON(r < 0); | ||
| 131 | return r < 0 ? r : 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static void rfbi_runtime_put(void) | ||
| 135 | { | ||
| 136 | int r; | ||
| 137 | |||
| 138 | DSSDBG("rfbi_runtime_put\n"); | ||
| 139 | |||
| 140 | r = pm_runtime_put_sync(&rfbi.pdev->dev); | ||
| 141 | WARN_ON(r < 0 && r != -ENOSYS); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void rfbi_bus_lock(void) | ||
| 145 | { | ||
| 146 | down(&rfbi.bus_lock); | ||
| 147 | } | ||
| 148 | |||
| 149 | static void rfbi_bus_unlock(void) | ||
| 150 | { | ||
| 151 | up(&rfbi.bus_lock); | ||
| 152 | } | ||
| 153 | |||
| 154 | static void rfbi_write_command(const void *buf, u32 len) | ||
| 155 | { | ||
| 156 | switch (rfbi.parallelmode) { | ||
| 157 | case OMAP_DSS_RFBI_PARALLELMODE_8: | ||
| 158 | { | ||
| 159 | const u8 *b = buf; | ||
| 160 | for (; len; len--) | ||
| 161 | rfbi_write_reg(RFBI_CMD, *b++); | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | |||
| 165 | case OMAP_DSS_RFBI_PARALLELMODE_16: | ||
| 166 | { | ||
| 167 | const u16 *w = buf; | ||
| 168 | BUG_ON(len & 1); | ||
| 169 | for (; len; len -= 2) | ||
| 170 | rfbi_write_reg(RFBI_CMD, *w++); | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | |||
| 174 | case OMAP_DSS_RFBI_PARALLELMODE_9: | ||
| 175 | case OMAP_DSS_RFBI_PARALLELMODE_12: | ||
| 176 | default: | ||
| 177 | BUG(); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | static void rfbi_read_data(void *buf, u32 len) | ||
| 182 | { | ||
| 183 | switch (rfbi.parallelmode) { | ||
| 184 | case OMAP_DSS_RFBI_PARALLELMODE_8: | ||
| 185 | { | ||
| 186 | u8 *b = buf; | ||
| 187 | for (; len; len--) { | ||
| 188 | rfbi_write_reg(RFBI_READ, 0); | ||
| 189 | *b++ = rfbi_read_reg(RFBI_READ); | ||
| 190 | } | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | |||
| 194 | case OMAP_DSS_RFBI_PARALLELMODE_16: | ||
| 195 | { | ||
| 196 | u16 *w = buf; | ||
| 197 | BUG_ON(len & ~1); | ||
| 198 | for (; len; len -= 2) { | ||
| 199 | rfbi_write_reg(RFBI_READ, 0); | ||
| 200 | *w++ = rfbi_read_reg(RFBI_READ); | ||
| 201 | } | ||
| 202 | break; | ||
| 203 | } | ||
| 204 | |||
| 205 | case OMAP_DSS_RFBI_PARALLELMODE_9: | ||
| 206 | case OMAP_DSS_RFBI_PARALLELMODE_12: | ||
| 207 | default: | ||
| 208 | BUG(); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | static void rfbi_write_data(const void *buf, u32 len) | ||
| 213 | { | ||
| 214 | switch (rfbi.parallelmode) { | ||
| 215 | case OMAP_DSS_RFBI_PARALLELMODE_8: | ||
| 216 | { | ||
| 217 | const u8 *b = buf; | ||
| 218 | for (; len; len--) | ||
| 219 | rfbi_write_reg(RFBI_PARAM, *b++); | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | |||
| 223 | case OMAP_DSS_RFBI_PARALLELMODE_16: | ||
| 224 | { | ||
| 225 | const u16 *w = buf; | ||
| 226 | BUG_ON(len & 1); | ||
| 227 | for (; len; len -= 2) | ||
| 228 | rfbi_write_reg(RFBI_PARAM, *w++); | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | |||
| 232 | case OMAP_DSS_RFBI_PARALLELMODE_9: | ||
| 233 | case OMAP_DSS_RFBI_PARALLELMODE_12: | ||
| 234 | default: | ||
| 235 | BUG(); | ||
| 236 | |||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | static void rfbi_write_pixels(const void __iomem *buf, int scr_width, | ||
| 241 | u16 x, u16 y, | ||
| 242 | u16 w, u16 h) | ||
| 243 | { | ||
| 244 | int start_offset = scr_width * y + x; | ||
| 245 | int horiz_offset = scr_width - w; | ||
| 246 | int i; | ||
| 247 | |||
| 248 | if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && | ||
| 249 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { | ||
| 250 | const u16 __iomem *pd = buf; | ||
| 251 | pd += start_offset; | ||
| 252 | |||
| 253 | for (; h; --h) { | ||
| 254 | for (i = 0; i < w; ++i) { | ||
| 255 | const u8 __iomem *b = (const u8 __iomem *)pd; | ||
| 256 | rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); | ||
| 257 | rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); | ||
| 258 | ++pd; | ||
| 259 | } | ||
| 260 | pd += horiz_offset; | ||
| 261 | } | ||
| 262 | } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 && | ||
| 263 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { | ||
| 264 | const u32 __iomem *pd = buf; | ||
| 265 | pd += start_offset; | ||
| 266 | |||
| 267 | for (; h; --h) { | ||
| 268 | for (i = 0; i < w; ++i) { | ||
| 269 | const u8 __iomem *b = (const u8 __iomem *)pd; | ||
| 270 | rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2)); | ||
| 271 | rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); | ||
| 272 | rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); | ||
| 273 | ++pd; | ||
| 274 | } | ||
| 275 | pd += horiz_offset; | ||
| 276 | } | ||
| 277 | } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && | ||
| 278 | rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) { | ||
| 279 | const u16 __iomem *pd = buf; | ||
| 280 | pd += start_offset; | ||
| 281 | |||
| 282 | for (; h; --h) { | ||
| 283 | for (i = 0; i < w; ++i) { | ||
| 284 | rfbi_write_reg(RFBI_PARAM, __raw_readw(pd)); | ||
| 285 | ++pd; | ||
| 286 | } | ||
| 287 | pd += horiz_offset; | ||
| 288 | } | ||
| 289 | } else { | ||
| 290 | BUG(); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | static int rfbi_transfer_area(struct omap_dss_device *dssdev, | ||
| 295 | void (*callback)(void *data), void *data) | ||
| 296 | { | ||
| 297 | u32 l; | ||
| 298 | int r; | ||
| 299 | struct omap_overlay_manager *mgr = rfbi.output.manager; | ||
| 300 | u16 width = rfbi.timings.x_res; | ||
| 301 | u16 height = rfbi.timings.y_res; | ||
| 302 | |||
| 303 | /*BUG_ON(callback == 0);*/ | ||
| 304 | BUG_ON(rfbi.framedone_callback != NULL); | ||
| 305 | |||
| 306 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | ||
| 307 | |||
| 308 | dss_mgr_set_timings(mgr, &rfbi.timings); | ||
| 309 | |||
| 310 | r = dss_mgr_enable(mgr); | ||
| 311 | if (r) | ||
| 312 | return r; | ||
| 313 | |||
| 314 | rfbi.framedone_callback = callback; | ||
| 315 | rfbi.framedone_callback_data = data; | ||
| 316 | |||
| 317 | rfbi_write_reg(RFBI_PIXEL_CNT, width * height); | ||
| 318 | |||
| 319 | l = rfbi_read_reg(RFBI_CONTROL); | ||
| 320 | l = FLD_MOD(l, 1, 0, 0); /* enable */ | ||
| 321 | if (!rfbi.te_enabled) | ||
| 322 | l = FLD_MOD(l, 1, 4, 4); /* ITE */ | ||
| 323 | |||
| 324 | rfbi_write_reg(RFBI_CONTROL, l); | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static void framedone_callback(void *data) | ||
| 330 | { | ||
| 331 | void (*callback)(void *data); | ||
| 332 | |||
| 333 | DSSDBG("FRAMEDONE\n"); | ||
| 334 | |||
| 335 | REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); | ||
| 336 | |||
| 337 | callback = rfbi.framedone_callback; | ||
| 338 | rfbi.framedone_callback = NULL; | ||
| 339 | |||
| 340 | if (callback != NULL) | ||
| 341 | callback(rfbi.framedone_callback_data); | ||
| 342 | } | ||
| 343 | |||
| 344 | #if 1 /* VERBOSE */ | ||
| 345 | static void rfbi_print_timings(void) | ||
| 346 | { | ||
| 347 | u32 l; | ||
| 348 | u32 time; | ||
| 349 | |||
| 350 | l = rfbi_read_reg(RFBI_CONFIG(0)); | ||
| 351 | time = 1000000000 / rfbi.l4_khz; | ||
| 352 | if (l & (1 << 4)) | ||
| 353 | time *= 2; | ||
| 354 | |||
| 355 | DSSDBG("Tick time %u ps\n", time); | ||
| 356 | l = rfbi_read_reg(RFBI_ONOFF_TIME(0)); | ||
| 357 | DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " | ||
| 358 | "REONTIME %d, REOFFTIME %d\n", | ||
| 359 | l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, | ||
| 360 | (l >> 20) & 0x0f, (l >> 24) & 0x3f); | ||
| 361 | |||
| 362 | l = rfbi_read_reg(RFBI_CYCLE_TIME(0)); | ||
| 363 | DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " | ||
| 364 | "ACCESSTIME %d\n", | ||
| 365 | (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, | ||
| 366 | (l >> 22) & 0x3f); | ||
| 367 | } | ||
| 368 | #else | ||
| 369 | static void rfbi_print_timings(void) {} | ||
| 370 | #endif | ||
| 371 | |||
| 372 | |||
| 373 | |||
| 374 | |||
| 375 | static u32 extif_clk_period; | ||
| 376 | |||
| 377 | static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) | ||
| 378 | { | ||
| 379 | int bus_tick = extif_clk_period * div; | ||
| 380 | return (ps + bus_tick - 1) / bus_tick * bus_tick; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int calc_reg_timing(struct rfbi_timings *t, int div) | ||
| 384 | { | ||
| 385 | t->clk_div = div; | ||
| 386 | |||
| 387 | t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div); | ||
| 388 | |||
| 389 | t->we_on_time = round_to_extif_ticks(t->we_on_time, div); | ||
| 390 | t->we_off_time = round_to_extif_ticks(t->we_off_time, div); | ||
| 391 | t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div); | ||
| 392 | |||
| 393 | t->re_on_time = round_to_extif_ticks(t->re_on_time, div); | ||
| 394 | t->re_off_time = round_to_extif_ticks(t->re_off_time, div); | ||
| 395 | t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div); | ||
| 396 | |||
| 397 | t->access_time = round_to_extif_ticks(t->access_time, div); | ||
| 398 | t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div); | ||
| 399 | t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div); | ||
| 400 | |||
| 401 | DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n", | ||
| 402 | t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); | ||
| 403 | DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n", | ||
| 404 | t->we_on_time, t->we_off_time, t->re_cycle_time, | ||
| 405 | t->we_cycle_time); | ||
| 406 | DSSDBG("[reg]rdaccess %d cspulse %d\n", | ||
| 407 | t->access_time, t->cs_pulse_width); | ||
| 408 | |||
| 409 | return rfbi_convert_timings(t); | ||
| 410 | } | ||
| 411 | |||
| 412 | static int calc_extif_timings(struct rfbi_timings *t) | ||
| 413 | { | ||
| 414 | u32 max_clk_div; | ||
| 415 | int div; | ||
| 416 | |||
| 417 | rfbi_get_clk_info(&extif_clk_period, &max_clk_div); | ||
| 418 | for (div = 1; div <= max_clk_div; div++) { | ||
| 419 | if (calc_reg_timing(t, div) == 0) | ||
| 420 | break; | ||
| 421 | } | ||
| 422 | |||
| 423 | if (div <= max_clk_div) | ||
| 424 | return 0; | ||
| 425 | |||
| 426 | DSSERR("can't setup timings\n"); | ||
| 427 | return -1; | ||
| 428 | } | ||
| 429 | |||
| 430 | |||
| 431 | static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) | ||
| 432 | { | ||
| 433 | int r; | ||
| 434 | |||
| 435 | if (!t->converted) { | ||
| 436 | r = calc_extif_timings(t); | ||
| 437 | if (r < 0) | ||
| 438 | DSSERR("Failed to calc timings\n"); | ||
| 439 | } | ||
| 440 | |||
| 441 | BUG_ON(!t->converted); | ||
| 442 | |||
| 443 | rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); | ||
| 444 | rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); | ||
| 445 | |||
| 446 | /* TIMEGRANULARITY */ | ||
| 447 | REG_FLD_MOD(RFBI_CONFIG(rfbi_module), | ||
| 448 | (t->tim[2] ? 1 : 0), 4, 4); | ||
| 449 | |||
| 450 | rfbi_print_timings(); | ||
| 451 | } | ||
| 452 | |||
| 453 | static int ps_to_rfbi_ticks(int time, int div) | ||
| 454 | { | ||
| 455 | unsigned long tick_ps; | ||
| 456 | int ret; | ||
| 457 | |||
| 458 | /* Calculate in picosecs to yield more exact results */ | ||
| 459 | tick_ps = 1000000000 / (rfbi.l4_khz) * div; | ||
| 460 | |||
| 461 | ret = (time + tick_ps - 1) / tick_ps; | ||
| 462 | |||
| 463 | return ret; | ||
| 464 | } | ||
| 465 | |||
| 466 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) | ||
| 467 | { | ||
| 468 | *clk_period = 1000000000 / rfbi.l4_khz; | ||
| 469 | *max_clk_div = 2; | ||
| 470 | } | ||
| 471 | |||
| 472 | static int rfbi_convert_timings(struct rfbi_timings *t) | ||
| 473 | { | ||
| 474 | u32 l; | ||
| 475 | int reon, reoff, weon, weoff, cson, csoff, cs_pulse; | ||
| 476 | int actim, recyc, wecyc; | ||
| 477 | int div = t->clk_div; | ||
| 478 | |||
| 479 | if (div <= 0 || div > 2) | ||
| 480 | return -1; | ||
| 481 | |||
| 482 | /* Make sure that after conversion it still holds that: | ||
| 483 | * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, | ||
| 484 | * csoff > cson, csoff >= max(weoff, reoff), actim > reon | ||
| 485 | */ | ||
| 486 | weon = ps_to_rfbi_ticks(t->we_on_time, div); | ||
| 487 | weoff = ps_to_rfbi_ticks(t->we_off_time, div); | ||
| 488 | if (weoff <= weon) | ||
| 489 | weoff = weon + 1; | ||
| 490 | if (weon > 0x0f) | ||
| 491 | return -1; | ||
| 492 | if (weoff > 0x3f) | ||
| 493 | return -1; | ||
| 494 | |||
| 495 | reon = ps_to_rfbi_ticks(t->re_on_time, div); | ||
| 496 | reoff = ps_to_rfbi_ticks(t->re_off_time, div); | ||
| 497 | if (reoff <= reon) | ||
| 498 | reoff = reon + 1; | ||
| 499 | if (reon > 0x0f) | ||
| 500 | return -1; | ||
| 501 | if (reoff > 0x3f) | ||
| 502 | return -1; | ||
| 503 | |||
| 504 | cson = ps_to_rfbi_ticks(t->cs_on_time, div); | ||
| 505 | csoff = ps_to_rfbi_ticks(t->cs_off_time, div); | ||
| 506 | if (csoff <= cson) | ||
| 507 | csoff = cson + 1; | ||
| 508 | if (csoff < max(weoff, reoff)) | ||
| 509 | csoff = max(weoff, reoff); | ||
| 510 | if (cson > 0x0f) | ||
| 511 | return -1; | ||
| 512 | if (csoff > 0x3f) | ||
| 513 | return -1; | ||
| 514 | |||
| 515 | l = cson; | ||
| 516 | l |= csoff << 4; | ||
| 517 | l |= weon << 10; | ||
| 518 | l |= weoff << 14; | ||
| 519 | l |= reon << 20; | ||
| 520 | l |= reoff << 24; | ||
| 521 | |||
| 522 | t->tim[0] = l; | ||
| 523 | |||
| 524 | actim = ps_to_rfbi_ticks(t->access_time, div); | ||
| 525 | if (actim <= reon) | ||
| 526 | actim = reon + 1; | ||
| 527 | if (actim > 0x3f) | ||
| 528 | return -1; | ||
| 529 | |||
| 530 | wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); | ||
| 531 | if (wecyc < weoff) | ||
| 532 | wecyc = weoff; | ||
| 533 | if (wecyc > 0x3f) | ||
| 534 | return -1; | ||
| 535 | |||
| 536 | recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); | ||
| 537 | if (recyc < reoff) | ||
| 538 | recyc = reoff; | ||
| 539 | if (recyc > 0x3f) | ||
| 540 | return -1; | ||
| 541 | |||
| 542 | cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); | ||
| 543 | if (cs_pulse > 0x3f) | ||
| 544 | return -1; | ||
| 545 | |||
| 546 | l = wecyc; | ||
| 547 | l |= recyc << 6; | ||
| 548 | l |= cs_pulse << 12; | ||
| 549 | l |= actim << 22; | ||
| 550 | |||
| 551 | t->tim[1] = l; | ||
| 552 | |||
| 553 | t->tim[2] = div - 1; | ||
| 554 | |||
| 555 | t->converted = 1; | ||
| 556 | |||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* xxx FIX module selection missing */ | ||
| 561 | static int rfbi_setup_te(enum omap_rfbi_te_mode mode, | ||
| 562 | unsigned hs_pulse_time, unsigned vs_pulse_time, | ||
| 563 | int hs_pol_inv, int vs_pol_inv, int extif_div) | ||
| 564 | { | ||
| 565 | int hs, vs; | ||
| 566 | int min; | ||
| 567 | u32 l; | ||
| 568 | |||
| 569 | hs = ps_to_rfbi_ticks(hs_pulse_time, 1); | ||
| 570 | vs = ps_to_rfbi_ticks(vs_pulse_time, 1); | ||
| 571 | if (hs < 2) | ||
| 572 | return -EDOM; | ||
| 573 | if (mode == OMAP_DSS_RFBI_TE_MODE_2) | ||
| 574 | min = 2; | ||
| 575 | else /* OMAP_DSS_RFBI_TE_MODE_1 */ | ||
| 576 | min = 4; | ||
| 577 | if (vs < min) | ||
| 578 | return -EDOM; | ||
| 579 | if (vs == hs) | ||
| 580 | return -EINVAL; | ||
| 581 | rfbi.te_mode = mode; | ||
| 582 | DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", | ||
| 583 | mode, hs, vs, hs_pol_inv, vs_pol_inv); | ||
| 584 | |||
| 585 | rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); | ||
| 586 | rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); | ||
| 587 | |||
| 588 | l = rfbi_read_reg(RFBI_CONFIG(0)); | ||
| 589 | if (hs_pol_inv) | ||
| 590 | l &= ~(1 << 21); | ||
| 591 | else | ||
| 592 | l |= 1 << 21; | ||
| 593 | if (vs_pol_inv) | ||
| 594 | l &= ~(1 << 20); | ||
| 595 | else | ||
| 596 | l |= 1 << 20; | ||
| 597 | |||
| 598 | return 0; | ||
| 599 | } | ||
| 600 | |||
| 601 | /* xxx FIX module selection missing */ | ||
| 602 | static int rfbi_enable_te(bool enable, unsigned line) | ||
| 603 | { | ||
| 604 | u32 l; | ||
| 605 | |||
| 606 | DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode); | ||
| 607 | if (line > (1 << 11) - 1) | ||
| 608 | return -EINVAL; | ||
| 609 | |||
| 610 | l = rfbi_read_reg(RFBI_CONFIG(0)); | ||
| 611 | l &= ~(0x3 << 2); | ||
| 612 | if (enable) { | ||
| 613 | rfbi.te_enabled = 1; | ||
| 614 | l |= rfbi.te_mode << 2; | ||
| 615 | } else | ||
| 616 | rfbi.te_enabled = 0; | ||
| 617 | rfbi_write_reg(RFBI_CONFIG(0), l); | ||
| 618 | rfbi_write_reg(RFBI_LINE_NUMBER, line); | ||
| 619 | |||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | |||
| 623 | static int rfbi_configure_bus(int rfbi_module, int bpp, int lines) | ||
| 624 | { | ||
| 625 | u32 l; | ||
| 626 | int cycle1 = 0, cycle2 = 0, cycle3 = 0; | ||
| 627 | enum omap_rfbi_cycleformat cycleformat; | ||
| 628 | enum omap_rfbi_datatype datatype; | ||
| 629 | enum omap_rfbi_parallelmode parallelmode; | ||
| 630 | |||
| 631 | switch (bpp) { | ||
| 632 | case 12: | ||
| 633 | datatype = OMAP_DSS_RFBI_DATATYPE_12; | ||
| 634 | break; | ||
| 635 | case 16: | ||
| 636 | datatype = OMAP_DSS_RFBI_DATATYPE_16; | ||
| 637 | break; | ||
| 638 | case 18: | ||
| 639 | datatype = OMAP_DSS_RFBI_DATATYPE_18; | ||
| 640 | break; | ||
| 641 | case 24: | ||
| 642 | datatype = OMAP_DSS_RFBI_DATATYPE_24; | ||
| 643 | break; | ||
| 644 | default: | ||
| 645 | BUG(); | ||
| 646 | return 1; | ||
| 647 | } | ||
| 648 | rfbi.datatype = datatype; | ||
| 649 | |||
| 650 | switch (lines) { | ||
| 651 | case 8: | ||
| 652 | parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8; | ||
| 653 | break; | ||
| 654 | case 9: | ||
| 655 | parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9; | ||
| 656 | break; | ||
| 657 | case 12: | ||
| 658 | parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12; | ||
| 659 | break; | ||
| 660 | case 16: | ||
| 661 | parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16; | ||
| 662 | break; | ||
| 663 | default: | ||
| 664 | BUG(); | ||
| 665 | return 1; | ||
| 666 | } | ||
| 667 | rfbi.parallelmode = parallelmode; | ||
| 668 | |||
| 669 | if ((bpp % lines) == 0) { | ||
| 670 | switch (bpp / lines) { | ||
| 671 | case 1: | ||
| 672 | cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1; | ||
| 673 | break; | ||
| 674 | case 2: | ||
| 675 | cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1; | ||
| 676 | break; | ||
| 677 | case 3: | ||
| 678 | cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1; | ||
| 679 | break; | ||
| 680 | default: | ||
| 681 | BUG(); | ||
| 682 | return 1; | ||
| 683 | } | ||
| 684 | } else if ((2 * bpp % lines) == 0) { | ||
| 685 | if ((2 * bpp / lines) == 3) | ||
| 686 | cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2; | ||
| 687 | else { | ||
| 688 | BUG(); | ||
| 689 | return 1; | ||
| 690 | } | ||
| 691 | } else { | ||
| 692 | BUG(); | ||
| 693 | return 1; | ||
| 694 | } | ||
| 695 | |||
| 696 | switch (cycleformat) { | ||
| 697 | case OMAP_DSS_RFBI_CYCLEFORMAT_1_1: | ||
| 698 | cycle1 = lines; | ||
| 699 | break; | ||
| 700 | |||
| 701 | case OMAP_DSS_RFBI_CYCLEFORMAT_2_1: | ||
| 702 | cycle1 = lines; | ||
| 703 | cycle2 = lines; | ||
| 704 | break; | ||
| 705 | |||
| 706 | case OMAP_DSS_RFBI_CYCLEFORMAT_3_1: | ||
| 707 | cycle1 = lines; | ||
| 708 | cycle2 = lines; | ||
| 709 | cycle3 = lines; | ||
| 710 | break; | ||
| 711 | |||
| 712 | case OMAP_DSS_RFBI_CYCLEFORMAT_3_2: | ||
| 713 | cycle1 = lines; | ||
| 714 | cycle2 = (lines / 2) | ((lines / 2) << 16); | ||
| 715 | cycle3 = (lines << 16); | ||
| 716 | break; | ||
| 717 | } | ||
| 718 | |||
| 719 | REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ | ||
| 720 | |||
| 721 | l = 0; | ||
| 722 | l |= FLD_VAL(parallelmode, 1, 0); | ||
| 723 | l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */ | ||
| 724 | l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */ | ||
| 725 | l |= FLD_VAL(datatype, 6, 5); | ||
| 726 | /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ | ||
| 727 | l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */ | ||
| 728 | l |= FLD_VAL(cycleformat, 10, 9); | ||
| 729 | l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */ | ||
| 730 | l |= FLD_VAL(0, 16, 16); /* A0POLARITY */ | ||
| 731 | l |= FLD_VAL(0, 17, 17); /* REPOLARITY */ | ||
| 732 | l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */ | ||
| 733 | l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */ | ||
| 734 | l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */ | ||
| 735 | l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */ | ||
| 736 | rfbi_write_reg(RFBI_CONFIG(rfbi_module), l); | ||
| 737 | |||
| 738 | rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1); | ||
| 739 | rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2); | ||
| 740 | rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3); | ||
| 741 | |||
| 742 | |||
| 743 | l = rfbi_read_reg(RFBI_CONTROL); | ||
| 744 | l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */ | ||
| 745 | l = FLD_MOD(l, 0, 1, 1); /* clear bypass */ | ||
| 746 | rfbi_write_reg(RFBI_CONTROL, l); | ||
| 747 | |||
| 748 | |||
| 749 | DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", | ||
| 750 | bpp, lines, cycle1, cycle2, cycle3); | ||
| 751 | |||
| 752 | return 0; | ||
| 753 | } | ||
| 754 | |||
| 755 | static int rfbi_configure(struct omap_dss_device *dssdev) | ||
| 756 | { | ||
| 757 | return rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size, | ||
| 758 | rfbi.data_lines); | ||
| 759 | } | ||
| 760 | |||
| 761 | static int rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), | ||
| 762 | void *data) | ||
| 763 | { | ||
| 764 | return rfbi_transfer_area(dssdev, callback, data); | ||
| 765 | } | ||
| 766 | |||
| 767 | static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) | ||
| 768 | { | ||
| 769 | rfbi.timings.x_res = w; | ||
| 770 | rfbi.timings.y_res = h; | ||
| 771 | } | ||
| 772 | |||
| 773 | static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size) | ||
| 774 | { | ||
| 775 | rfbi.pixel_size = pixel_size; | ||
| 776 | } | ||
| 777 | |||
| 778 | static void rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) | ||
| 779 | { | ||
| 780 | rfbi.data_lines = data_lines; | ||
| 781 | } | ||
| 782 | |||
| 783 | static void rfbi_set_interface_timings(struct omap_dss_device *dssdev, | ||
| 784 | struct rfbi_timings *timings) | ||
| 785 | { | ||
| 786 | rfbi.intf_timings = *timings; | ||
| 787 | } | ||
| 788 | |||
| 789 | static void rfbi_dump_regs(struct seq_file *s) | ||
| 790 | { | ||
| 791 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) | ||
| 792 | |||
| 793 | if (rfbi_runtime_get()) | ||
| 794 | return; | ||
| 795 | |||
| 796 | DUMPREG(RFBI_REVISION); | ||
| 797 | DUMPREG(RFBI_SYSCONFIG); | ||
| 798 | DUMPREG(RFBI_SYSSTATUS); | ||
| 799 | DUMPREG(RFBI_CONTROL); | ||
| 800 | DUMPREG(RFBI_PIXEL_CNT); | ||
| 801 | DUMPREG(RFBI_LINE_NUMBER); | ||
| 802 | DUMPREG(RFBI_CMD); | ||
| 803 | DUMPREG(RFBI_PARAM); | ||
| 804 | DUMPREG(RFBI_DATA); | ||
| 805 | DUMPREG(RFBI_READ); | ||
| 806 | DUMPREG(RFBI_STATUS); | ||
| 807 | |||
| 808 | DUMPREG(RFBI_CONFIG(0)); | ||
| 809 | DUMPREG(RFBI_ONOFF_TIME(0)); | ||
| 810 | DUMPREG(RFBI_CYCLE_TIME(0)); | ||
| 811 | DUMPREG(RFBI_DATA_CYCLE1(0)); | ||
| 812 | DUMPREG(RFBI_DATA_CYCLE2(0)); | ||
| 813 | DUMPREG(RFBI_DATA_CYCLE3(0)); | ||
| 814 | |||
| 815 | DUMPREG(RFBI_CONFIG(1)); | ||
| 816 | DUMPREG(RFBI_ONOFF_TIME(1)); | ||
| 817 | DUMPREG(RFBI_CYCLE_TIME(1)); | ||
| 818 | DUMPREG(RFBI_DATA_CYCLE1(1)); | ||
| 819 | DUMPREG(RFBI_DATA_CYCLE2(1)); | ||
| 820 | DUMPREG(RFBI_DATA_CYCLE3(1)); | ||
| 821 | |||
| 822 | DUMPREG(RFBI_VSYNC_WIDTH); | ||
| 823 | DUMPREG(RFBI_HSYNC_WIDTH); | ||
| 824 | |||
| 825 | rfbi_runtime_put(); | ||
| 826 | #undef DUMPREG | ||
| 827 | } | ||
| 828 | |||
| 829 | static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) | ||
| 830 | { | ||
| 831 | struct omap_overlay_manager *mgr = rfbi.output.manager; | ||
| 832 | struct dss_lcd_mgr_config mgr_config; | ||
| 833 | |||
| 834 | mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; | ||
| 835 | |||
| 836 | mgr_config.stallmode = true; | ||
| 837 | /* Do we need fifohandcheck for RFBI? */ | ||
| 838 | mgr_config.fifohandcheck = false; | ||
| 839 | |||
| 840 | mgr_config.video_port_width = rfbi.pixel_size; | ||
| 841 | mgr_config.lcden_sig_polarity = 0; | ||
| 842 | |||
| 843 | dss_mgr_set_lcd_config(mgr, &mgr_config); | ||
| 844 | |||
| 845 | /* | ||
| 846 | * Set rfbi.timings with default values, the x_res and y_res fields | ||
| 847 | * are expected to be already configured by the panel driver via | ||
| 848 | * omapdss_rfbi_set_size() | ||
| 849 | */ | ||
| 850 | rfbi.timings.hsw = 1; | ||
| 851 | rfbi.timings.hfp = 1; | ||
| 852 | rfbi.timings.hbp = 1; | ||
| 853 | rfbi.timings.vsw = 1; | ||
| 854 | rfbi.timings.vfp = 0; | ||
| 855 | rfbi.timings.vbp = 0; | ||
| 856 | |||
| 857 | rfbi.timings.interlace = false; | ||
| 858 | rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; | ||
| 859 | rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; | ||
| 860 | rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; | ||
| 861 | rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; | ||
| 862 | rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE; | ||
| 863 | |||
| 864 | dss_mgr_set_timings(mgr, &rfbi.timings); | ||
| 865 | } | ||
| 866 | |||
| 867 | static int rfbi_display_enable(struct omap_dss_device *dssdev) | ||
| 868 | { | ||
| 869 | struct omap_dss_device *out = &rfbi.output; | ||
| 870 | int r; | ||
| 871 | |||
| 872 | if (out->manager == NULL) { | ||
| 873 | DSSERR("failed to enable display: no output/manager\n"); | ||
| 874 | return -ENODEV; | ||
| 875 | } | ||
| 876 | |||
| 877 | r = rfbi_runtime_get(); | ||
| 878 | if (r) | ||
| 879 | return r; | ||
| 880 | |||
| 881 | r = dss_mgr_register_framedone_handler(out->manager, | ||
| 882 | framedone_callback, NULL); | ||
| 883 | if (r) { | ||
| 884 | DSSERR("can't get FRAMEDONE irq\n"); | ||
| 885 | goto err1; | ||
| 886 | } | ||
| 887 | |||
| 888 | rfbi_config_lcd_manager(dssdev); | ||
| 889 | |||
| 890 | rfbi_configure_bus(dssdev->phy.rfbi.channel, rfbi.pixel_size, | ||
| 891 | rfbi.data_lines); | ||
| 892 | |||
| 893 | rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings); | ||
| 894 | |||
| 895 | return 0; | ||
| 896 | err1: | ||
| 897 | rfbi_runtime_put(); | ||
| 898 | return r; | ||
| 899 | } | ||
| 900 | |||
| 901 | static void rfbi_display_disable(struct omap_dss_device *dssdev) | ||
| 902 | { | ||
| 903 | struct omap_dss_device *out = &rfbi.output; | ||
| 904 | |||
| 905 | dss_mgr_unregister_framedone_handler(out->manager, | ||
| 906 | framedone_callback, NULL); | ||
| 907 | |||
| 908 | rfbi_runtime_put(); | ||
| 909 | } | ||
| 910 | |||
| 911 | static int rfbi_init_display(struct omap_dss_device *dssdev) | ||
| 912 | { | ||
| 913 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; | ||
| 914 | return 0; | ||
| 915 | } | ||
| 916 | |||
| 917 | static void rfbi_init_output(struct platform_device *pdev) | ||
| 918 | { | ||
| 919 | struct omap_dss_device *out = &rfbi.output; | ||
| 920 | |||
| 921 | out->dev = &pdev->dev; | ||
| 922 | out->id = OMAP_DSS_OUTPUT_DBI; | ||
| 923 | out->output_type = OMAP_DISPLAY_TYPE_DBI; | ||
| 924 | out->name = "rfbi.0"; | ||
| 925 | out->dispc_channel = OMAP_DSS_CHANNEL_LCD; | ||
| 926 | out->owner = THIS_MODULE; | ||
| 927 | |||
| 928 | omapdss_register_output(out); | ||
| 929 | } | ||
| 930 | |||
| 931 | static void rfbi_uninit_output(struct platform_device *pdev) | ||
| 932 | { | ||
| 933 | struct omap_dss_device *out = &rfbi.output; | ||
| 934 | |||
| 935 | omapdss_unregister_output(out); | ||
| 936 | } | ||
| 937 | |||
| 938 | /* RFBI HW IP initialisation */ | ||
| 939 | static int rfbi_bind(struct device *dev, struct device *master, void *data) | ||
| 940 | { | ||
| 941 | struct platform_device *pdev = to_platform_device(dev); | ||
| 942 | u32 rev; | ||
| 943 | struct resource *rfbi_mem; | ||
| 944 | struct clk *clk; | ||
| 945 | int r; | ||
| 946 | |||
| 947 | rfbi.pdev = pdev; | ||
| 948 | |||
| 949 | sema_init(&rfbi.bus_lock, 1); | ||
| 950 | |||
| 951 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); | ||
| 952 | if (!rfbi_mem) { | ||
| 953 | DSSERR("can't get IORESOURCE_MEM RFBI\n"); | ||
| 954 | return -EINVAL; | ||
| 955 | } | ||
| 956 | |||
| 957 | rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start, | ||
| 958 | resource_size(rfbi_mem)); | ||
| 959 | if (!rfbi.base) { | ||
| 960 | DSSERR("can't ioremap RFBI\n"); | ||
| 961 | return -ENOMEM; | ||
| 962 | } | ||
| 963 | |||
| 964 | clk = clk_get(&pdev->dev, "ick"); | ||
| 965 | if (IS_ERR(clk)) { | ||
| 966 | DSSERR("can't get ick\n"); | ||
| 967 | return PTR_ERR(clk); | ||
| 968 | } | ||
| 969 | |||
| 970 | rfbi.l4_khz = clk_get_rate(clk) / 1000; | ||
| 971 | |||
| 972 | clk_put(clk); | ||
| 973 | |||
| 974 | pm_runtime_enable(&pdev->dev); | ||
| 975 | |||
| 976 | r = rfbi_runtime_get(); | ||
| 977 | if (r) | ||
| 978 | goto err_runtime_get; | ||
| 979 | |||
| 980 | msleep(10); | ||
| 981 | |||
| 982 | rev = rfbi_read_reg(RFBI_REVISION); | ||
| 983 | dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", | ||
| 984 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
| 985 | |||
| 986 | rfbi_runtime_put(); | ||
| 987 | |||
| 988 | dss_debugfs_create_file("rfbi", rfbi_dump_regs); | ||
| 989 | |||
| 990 | rfbi_init_output(pdev); | ||
| 991 | |||
| 992 | return 0; | ||
| 993 | |||
| 994 | err_runtime_get: | ||
| 995 | pm_runtime_disable(&pdev->dev); | ||
| 996 | return r; | ||
| 997 | } | ||
| 998 | |||
| 999 | static void rfbi_unbind(struct device *dev, struct device *master, void *data) | ||
| 1000 | { | ||
| 1001 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1002 | |||
| 1003 | rfbi_uninit_output(pdev); | ||
| 1004 | |||
| 1005 | pm_runtime_disable(&pdev->dev); | ||
| 1006 | |||
| 1007 | return 0; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static const struct component_ops rfbi_component_ops = { | ||
| 1011 | .bind = rfbi_bind, | ||
| 1012 | .unbind = rfbi_unbind, | ||
| 1013 | }; | ||
| 1014 | |||
| 1015 | static int rfbi_probe(struct platform_device *pdev) | ||
| 1016 | { | ||
| 1017 | return component_add(&pdev->dev, &rfbi_component_ops); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static int rfbi_remove(struct platform_device *pdev) | ||
| 1021 | { | ||
| 1022 | component_del(&pdev->dev, &rfbi_component_ops); | ||
| 1023 | return 0; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static int rfbi_runtime_suspend(struct device *dev) | ||
| 1027 | { | ||
| 1028 | dispc_runtime_put(); | ||
| 1029 | |||
| 1030 | return 0; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | static int rfbi_runtime_resume(struct device *dev) | ||
| 1034 | { | ||
| 1035 | int r; | ||
| 1036 | |||
| 1037 | r = dispc_runtime_get(); | ||
| 1038 | if (r < 0) | ||
| 1039 | return r; | ||
| 1040 | |||
| 1041 | return 0; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | static const struct dev_pm_ops rfbi_pm_ops = { | ||
| 1045 | .runtime_suspend = rfbi_runtime_suspend, | ||
| 1046 | .runtime_resume = rfbi_runtime_resume, | ||
| 1047 | }; | ||
| 1048 | |||
| 1049 | static struct platform_driver omap_rfbihw_driver = { | ||
| 1050 | .probe = rfbi_probe, | ||
| 1051 | .remove = rfbi_remove, | ||
| 1052 | .driver = { | ||
| 1053 | .name = "omapdss_rfbi", | ||
| 1054 | .pm = &rfbi_pm_ops, | ||
| 1055 | .suppress_bind_attrs = true, | ||
| 1056 | }, | ||
| 1057 | }; | ||
| 1058 | |||
| 1059 | int __init rfbi_init_platform_driver(void) | ||
| 1060 | { | ||
| 1061 | return platform_driver_register(&omap_rfbihw_driver); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | void rfbi_uninit_platform_driver(void) | ||
| 1065 | { | ||
| 1066 | platform_driver_unregister(&omap_rfbihw_driver); | ||
| 1067 | } | ||
| @@ -1881,12 +1881,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) · 1880 unmodified lines | |||
| 1881 | 1881 | ||
| 1882 | fbi = framebuffer_alloc(sizeof(struct omapfb_info), | 1882 | fbi = framebuffer_alloc(sizeof(struct omapfb_info), |
| 1883 | fbdev->dev); | 1883 | fbdev->dev); |
| 1884 | 1884 | if (!fbi) | |
| 1885 | if (fbi == NULL) { | ||
| 1886 | dev_err(fbdev->dev, | ||
| 1887 | "unable to allocate memory for plane info\n"); | ||
| 1888 | return -ENOMEM; | 1885 | return -ENOMEM; |
| 1889 | } | ||
| 1890 | 1886 | ||
| 1891 | clear_fb_info(fbi); | 1887 | clear_fb_info(fbi); |
| 1892 | 1888 | ||
| @@ -49,8 +49,7 @@ static ssize_t store_rotate_type(struct device *dev, · 48 unmodified lines | |||
| 49 | if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) | 49 | if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) |
| 50 | return -EINVAL; | 50 | return -EINVAL; |
| 51 | 51 | ||
| 52 | if (!lock_fb_info(fbi)) | 52 | lock_fb_info(fbi); |
| 53 | return -ENODEV; | ||
| 54 | 53 | ||
| 55 | r = 0; | 54 | r = 0; |
| 56 | if (rot_type == ofbi->rotation_type) | 55 | if (rot_type == ofbi->rotation_type) |
| @@ -101,8 +100,7 @@ static ssize_t store_mirror(struct device *dev, · 44 unmodified lines | |||
| 101 | if (r) | 100 | if (r) |
| 102 | return r; | 101 | return r; |
| 103 | 102 | ||
| 104 | if (!lock_fb_info(fbi)) | 103 | lock_fb_info(fbi); |
| 105 | return -ENODEV; | ||
| 106 | 104 | ||
| 107 | ofbi->mirror = mirror; | 105 | ofbi->mirror = mirror; |
| 108 | 106 | ||
| @@ -138,8 +136,7 @@ static ssize_t show_overlays(struct device *dev, · 29 unmodified lines | |||
| 138 | ssize_t l = 0; | 136 | ssize_t l = 0; |
| 139 | int t; | 137 | int t; |
| 140 | 138 | ||
| 141 | if (!lock_fb_info(fbi)) | 139 | lock_fb_info(fbi); |
| 142 | return -ENODEV; | ||
| 143 | omapfb_lock(fbdev); | 140 | omapfb_lock(fbdev); |
| 144 | 141 | ||
| 145 | for (t = 0; t < ofbi->num_overlays; t++) { | 142 | for (t = 0; t < ofbi->num_overlays; t++) { |
| @@ -197,8 +194,7 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, · 51 unmodified lines | |||
| 197 | if (buf[len - 1] == '\n') | 194 | if (buf[len - 1] == '\n') |
| 198 | len = len - 1; | 195 | len = len - 1; |
| 199 | 196 | ||
| 200 | if (!lock_fb_info(fbi)) | 197 | lock_fb_info(fbi); |
| 201 | return -ENODEV; | ||
| 202 | omapfb_lock(fbdev); | 198 | omapfb_lock(fbdev); |
| 203 | 199 | ||
| 204 | if (len > 0) { | 200 | if (len > 0) { |
| @@ -329,8 +325,7 @@ static ssize_t show_overlays_rotate(struct device *dev, · 124 unmodified lines | |||
| 329 | ssize_t l = 0; | 325 | ssize_t l = 0; |
| 330 | int t; | 326 | int t; |
| 331 | 327 | ||
| 332 | if (!lock_fb_info(fbi)) | 328 | lock_fb_info(fbi); |
| 333 | return -ENODEV; | ||
| 334 | 329 | ||
| 335 | for (t = 0; t < ofbi->num_overlays; t++) { | 330 | for (t = 0; t < ofbi->num_overlays; t++) { |
| 336 | l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", | 331 | l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", |
| @@ -358,8 +353,7 @@ static ssize_t store_overlays_rotate(struct device *dev, · 21 unmodified lines | |||
| 358 | if (buf[len - 1] == '\n') | 353 | if (buf[len - 1] == '\n') |
| 359 | len = len - 1; | 354 | len = len - 1; |
| 360 | 355 | ||
| 361 | if (!lock_fb_info(fbi)) | 356 | lock_fb_info(fbi); |
| 362 | return -ENODEV; | ||
| 363 | 357 | ||
| 364 | if (len > 0) { | 358 | if (len > 0) { |
| 365 | char *p = (char *)buf; | 359 | char *p = (char *)buf; |
| @@ -442,8 +436,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, · 76 unmodified lines | |||
| 442 | 436 | ||
| 443 | size = PAGE_ALIGN(size); | 437 | size = PAGE_ALIGN(size); |
| 444 | 438 | ||
| 445 | if (!lock_fb_info(fbi)) | 439 | lock_fb_info(fbi); |
| 446 | return -ENODEV; | ||
| 447 | 440 | ||
| 448 | if (display && display->driver->sync) | 441 | if (display && display->driver->sync) |
| 449 | display->driver->sync(display); | 442 | display->driver->sync(display); |
| @@ -538,10 +538,9 @@ static int platinumfb_probe(struct platform_device* odev) · 537 unmodified lines | |||
| 538 | dev_info(&odev->dev, "Found Apple Platinum video hardware\n"); | 538 | dev_info(&odev->dev, "Found Apple Platinum video hardware\n"); |
| 539 | 539 | ||
| 540 | info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); | 540 | info = framebuffer_alloc(sizeof(*pinfo), &odev->dev); |
| 541 | if (info == NULL) { | 541 | if (!info) |
| 542 | dev_err(&odev->dev, "Failed to allocate fbdev !\n"); | ||
| 543 | return -ENOMEM; | 542 | return -ENOMEM; |
| 544 | } | 543 | |
| 545 | pinfo = info->par; | 544 | pinfo = info->par; |
| 546 | 545 | ||
| 547 | if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) || | 546 | if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) || |
| @@ -165,10 +165,8 @@ static int pmagaafb_probe(struct device *dev) · 164 unmodified lines | |||
| 165 | int err; | 165 | int err; |
| 166 | 166 | ||
| 167 | info = framebuffer_alloc(sizeof(struct aafb_par), dev); | 167 | info = framebuffer_alloc(sizeof(struct aafb_par), dev); |
| 168 | if (!info) { | 168 | if (!info) |
| 169 | printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); | ||
| 170 | return -ENOMEM; | 169 | return -ENOMEM; |
| 171 | } | ||
| 172 | 170 | ||
| 173 | par = info->par; | 171 | par = info->par; |
| 174 | dev_set_drvdata(dev, info); | 172 | dev_set_drvdata(dev, info); |
| @@ -150,10 +150,8 @@ static int pmagbafb_probe(struct device *dev) · 149 unmodified lines | |||
| 150 | int err; | 150 | int err; |
| 151 | 151 | ||
| 152 | info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev); | 152 | info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev); |
| 153 | if (!info) { | 153 | if (!info) |
| 154 | printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); | ||
| 155 | return -ENOMEM; | 154 | return -ENOMEM; |
| 156 | } | ||
| 157 | 155 | ||
| 158 | par = info->par; | 156 | par = info->par; |
| 159 | dev_set_drvdata(dev, info); | 157 | dev_set_drvdata(dev, info); |
| @@ -257,10 +257,8 @@ static int pmagbbfb_probe(struct device *dev) · 256 unmodified lines | |||
| 257 | int err; | 257 | int err; |
| 258 | 258 | ||
| 259 | info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev); | 259 | info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev); |
| 260 | if (!info) { | 260 | if (!info) |
| 261 | printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); | ||
| 262 | return -ENOMEM; | 261 | return -ENOMEM; |
| 263 | } | ||
| 264 | 262 | ||
| 265 | par = info->par; | 263 | par = info->par; |
| 266 | dev_set_drvdata(dev, info); | 264 | dev_set_drvdata(dev, info); |
| @@ -140,7 +140,7 @@ static struct pvr2fb_par { · 139 unmodified lines | |||
| 140 | unsigned char is_doublescan; /* Are scanlines output twice? (doublescan) */ | 140 | unsigned char is_doublescan; /* Are scanlines output twice? (doublescan) */ |
| 141 | unsigned char is_lowres; /* Is horizontal pixel-doubling enabled? */ | 141 | unsigned char is_lowres; /* Is horizontal pixel-doubling enabled? */ |
| 142 | 142 | ||
| 143 | unsigned long mmio_base; /* MMIO base */ | 143 | void __iomem *mmio_base; /* MMIO base */ |
| 144 | u32 palette[16]; | 144 | u32 palette[16]; |
| 145 | } *currentpar; | 145 | } *currentpar; |
| 146 | 146 | ||
| @@ -194,39 +194,6 @@ static unsigned int shdma = PVR2_CASCADE_CHAN; · 47 unmodified lines | |||
| 194 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; | 194 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; |
| 195 | #endif | 195 | #endif |
| 196 | 196 | ||
| 197 | static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, | ||
| 198 | unsigned int transp, struct fb_info *info); | ||
| 199 | static int pvr2fb_blank(int blank, struct fb_info *info); | ||
| 200 | static unsigned long get_line_length(int xres_virtual, int bpp); | ||
| 201 | static void set_color_bitfields(struct fb_var_screeninfo *var); | ||
| 202 | static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); | ||
| 203 | static int pvr2fb_set_par(struct fb_info *info); | ||
| 204 | static void pvr2_update_display(struct fb_info *info); | ||
| 205 | static void pvr2_init_display(struct fb_info *info); | ||
| 206 | static void pvr2_do_blank(void); | ||
| 207 | static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id); | ||
| 208 | static int pvr2_init_cable(void); | ||
| 209 | static int pvr2_get_param(const struct pvr2_params *p, const char *s, | ||
| 210 | int val, int size); | ||
| 211 | #ifdef CONFIG_PVR2_DMA | ||
| 212 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | ||
| 213 | size_t count, loff_t *ppos); | ||
| 214 | #endif | ||
| 215 | |||
| 216 | static struct fb_ops pvr2fb_ops = { | ||
| 217 | .owner = THIS_MODULE, | ||
| 218 | .fb_setcolreg = pvr2fb_setcolreg, | ||
| 219 | .fb_blank = pvr2fb_blank, | ||
| 220 | .fb_check_var = pvr2fb_check_var, | ||
| 221 | .fb_set_par = pvr2fb_set_par, | ||
| 222 | #ifdef CONFIG_PVR2_DMA | ||
| 223 | .fb_write = pvr2fb_write, | ||
| 224 | #endif | ||
| 225 | .fb_fillrect = cfb_fillrect, | ||
| 226 | .fb_copyarea = cfb_copyarea, | ||
| 227 | .fb_imageblit = cfb_imageblit, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static struct fb_videomode pvr2_modedb[] = { | 197 | static struct fb_videomode pvr2_modedb[] = { |
| 231 | /* | 198 | /* |
| 232 | * Broadcast video modes (PAL and NTSC). I'm unfamiliar with | 199 | * Broadcast video modes (PAL and NTSC). I'm unfamiliar with |
| @@ -354,6 +321,36 @@ static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, · 121 unmodified lines | |||
| 354 | return 0; | 321 | return 0; |
| 355 | } | 322 | } |
| 356 | 323 | ||
| 324 | /* | ||
| 325 | * Determine the cable type and initialize the cable output format. Don't do | ||
| 326 | * anything if the cable type has been overidden (via "cable:XX"). | ||
| 327 | */ | ||
| 328 | |||
| 329 | #define PCTRA ((void __iomem *)0xff80002c) | ||
| 330 | #define PDTRA ((void __iomem *)0xff800030) | ||
| 331 | #define VOUTC ((void __iomem *)0xa0702c00) | ||
| 332 | |||
| 333 | static int pvr2_init_cable(void) | ||
| 334 | { | ||
| 335 | if (cable_type < 0) { | ||
| 336 | fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, | ||
| 337 | PCTRA); | ||
| 338 | cable_type = (fb_readw(PDTRA) >> 8) & 3; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* Now select the output format (either composite or other) */ | ||
| 342 | /* XXX: Save the previous val first, as this reg is also AICA | ||
| 343 | related */ | ||
| 344 | if (cable_type == CT_COMPOSITE) | ||
| 345 | fb_writel(3 << 8, VOUTC); | ||
| 346 | else if (cable_type == CT_RGB) | ||
| 347 | fb_writel(1 << 9, VOUTC); | ||
| 348 | else | ||
| 349 | fb_writel(0, VOUTC); | ||
| 350 | |||
| 351 | return cable_type; | ||
| 352 | } | ||
| 353 | |||
| 357 | static int pvr2fb_set_par(struct fb_info *info) | 354 | static int pvr2fb_set_par(struct fb_info *info) |
| 358 | { | 355 | { |
| 359 | struct pvr2fb_par *par = (struct pvr2fb_par *)info->par; | 356 | struct pvr2fb_par *par = (struct pvr2fb_par *)info->par; |
| @@ -623,7 +620,7 @@ static void pvr2_do_blank(void) · 263 unmodified lines | |||
| 623 | is_blanked = do_blank > 0 ? do_blank : 0; | 620 | is_blanked = do_blank > 0 ? do_blank : 0; |
| 624 | } | 621 | } |
| 625 | 622 | ||
| 626 | static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id) | 623 | static irqreturn_t __maybe_unused pvr2fb_interrupt(int irq, void *dev_id) |
| 627 | { | 624 | { |
| 628 | struct fb_info *info = dev_id; | 625 | struct fb_info *info = dev_id; |
| 629 | 626 | ||
| @@ -642,36 +639,6 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id) · 12 unmodified lines | |||
| 642 | return IRQ_HANDLED; | 639 | return IRQ_HANDLED; |
| 643 | } | 640 | } |
| 644 | 641 | ||
| 645 | /* | ||
| 646 | * Determine the cable type and initialize the cable output format. Don't do | ||
| 647 | * anything if the cable type has been overidden (via "cable:XX"). | ||
| 648 | */ | ||
| 649 | |||
| 650 | #define PCTRA 0xff80002c | ||
| 651 | #define PDTRA 0xff800030 | ||
| 652 | #define VOUTC 0xa0702c00 | ||
| 653 | |||
| 654 | static int pvr2_init_cable(void) | ||
| 655 | { | ||
| 656 | if (cable_type < 0) { | ||
| 657 | fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, | ||
| 658 | PCTRA); | ||
| 659 | cable_type = (fb_readw(PDTRA) >> 8) & 3; | ||
| 660 | } | ||
| 661 | |||
| 662 | /* Now select the output format (either composite or other) */ | ||
| 663 | /* XXX: Save the previous val first, as this reg is also AICA | ||
| 664 | related */ | ||
| 665 | if (cable_type == CT_COMPOSITE) | ||
| 666 | fb_writel(3 << 8, VOUTC); | ||
| 667 | else if (cable_type == CT_RGB) | ||
| 668 | fb_writel(1 << 9, VOUTC); | ||
| 669 | else | ||
| 670 | fb_writel(0, VOUTC); | ||
| 671 | |||
| 672 | return cable_type; | ||
| 673 | } | ||
| 674 | |||
| 675 | #ifdef CONFIG_PVR2_DMA | 642 | #ifdef CONFIG_PVR2_DMA |
| 676 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | 643 | static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, |
| 677 | size_t count, loff_t *ppos) | 644 | size_t count, loff_t *ppos) |
| @@ -742,6 +709,46 @@ out_unmap: · 64 unmodified lines | |||
| 742 | } | 709 | } |
| 743 | #endif /* CONFIG_PVR2_DMA */ | 710 | #endif /* CONFIG_PVR2_DMA */ |
| 744 | 711 | ||
| 712 | static struct fb_ops pvr2fb_ops = { | ||
| 713 | .owner = THIS_MODULE, | ||
| 714 | .fb_setcolreg = pvr2fb_setcolreg, | ||
| 715 | .fb_blank = pvr2fb_blank, | ||
| 716 | .fb_check_var = pvr2fb_check_var, | ||
| 717 | .fb_set_par = pvr2fb_set_par, | ||
| 718 | #ifdef CONFIG_PVR2_DMA | ||
| 719 | .fb_write = pvr2fb_write, | ||
| 720 | #endif | ||
| 721 | .fb_fillrect = cfb_fillrect, | ||
| 722 | .fb_copyarea = cfb_copyarea, | ||
| 723 | .fb_imageblit = cfb_imageblit, | ||
| 724 | }; | ||
| 725 | |||
| 726 | #ifndef MODULE | ||
| 727 | static int pvr2_get_param_val(const struct pvr2_params *p, const char *s, | ||
| 728 | int size) | ||
| 729 | { | ||
| 730 | int i; | ||
| 731 | |||
| 732 | for (i = 0; i < size; i++) { | ||
| 733 | if (!strncasecmp(p[i].name, s, strlen(s))) | ||
| 734 | return p[i].val; | ||
| 735 | } | ||
| 736 | return -1; | ||
| 737 | } | ||
| 738 | #endif | ||
| 739 | |||
| 740 | static char *pvr2_get_param_name(const struct pvr2_params *p, int val, | ||
| 741 | int size) | ||
| 742 | { | ||
| 743 | int i; | ||
| 744 | |||
| 745 | for (i = 0; i < size; i++) { | ||
| 746 | if (p[i].val == val) | ||
| 747 | return p[i].name; | ||
| 748 | } | ||
| 749 | return NULL; | ||
| 750 | } | ||
| 751 | |||
| 745 | /** | 752 | /** |
| 746 | * pvr2fb_common_init | 753 | * pvr2fb_common_init |
| 747 | * | 754 | * |
| @@ -760,7 +767,7 @@ out_unmap: · 12 unmodified lines | |||
| 760 | * in for flexibility anyways. Who knows, maybe someone has tv-out on a | 767 | * in for flexibility anyways. Who knows, maybe someone has tv-out on a |
| 761 | * PCI-based version of these things ;-) | 768 | * PCI-based version of these things ;-) |
| 762 | */ | 769 | */ |
| 763 | static int pvr2fb_common_init(void) | 770 | static int __maybe_unused pvr2fb_common_init(void) |
| 764 | { | 771 | { |
| 765 | struct pvr2fb_par *par = currentpar; | 772 | struct pvr2fb_par *par = currentpar; |
| 766 | unsigned long modememused, rev; | 773 | unsigned long modememused, rev; |
| @@ -773,8 +780,8 @@ static int pvr2fb_common_init(void) · 6 unmodified lines | |||
| 773 | goto out_err; | 780 | goto out_err; |
| 774 | } | 781 | } |
| 775 | 782 | ||
| 776 | par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start, | 783 | par->mmio_base = ioremap_nocache(pvr2_fix.mmio_start, |
| 777 | pvr2_fix.mmio_len); | 784 | pvr2_fix.mmio_len); |
| 778 | if (!par->mmio_base) { | 785 | if (!par->mmio_base) { |
| 779 | printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); | 786 | printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); |
| 780 | goto out_err; | 787 | goto out_err; |
| @@ -822,8 +829,8 @@ static int pvr2fb_common_init(void) · 41 unmodified lines | |||
| 822 | fb_info->var.xres, fb_info->var.yres, | 829 | fb_info->var.xres, fb_info->var.yres, |
| 823 | fb_info->var.bits_per_pixel, | 830 | fb_info->var.bits_per_pixel, |
| 824 | get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), | 831 | get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), |
| 825 | (char *)pvr2_get_param(cables, NULL, cable_type, 3), | 832 | pvr2_get_param_name(cables, cable_type, 3), |
| 826 | (char *)pvr2_get_param(outputs, NULL, video_output, 3)); | 833 | pvr2_get_param_name(outputs, video_output, 3)); |
| 827 | 834 | ||
| 828 | #ifdef CONFIG_SH_STORE_QUEUES | 835 | #ifdef CONFIG_SH_STORE_QUEUES |
| 829 | fb_notice(fb_info, "registering with SQ API\n"); | 836 | fb_notice(fb_info, "registering with SQ API\n"); |
| @@ -841,7 +848,7 @@ out_err: · 11 unmodified lines | |||
| 841 | if (fb_info->screen_base) | 848 | if (fb_info->screen_base) |
| 842 | iounmap(fb_info->screen_base); | 849 | iounmap(fb_info->screen_base); |
| 843 | if (par->mmio_base) | 850 | if (par->mmio_base) |
| 844 | iounmap((void *)par->mmio_base); | 851 | iounmap(par->mmio_base); |
| 845 | 852 | ||
| 846 | return -ENXIO; | 853 | return -ENXIO; |
| 847 | } | 854 | } |
| @@ -901,15 +908,15 @@ static int __init pvr2fb_dc_init(void) · 53 unmodified lines | |||
| 901 | return pvr2fb_common_init(); | 908 | return pvr2fb_common_init(); |
| 902 | } | 909 | } |
| 903 | 910 | ||
| 904 | static void __exit pvr2fb_dc_exit(void) | 911 | static void pvr2fb_dc_exit(void) |
| 905 | { | 912 | { |
| 906 | if (fb_info->screen_base) { | 913 | if (fb_info->screen_base) { |
| 907 | iounmap(fb_info->screen_base); | 914 | iounmap(fb_info->screen_base); |
| 908 | fb_info->screen_base = NULL; | 915 | fb_info->screen_base = NULL; |
| 909 | } | 916 | } |
| 910 | if (currentpar->mmio_base) { | 917 | if (currentpar->mmio_base) { |
| 911 | iounmap((void *)currentpar->mmio_base); | 918 | iounmap(currentpar->mmio_base); |
| 912 | currentpar->mmio_base = 0; | 919 | currentpar->mmio_base = NULL; |
| 913 | } | 920 | } |
| 914 | 921 | ||
| 915 | free_irq(HW_EVENT_VSYNC, fb_info); | 922 | free_irq(HW_EVENT_VSYNC, fb_info); |
| @@ -958,8 +965,8 @@ static void pvr2fb_pci_remove(struct pci_dev *pdev) · 42 unmodified lines | |||
| 958 | fb_info->screen_base = NULL; | 965 | fb_info->screen_base = NULL; |
| 959 | } | 966 | } |
| 960 | if (currentpar->mmio_base) { | 967 | if (currentpar->mmio_base) { |
| 961 | iounmap((void *)currentpar->mmio_base); | 968 | iounmap(currentpar->mmio_base); |
| 962 | currentpar->mmio_base = 0; | 969 | currentpar->mmio_base = NULL; |
| 963 | } | 970 | } |
| 964 | 971 | ||
| 965 | pci_release_regions(pdev); | 972 | pci_release_regions(pdev); |
| @@ -985,29 +992,12 @@ static int __init pvr2fb_pci_init(void) · 19 unmodified lines | |||
| 985 | return pci_register_driver(&pvr2fb_pci_driver); | 992 | return pci_register_driver(&pvr2fb_pci_driver); |
| 986 | } | 993 | } |
| 987 | 994 | ||
| 988 | static void __exit pvr2fb_pci_exit(void) | 995 | static void pvr2fb_pci_exit(void) |
| 989 | { | 996 | { |
| 990 | pci_unregister_driver(&pvr2fb_pci_driver); | 997 | pci_unregister_driver(&pvr2fb_pci_driver); |
| 991 | } | 998 | } |
| 992 | #endif /* CONFIG_PCI */ | 999 | #endif /* CONFIG_PCI */ |
| 993 | 1000 | ||
| 994 | static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, | ||
| 995 | int size) | ||
| 996 | { | ||
| 997 | int i; | ||
| 998 | |||
| 999 | for (i = 0 ; i < size ; i++ ) { | ||
| 1000 | if (s != NULL) { | ||
| 1001 | if (!strncasecmp(p[i].name, s, strlen(s))) | ||
| 1002 | return p[i].val; | ||
| 1003 | } else { | ||
| 1004 | if (p[i].val == val) | ||
| 1005 | return (int)p[i].name; | ||
| 1006 | } | ||
| 1007 | } | ||
| 1008 | return -1; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | /* | 1001 | /* |
| 1012 | * Parse command arguments. Supported arguments are: | 1002 | * Parse command arguments. Supported arguments are: |
| 1013 | * inverse Use inverse color maps | 1003 | * inverse Use inverse color maps |
| @@ -1047,9 +1037,9 @@ static int __init pvr2fb_setup(char *options) · 33 unmodified lines | |||
| 1047 | } | 1037 | } |
| 1048 | 1038 | ||
| 1049 | if (*cable_arg) | 1039 | if (*cable_arg) |
| 1050 | cable_type = pvr2_get_param(cables, cable_arg, 0, 3); | 1040 | cable_type = pvr2_get_param_val(cables, cable_arg, 3); |
| 1051 | if (*output_arg) | 1041 | if (*output_arg) |
| 1052 | video_output = pvr2_get_param(outputs, output_arg, 0, 3); | 1042 | video_output = pvr2_get_param_val(outputs, output_arg, 3); |
| 1053 | 1043 | ||
| 1054 | return 0; | 1044 | return 0; |
| 1055 | } | 1045 | } |
| @@ -1082,12 +1072,8 @@ static int __init pvr2fb_init(void) · 26 unmodified lines | |||
| 1082 | #endif | 1072 | #endif |
| 1083 | 1073 | ||
| 1084 | fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL); | 1074 | fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL); |
| 1085 | 1075 | if (!fb_info) | |
| 1086 | if (!fb_info) { | ||
| 1087 | printk(KERN_ERR "Failed to allocate memory for fb_info\n"); | ||
| 1088 | return -ENOMEM; | 1076 | return -ENOMEM; |
| 1089 | } | ||
| 1090 | |||
| 1091 | 1077 | ||
| 1092 | currentpar = fb_info->par; | 1078 | currentpar = fb_info->par; |
| 1093 | 1079 | ||
| @@ -1902,7 +1902,6 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) · 1901 unmodified lines | |||
| 1902 | 1902 | ||
| 1903 | info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev); | 1903 | info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev); |
| 1904 | if (!info) { | 1904 | if (!info) { |
| 1905 | printk (KERN_ERR PFX "could not allocate memory\n"); | ||
| 1906 | ret = -ENOMEM; | 1905 | ret = -ENOMEM; |
| 1907 | goto err_ret; | 1906 | goto err_ret; |
| 1908 | } | 1907 | } |
| @@ -284,7 +284,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, · 283 unmodified lines | |||
| 284 | /* 666 with one bit alpha/transparency */ | 284 | /* 666 with one bit alpha/transparency */ |
| 285 | var->transp.offset = 18; | 285 | var->transp.offset = 18; |
| 286 | var->transp.length = 1; | 286 | var->transp.length = 1; |
| 287 | /* drop through */ | 287 | /* fall through */ |
| 288 | case 18: | 288 | case 18: |
| 289 | var->bits_per_pixel = 32; | 289 | var->bits_per_pixel = 32; |
| 290 | 290 | ||
| @@ -312,7 +312,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, · 21 unmodified lines | |||
| 312 | case 25: | 312 | case 25: |
| 313 | var->transp.length = var->bits_per_pixel - 24; | 313 | var->transp.length = var->bits_per_pixel - 24; |
| 314 | var->transp.offset = 24; | 314 | var->transp.offset = 24; |
| 315 | /* drop through */ | 315 | /* fall through */ |
| 316 | case 24: | 316 | case 24: |
| 317 | /* our 24bpp is unpacked, so 32bpp */ | 317 | /* our 24bpp is unpacked, so 32bpp */ |
| 318 | var->bits_per_pixel = 32; | 318 | var->bits_per_pixel = 32; |
| @@ -809,7 +809,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) · 490 unmodified lines | |||
| 809 | case FB_BLANK_POWERDOWN: | 809 | case FB_BLANK_POWERDOWN: |
| 810 | wincon &= ~WINCONx_ENWIN; | 810 | wincon &= ~WINCONx_ENWIN; |
| 811 | sfb->enabled &= ~(1 << index); | 811 | sfb->enabled &= ~(1 << index); |
| 812 | /* fall through to FB_BLANK_NORMAL */ | 812 | /* fall through - to FB_BLANK_NORMAL */ |
| 813 | 813 | ||
| 814 | case FB_BLANK_NORMAL: | 814 | case FB_BLANK_NORMAL: |
| 815 | /* disable the DMA and display 0x0 (black) */ | 815 | /* disable the DMA and display 0x0 (black) */ |
| @@ -1102,14 +1102,14 @@ static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) · 286 unmodified lines | |||
| 1102 | 1102 | ||
| 1103 | dev_dbg(sfb->dev, "want %u bytes for window\n", size); | 1103 | dev_dbg(sfb->dev, "want %u bytes for window\n", size); |
| 1104 | 1104 | ||
| 1105 | fbi->screen_base = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL); | 1105 | fbi->screen_buffer = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL); |
| 1106 | if (!fbi->screen_base) | 1106 | if (!fbi->screen_buffer) |
| 1107 | return -ENOMEM; | 1107 | return -ENOMEM; |
| 1108 | 1108 | ||
| 1109 | dev_dbg(sfb->dev, "mapped %x to %p\n", | 1109 | dev_dbg(sfb->dev, "mapped %x to %p\n", |
| 1110 | (unsigned int)map_dma, fbi->screen_base); | 1110 | (unsigned int)map_dma, fbi->screen_buffer); |
| 1111 | 1111 | ||
| 1112 | memset(fbi->screen_base, 0x0, size); | 1112 | memset(fbi->screen_buffer, 0x0, size); |
| 1113 | fbi->fix.smem_start = map_dma; | 1113 | fbi->fix.smem_start = map_dma; |
| 1114 | 1114 | ||
| 1115 | return 0; | 1115 | return 0; |
| @@ -1126,9 +1126,9 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) · 10 unmodified lines | |||
| 1126 | { | 1126 | { |
| 1127 | struct fb_info *fbi = win->fbinfo; | 1127 | struct fb_info *fbi = win->fbinfo; |
| 1128 | 1128 | ||
| 1129 | if (fbi->screen_base) | 1129 | if (fbi->screen_buffer) |
| 1130 | dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), | 1130 | dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), |
| 1131 | fbi->screen_base, fbi->fix.smem_start); | 1131 | fbi->screen_buffer, fbi->fix.smem_start); |
| 1132 | } | 1132 | } |
| 1133 | 1133 | ||
| 1134 | /** | 1134 | /** |
| @@ -1186,10 +1186,8 @@ static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, · 51 unmodified lines | |||
| 1186 | 1186 | ||
| 1187 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + | 1187 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + |
| 1188 | palette_size * sizeof(u32), sfb->dev); | 1188 | palette_size * sizeof(u32), sfb->dev); |
| 1189 | if (!fbinfo) { | 1189 | if (!fbinfo) |
| 1190 | dev_err(sfb->dev, "failed to allocate framebuffer\n"); | 1190 | return -ENOMEM; |
| 1191 | return -ENOENT; | ||
| 1192 | } | ||
| 1193 | 1191 | ||
| 1194 | windata = sfb->pdata->win[win_no]; | 1192 | windata = sfb->pdata->win[win_no]; |
| 1195 | initmode = *sfb->pdata->vtiming; | 1193 | initmode = *sfb->pdata->vtiming; |
| @@ -1128,10 +1128,8 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 1127 unmodified lines | |||
| 1128 | 1128 | ||
| 1129 | /* Allocate and fill driver data structure */ | 1129 | /* Allocate and fill driver data structure */ |
| 1130 | info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev)); | 1130 | info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev)); |
| 1131 | if (!info) { | 1131 | if (!info) |
| 1132 | dev_err(&(dev->dev), "cannot allocate memory\n"); | ||
| 1133 | return -ENOMEM; | 1132 | return -ENOMEM; |
| 1134 | } | ||
| 1135 | 1133 | ||
| 1136 | par = info->par; | 1134 | par = info->par; |
| 1137 | mutex_init(&par->open_lock); | 1135 | mutex_init(&par->open_lock); |
| @@ -974,35 +974,10 @@ static void sa1100fb_task(struct work_struct *w) · 973 unmodified lines | |||
| 974 | */ | 974 | */ |
| 975 | static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) | 975 | static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) |
| 976 | { | 976 | { |
| 977 | #if 0 | ||
| 978 | unsigned int min_period = (unsigned int)-1; | ||
| 979 | int i; | ||
| 980 | |||
| 981 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | ||
| 982 | struct display *disp = &fb_display[i]; | ||
| 983 | unsigned int period; | ||
| 984 | |||
| 985 | /* | ||
| 986 | * Do we own this display? | ||
| 987 | */ | ||
| 988 | if (disp->fb_info != &fbi->fb) | ||
| 989 | continue; | ||
| 990 | |||
| 991 | /* | ||
| 992 | * Ok, calculate its DMA period | ||
| 993 | */ | ||
| 994 | period = sa1100fb_display_dma_period(&disp->var); | ||
| 995 | if (period < min_period) | ||
| 996 | min_period = period; | ||
| 997 | } | ||
| 998 | |||
| 999 | return min_period; | ||
| 1000 | #else | ||
| 1001 | /* | 977 | /* |
| 1002 | * FIXME: we need to verify _all_ consoles. | 978 | * FIXME: we need to verify _all_ consoles. |
| 1003 | */ | 979 | */ |
| 1004 | return sa1100fb_display_dma_period(&fbi->fb.var); | 980 | return sa1100fb_display_dma_period(&fbi->fb.var); |
| 1005 | #endif | ||
| 1006 | } | 981 | } |
| 1007 | 982 | ||
| 1008 | /* | 983 | /* |
| @@ -2333,14 +2333,7 @@ static void savagefb_remove(struct pci_dev *dev) · 2332 unmodified lines | |||
| 2333 | DBG("savagefb_remove"); | 2333 | DBG("savagefb_remove"); |
| 2334 | 2334 | ||
| 2335 | if (info) { | 2335 | if (info) { |
| 2336 | /* | 2336 | unregister_framebuffer(info); |
| 2337 | * If unregister_framebuffer fails, then | ||
| 2338 | * we will be leaving hooks that could cause | ||
| 2339 | * oopsen laying around. | ||
| 2340 | */ | ||
| 2341 | if (unregister_framebuffer(info)) | ||
| 2342 | printk(KERN_WARNING "savagefb: danger danger! " | ||
| 2343 | "Oopsen imminent!\n"); | ||
| 2344 | 2337 | ||
| 2345 | #ifdef CONFIG_FB_SAVAGE_I2C | 2338 | #ifdef CONFIG_FB_SAVAGE_I2C |
| 2346 | savagefb_delete_i2c_busses(info); | 2339 | savagefb_delete_i2c_busses(info); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
| 16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/fbcon.h> | ||
| 18 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
| 19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| @@ -213,7 +214,6 @@ struct sh_mobile_lcdc_priv { · 192 unmodified lines | |||
| 213 | struct sh_mobile_lcdc_chan ch[2]; | 214 | struct sh_mobile_lcdc_chan ch[2]; |
| 214 | struct sh_mobile_lcdc_overlay overlays[4]; | 215 | struct sh_mobile_lcdc_overlay overlays[4]; |
| 215 | 216 | ||
| 216 | struct notifier_block notifier; | ||
| 217 | int started; | 217 | int started; |
| 218 | int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ | 218 | int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ |
| 219 | }; | 219 | }; |
| @@ -534,89 +534,9 @@ static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch) · 314 unmodified lines | |||
| 534 | ch->tx_dev->ops->display_off(ch->tx_dev); | 534 | ch->tx_dev->ops->display_off(ch->tx_dev); |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | static bool | ||
| 538 | sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, | ||
| 539 | const struct fb_videomode *new_mode) | ||
| 540 | { | ||
| 541 | dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n", | ||
| 542 | ch->display.mode.xres, ch->display.mode.yres, | ||
| 543 | new_mode->xres, new_mode->yres); | ||
| 544 | |||
| 545 | /* It can be a different monitor with an equal video-mode */ | ||
| 546 | if (fb_mode_is_equal(&ch->display.mode, new_mode)) | ||
| 547 | return false; | ||
| 548 | |||
| 549 | dev_dbg(ch->info->dev, "Switching %u -> %u lines\n", | ||
| 550 | ch->display.mode.yres, new_mode->yres); | ||
| 551 | ch->display.mode = *new_mode; | ||
| 552 | |||
| 553 | return true; | ||
| 554 | } | ||
| 555 | |||
| 556 | static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, | 537 | static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, |
| 557 | struct fb_info *info); | 538 | struct fb_info *info); |
| 558 | 539 | ||
| 559 | static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, | ||
| 560 | enum sh_mobile_lcdc_entity_event event, | ||
| 561 | const struct fb_videomode *mode, | ||
| 562 | const struct fb_monspecs *monspec) | ||
| 563 | { | ||
| 564 | struct fb_info *info = ch->info; | ||
| 565 | struct fb_var_screeninfo var; | ||
| 566 | int ret = 0; | ||
| 567 | |||
| 568 | switch (event) { | ||
| 569 | case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: | ||
| 570 | /* HDMI plug in */ | ||
| 571 | console_lock(); | ||
| 572 | if (lock_fb_info(info)) { | ||
| 573 | |||
| 574 | |||
| 575 | ch->display.width = monspec->max_x * 10; | ||
| 576 | ch->display.height = monspec->max_y * 10; | ||
| 577 | |||
| 578 | if (!sh_mobile_lcdc_must_reconfigure(ch, mode) && | ||
| 579 | info->state == FBINFO_STATE_RUNNING) { | ||
| 580 | /* First activation with the default monitor. | ||
| 581 | * Just turn on, if we run a resume here, the | ||
| 582 | * logo disappears. | ||
| 583 | */ | ||
| 584 | info->var.width = ch->display.width; | ||
| 585 | info->var.height = ch->display.height; | ||
| 586 | sh_mobile_lcdc_display_on(ch); | ||
| 587 | } else { | ||
| 588 | /* New monitor or have to wake up */ | ||
| 589 | fb_set_suspend(info, 0); | ||
| 590 | } | ||
| 591 | |||
| 592 | |||
| 593 | unlock_fb_info(info); | ||
| 594 | } | ||
| 595 | console_unlock(); | ||
| 596 | break; | ||
| 597 | |||
| 598 | case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: | ||
| 599 | /* HDMI disconnect */ | ||
| 600 | console_lock(); | ||
| 601 | if (lock_fb_info(info)) { | ||
| 602 | fb_set_suspend(info, 1); | ||
| 603 | unlock_fb_info(info); | ||
| 604 | } | ||
| 605 | console_unlock(); | ||
| 606 | break; | ||
| 607 | |||
| 608 | case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: | ||
| 609 | /* Validate a proposed new mode */ | ||
| 610 | fb_videomode_to_var(&var, mode); | ||
| 611 | var.bits_per_pixel = info->var.bits_per_pixel; | ||
| 612 | var.grayscale = info->var.grayscale; | ||
| 613 | ret = sh_mobile_lcdc_check_var(&var, info); | ||
| 614 | break; | ||
| 615 | } | ||
| 616 | |||
| 617 | return ret; | ||
| 618 | } | ||
| 619 | |||
| 620 | /* ----------------------------------------------------------------------------- | 540 | /* ----------------------------------------------------------------------------- |
| 621 | * Format helpers | 541 | * Format helpers |
| 622 | */ | 542 | */ |
| @@ -1644,10 +1564,8 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) · 1021 unmodified lines | |||
| 1644 | 1564 | ||
| 1645 | /* Allocate and initialize the frame buffer device. */ | 1565 | /* Allocate and initialize the frame buffer device. */ |
| 1646 | info = framebuffer_alloc(0, priv->dev); | 1566 | info = framebuffer_alloc(0, priv->dev); |
| 1647 | if (info == NULL) { | 1567 | if (!info) |
| 1648 | dev_err(priv->dev, "unable to allocate fb_info\n"); | ||
| 1649 | return -ENOMEM; | 1568 | return -ENOMEM; |
| 1650 | } | ||
| 1651 | 1569 | ||
| 1652 | ovl->info = info; | 1570 | ovl->info = info; |
| 1653 | 1571 | ||
| @@ -1838,8 +1756,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) · 184 unmodified lines | |||
| 1838 | struct sh_mobile_lcdc_chan *ch = info->par; | 1756 | struct sh_mobile_lcdc_chan *ch = info->par; |
| 1839 | struct fb_var_screeninfo var; | 1757 | struct fb_var_screeninfo var; |
| 1840 | struct fb_videomode mode; | 1758 | struct fb_videomode mode; |
| 1841 | struct fb_event event; | ||
| 1842 | int evnt = FB_EVENT_MODE_CHANGE_ALL; | ||
| 1843 | 1759 | ||
| 1844 | if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) | 1760 | if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) |
| 1845 | /* More framebuffer users are active */ | 1761 | /* More framebuffer users are active */ |
| @@ -1861,14 +1777,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) · 15 unmodified lines | |||
| 1861 | /* Couldn't reconfigure, hopefully, can continue as before */ | 1777 | /* Couldn't reconfigure, hopefully, can continue as before */ |
| 1862 | return; | 1778 | return; |
| 1863 | 1779 | ||
| 1864 | /* | 1780 | fbcon_update_vcs(info, true); |
| 1865 | * fb_set_var() calls the notifier change internally, only if | ||
| 1866 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a | ||
| 1867 | * user event, we have to call the chain ourselves. | ||
| 1868 | */ | ||
| 1869 | event.info = info; | ||
| 1870 | event.data = &ch->display.mode; | ||
| 1871 | fb_notifier_call_chain(evnt, &event); | ||
| 1872 | } | 1781 | } |
| 1873 | 1782 | ||
| 1874 | /* | 1783 | /* |
| @@ -2138,10 +2047,8 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, · 263 unmodified lines | |||
| 2138 | * list and allocate the color map. | 2047 | * list and allocate the color map. |
| 2139 | */ | 2048 | */ |
| 2140 | info = framebuffer_alloc(0, priv->dev); | 2049 | info = framebuffer_alloc(0, priv->dev); |
| 2141 | if (info == NULL) { | 2050 | if (!info) |
| 2142 | dev_err(priv->dev, "unable to allocate fb_info\n"); | ||
| 2143 | return -ENOMEM; | 2051 | return -ENOMEM; |
| 2144 | } | ||
| 2145 | 2052 | ||
| 2146 | ch->info = info; | 2053 | ch->info = info; |
| 2147 | 2054 | ||
| @@ -2319,37 +2226,6 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { · 171 unmodified lines | |||
| 2319 | * Framebuffer notifier | 2226 | * Framebuffer notifier |
| 2320 | */ | 2227 | */ |
| 2321 | 2228 | ||
| 2322 | /* locking: called with info->lock held */ | ||
| 2323 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, | ||
| 2324 | unsigned long action, void *data) | ||
| 2325 | { | ||
| 2326 | struct fb_event *event = data; | ||
| 2327 | struct fb_info *info = event->info; | ||
| 2328 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
| 2329 | |||
| 2330 | if (&ch->lcdc->notifier != nb) | ||
| 2331 | return NOTIFY_DONE; | ||
| 2332 | |||
| 2333 | dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", | ||
| 2334 | __func__, action, event->data); | ||
| 2335 | |||
| 2336 | switch(action) { | ||
| 2337 | case FB_EVENT_SUSPEND: | ||
| 2338 | sh_mobile_lcdc_display_off(ch); | ||
| 2339 | sh_mobile_lcdc_stop(ch->lcdc); | ||
| 2340 | break; | ||
| 2341 | case FB_EVENT_RESUME: | ||
| 2342 | mutex_lock(&ch->open_lock); | ||
| 2343 | sh_mobile_fb_reconfig(info); | ||
| 2344 | mutex_unlock(&ch->open_lock); | ||
| 2345 | |||
| 2346 | sh_mobile_lcdc_display_on(ch); | ||
| 2347 | sh_mobile_lcdc_start(ch->lcdc); | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | return NOTIFY_OK; | ||
| 2351 | } | ||
| 2352 | |||
| 2353 | /* ----------------------------------------------------------------------------- | 2229 | /* ----------------------------------------------------------------------------- |
| 2354 | * Probe/remove and driver init/exit | 2230 | * Probe/remove and driver init/exit |
| 2355 | */ | 2231 | */ |
| @@ -2377,8 +2253,6 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) · 21 unmodified lines | |||
| 2377 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | 2253 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); |
| 2378 | unsigned int i; | 2254 | unsigned int i; |
| 2379 | 2255 | ||
| 2380 | fb_unregister_client(&priv->notifier); | ||
| 2381 | |||
| 2382 | for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) | 2256 | for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) |
| 2383 | sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); | 2257 | sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); |
| 2384 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | 2258 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) |
| @@ -2540,8 +2414,6 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch) · 155 unmodified lines | |||
| 2540 | unsigned int max_size; | 2414 | unsigned int max_size; |
| 2541 | unsigned int i; | 2415 | unsigned int i; |
| 2542 | 2416 | ||
| 2543 | ch->notify = sh_mobile_lcdc_display_notify; | ||
| 2544 | |||
| 2545 | /* Validate the format. */ | 2417 | /* Validate the format. */ |
| 2546 | format = sh_mobile_format_info(cfg->fourcc); | 2418 | format = sh_mobile_format_info(cfg->fourcc); |
| 2547 | if (format == NULL) { | 2419 | if (format == NULL) { |
| @@ -2770,10 +2642,6 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev) · 222 unmodified lines | |||
| 2770 | goto err1; | 2642 | goto err1; |
| 2771 | } | 2643 | } |
| 2772 | 2644 | ||
| 2773 | /* Failure ignored */ | ||
| 2774 | priv->notifier.notifier_call = sh_mobile_lcdc_notify; | ||
| 2775 | fb_register_client(&priv->notifier); | ||
| 2776 | |||
| 2777 | return 0; | 2645 | return 0; |
| 2778 | err1: | 2646 | err1: |
| 2779 | sh_mobile_lcdc_remove(pdev); | 2647 | sh_mobile_lcdc_remove(pdev); |
| @@ -87,11 +87,6 @@ struct sh_mobile_lcdc_chan { · 86 unmodified lines | |||
| 87 | unsigned long base_addr_c; | 87 | unsigned long base_addr_c; |
| 88 | unsigned int line_size; | 88 | unsigned int line_size; |
| 89 | 89 | ||
| 90 | int (*notify)(struct sh_mobile_lcdc_chan *ch, | ||
| 91 | enum sh_mobile_lcdc_entity_event event, | ||
| 92 | const struct fb_videomode *mode, | ||
| 93 | const struct fb_monspecs *monspec); | ||
| 94 | |||
| 95 | /* Backlight */ | 90 | /* Backlight */ |
| 96 | struct backlight_device *bl; | 91 | struct backlight_device *bl; |
| 97 | unsigned int bl_brightness; | 92 | unsigned int bl_brightness; |
| @@ -1865,10 +1865,8 @@ static int sm501fb_probe_one(struct sm501fb_info *info, · 1864 unmodified lines | |||
| 1865 | } | 1865 | } |
| 1866 | 1866 | ||
| 1867 | fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev); | 1867 | fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev); |
| 1868 | if (fbi == NULL) { | 1868 | if (!fbi) |
| 1869 | dev_err(info->dev, "cannot allocate %s framebuffer\n", name); | ||
| 1870 | return -ENOMEM; | 1869 | return -ENOMEM; |
| 1871 | } | ||
| 1872 | 1870 | ||
| 1873 | par = fbi->par; | 1871 | par = fbi->par; |
| 1874 | par->info = info; | 1872 | par->info = info; |
| @@ -1538,7 +1538,6 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, · 1537 unmodified lines | |||
| 1538 | 1538 | ||
| 1539 | info = framebuffer_alloc(sizeof(*sfb), &pdev->dev); | 1539 | info = framebuffer_alloc(sizeof(*sfb), &pdev->dev); |
| 1540 | if (!info) { | 1540 | if (!info) { |
| 1541 | dev_err(&pdev->dev, "framebuffer_alloc failed\n"); | ||
| 1542 | err = -ENOMEM; | 1541 | err = -ENOMEM; |
| 1543 | goto failed_free; | 1542 | goto failed_free; |
| 1544 | } | 1543 | } |
| @@ -1650,10 +1650,8 @@ static int ufx_usb_probe(struct usb_interface *interface, · 1649 unmodified lines | |||
| 1650 | 1650 | ||
| 1651 | /* allocates framebuffer driver structure, not framebuffer memory */ | 1651 | /* allocates framebuffer driver structure, not framebuffer memory */ |
| 1652 | info = framebuffer_alloc(0, &usbdev->dev); | 1652 | info = framebuffer_alloc(0, &usbdev->dev); |
| 1653 | if (!info) { | 1653 | if (!info) |
| 1654 | dev_err(dev->gdev, "framebuffer_alloc failed\n"); | ||
| 1655 | goto e_nomem; | 1654 | goto e_nomem; |
| 1656 | } | ||
| 1657 | 1655 | ||
| 1658 | dev->info = info; | 1656 | dev->info = info; |
| 1659 | info->par = dev; | 1657 | info->par = dev; |
| @@ -555,10 +555,8 @@ static int ssd1307fb_probe(struct i2c_client *client, · 554 unmodified lines | |||
| 555 | } | 555 | } |
| 556 | 556 | ||
| 557 | info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev); | 557 | info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev); |
| 558 | if (!info) { | 558 | if (!info) |
| 559 | dev_err(&client->dev, "Couldn't allocate framebuffer.\n"); | ||
| 560 | return -ENOMEM; | 559 | return -ENOMEM; |
| 561 | } | ||
| 562 | 560 | ||
| 563 | par = info->par; | 561 | par = info->par; |
| 564 | par->info = info; | 562 | par->info = info; |
| @@ -121,7 +121,6 @@ static int gfb_probe(struct platform_device *op) · 120 unmodified lines | |||
| 121 | 121 | ||
| 122 | info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev); | 122 | info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev); |
| 123 | if (!info) { | 123 | if (!info) { |
| 124 | printk(KERN_ERR "gfb: Cannot allocate fb_info\n"); | ||
| 125 | err = -ENOMEM; | 124 | err = -ENOMEM; |
| 126 | goto err_out; | 125 | goto err_out; |
| 127 | } | 126 | } |
| @@ -132,7 +132,6 @@ static int s3d_pci_register(struct pci_dev *pdev, · 131 unmodified lines | |||
| 132 | 132 | ||
| 133 | info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev); | 133 | info = framebuffer_alloc(sizeof(struct s3d_info), &pdev->dev); |
| 134 | if (!info) { | 134 | if (!info) { |
| 135 | printk(KERN_ERR "s3d: Cannot allocate fb_info\n"); | ||
| 136 | err = -ENOMEM; | 135 | err = -ENOMEM; |
| 137 | goto err_disable; | 136 | goto err_disable; |
| 138 | } | 137 | } |
| @@ -272,7 +272,6 @@ static int e3d_pci_register(struct pci_dev *pdev, · 271 unmodified lines | |||
| 272 | 272 | ||
| 273 | info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev); | 273 | info = framebuffer_alloc(sizeof(struct e3d_info), &pdev->dev); |
| 274 | if (!info) { | 274 | if (!info) { |
| 275 | printk(KERN_ERR "e3d: Cannot allocate fb_info\n"); | ||
| 276 | err = -ENOMEM; | 275 | err = -ENOMEM; |
| 277 | goto err_disable; | 276 | goto err_disable; |
| 278 | } | 277 | } |
| @@ -1416,10 +1416,8 @@ static int tgafb_register(struct device *dev) · 1415 unmodified lines | |||
| 1416 | 1416 | ||
| 1417 | /* Allocate the fb and par structures. */ | 1417 | /* Allocate the fb and par structures. */ |
| 1418 | info = framebuffer_alloc(sizeof(struct tga_par), dev); | 1418 | info = framebuffer_alloc(sizeof(struct tga_par), dev); |
| 1419 | if (!info) { | 1419 | if (!info) |
| 1420 | printk(KERN_ERR "tgafb: Cannot allocate memory\n"); | ||
| 1421 | return -ENOMEM; | 1420 | return -ENOMEM; |
| 1422 | } | ||
| 1423 | 1421 | ||
| 1424 | par = info->par; | 1422 | par = info->par; |
| 1425 | dev_set_drvdata(dev, info); | 1423 | dev_set_drvdata(dev, info); |
| @@ -1686,10 +1686,8 @@ static int dlfb_usb_probe(struct usb_interface *intf, · 1685 unmodified lines | |||
| 1686 | 1686 | ||
| 1687 | /* allocates framebuffer driver structure, not framebuffer memory */ | 1687 | /* allocates framebuffer driver structure, not framebuffer memory */ |
| 1688 | info = framebuffer_alloc(0, &dlfb->udev->dev); | 1688 | info = framebuffer_alloc(0, &dlfb->udev->dev); |
| 1689 | if (!info) { | 1689 | if (!info) |
| 1690 | dev_err(&dlfb->udev->dev, "framebuffer_alloc failed\n"); | ||
| 1691 | goto error; | 1690 | goto error; |
| 1692 | } | ||
| 1693 | 1691 | ||
| 1694 | dlfb->info = info; | 1692 | dlfb->info = info; |
| 1695 | info->par = dlfb; | 1693 | info->par = dlfb; |
| @@ -1742,10 +1742,8 @@ int via_fb_pci_probe(struct viafb_dev *vdev) · 1741 unmodified lines | |||
| 1742 | viafbinfo = framebuffer_alloc(viafb_par_length + | 1742 | viafbinfo = framebuffer_alloc(viafb_par_length + |
| 1743 | ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), | 1743 | ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), |
| 1744 | &vdev->pdev->dev); | 1744 | &vdev->pdev->dev); |
| 1745 | if (!viafbinfo) { | 1745 | if (!viafbinfo) |
| 1746 | printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); | ||
| 1747 | return -ENOMEM; | 1746 | return -ENOMEM; |
| 1748 | } | ||
| 1749 | 1747 | ||
| 1750 | viaparinfo = (struct viafb_par *)viafbinfo->par; | 1748 | viaparinfo = (struct viafb_par *)viafbinfo->par; |
| 1751 | viaparinfo->shared = viafbinfo->par + viafb_par_length; | 1749 | viaparinfo->shared = viafbinfo->par + viafb_par_length; |
| @@ -1820,8 +1818,6 @@ int via_fb_pci_probe(struct viafb_dev *vdev) · 68 unmodified lines | |||
| 1820 | viafbinfo1 = framebuffer_alloc(viafb_par_length, | 1818 | viafbinfo1 = framebuffer_alloc(viafb_par_length, |
| 1821 | &vdev->pdev->dev); | 1819 | &vdev->pdev->dev); |
| 1822 | if (!viafbinfo1) { | 1820 | if (!viafbinfo1) { |
| 1823 | printk(KERN_ERR | ||
| 1824 | "allocate the second framebuffer struct error\n"); | ||
| 1825 | rc = -ENOMEM; | 1821 | rc = -ENOMEM; |
| 1826 | goto out_fb_release; | 1822 | goto out_fb_release; |
| 1827 | } | 1823 | } |
| @@ -669,10 +669,8 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 668 unmodified lines | |||
| 669 | 669 | ||
| 670 | /* Allocate and fill driver data structure */ | 670 | /* Allocate and fill driver data structure */ |
| 671 | info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev)); | 671 | info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev)); |
| 672 | if (! info) { | 672 | if (!info) |
| 673 | dev_err(&(dev->dev), "cannot allocate memory\n"); | ||
| 674 | return -ENOMEM; | 673 | return -ENOMEM; |
| 675 | } | ||
| 676 | 674 | ||
| 677 | par = info->par; | 675 | par = info->par; |
| 678 | mutex_init(&par->open_lock); | 676 | mutex_init(&par->open_lock); |
| @@ -168,9 +168,6 @@ extern void vc_SAK(struct work_struct *work); · 167 unmodified lines | |||
| 168 | 168 | ||
| 169 | #define CUR_DEFAULT CUR_UNDERLINE | 169 | #define CUR_DEFAULT CUR_UNDERLINE |
| 170 | 170 | ||
| 171 | static inline bool con_is_visible(const struct vc_data *vc) | 171 | bool con_is_visible(const struct vc_data *vc); |
| 172 | { | ||
| 173 | return *vc->vc_display_fg == vc; | ||
| 174 | } | ||
| 175 | 172 | ||
| 176 | #endif /* _LINUX_CONSOLE_STRUCT_H */ | 173 | #endif /* _LINUX_CONSOLE_STRUCT_H */ |
| @@ -126,39 +126,15 @@ struct fb_cursor_user { · 125 unmodified lines | |||
| 126 | 126 | ||
| 127 | /* The resolution of the passed in fb_info about to change */ | 127 | /* The resolution of the passed in fb_info about to change */ |
| 128 | #define FB_EVENT_MODE_CHANGE 0x01 | 128 | #define FB_EVENT_MODE_CHANGE 0x01 |
| 129 | /* The display on this fb_info is being suspended, no access to the | 129 | |
| 130 | * framebuffer is allowed any more after that call returns | 130 | #ifdef CONFIG_GUMSTIX_AM200EPD |
| 131 | */ | 131 | /* only used by mach-pxa/am200epd.c */ |
| 132 | #define FB_EVENT_SUSPEND 0x02 | ||
| 133 | /* The display on this fb_info was resumed, you can restore the display | ||
| 134 | * if you own it | ||
| 135 | */ | ||
| 136 | #define FB_EVENT_RESUME 0x03 | ||
| 137 | /* An entry from the modelist was removed */ | ||
| 138 | #define FB_EVENT_MODE_DELETE 0x04 | ||
| 139 | /* A driver registered itself */ | ||
| 140 | #define FB_EVENT_FB_REGISTERED 0x05 | 132 | #define FB_EVENT_FB_REGISTERED 0x05 |
| 141 | /* A driver unregistered itself */ | ||
| 142 | #define FB_EVENT_FB_UNREGISTERED 0x06 | 133 | #define FB_EVENT_FB_UNREGISTERED 0x06 |
| 143 | /* CONSOLE-SPECIFIC: get console to framebuffer mapping */ | 134 | #endif |
| 144 | #define FB_EVENT_GET_CONSOLE_MAP 0x07 | 135 | |
| 145 | /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ | 136 | /* A display blank is requested */ |
| 146 | #define FB_EVENT_SET_CONSOLE_MAP 0x08 | ||
| 147 | /* A hardware display blank change occurred */ | ||
| 148 | #define FB_EVENT_BLANK 0x09 | 137 | #define FB_EVENT_BLANK 0x09 |
| 149 | /* Private modelist is to be replaced */ | ||
| 150 | #define FB_EVENT_NEW_MODELIST 0x0A | ||
| 151 | /* The resolution of the passed in fb_info about to change and | ||
| 152 | all vc's should be changed */ | ||
| 153 | #define FB_EVENT_MODE_CHANGE_ALL 0x0B | ||
| 154 | /* A software display blank change occurred */ | ||
| 155 | #define FB_EVENT_CONBLANK 0x0C | ||
| 156 | /* Get drawing requirements */ | ||
| 157 | #define FB_EVENT_GET_REQ 0x0D | ||
| 158 | /* Unbind from the console if possible */ | ||
| 159 | #define FB_EVENT_FB_UNBIND 0x0E | ||
| 160 | /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ | ||
| 161 | #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F | ||
| 162 | /* A hardware display blank early change occurred */ | 138 | /* A hardware display blank early change occurred */ |
| 163 | #define FB_EARLY_EVENT_BLANK 0x10 | 139 | #define FB_EARLY_EVENT_BLANK 0x10 |
| 164 | /* A hardware display blank revert early change occurred */ | 140 | /* A hardware display blank revert early change occurred */ |
| @@ -633,8 +609,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, · 468 unmodified lines | |||
| 633 | 609 | ||
| 634 | /* drivers/video/fbmem.c */ | 610 | /* drivers/video/fbmem.c */ |
| 635 | extern int register_framebuffer(struct fb_info *fb_info); | 611 | extern int register_framebuffer(struct fb_info *fb_info); |
| 636 | extern int unregister_framebuffer(struct fb_info *fb_info); | 612 | extern void unregister_framebuffer(struct fb_info *fb_info); |
| 637 | extern int unlink_framebuffer(struct fb_info *fb_info); | 613 | extern void unlink_framebuffer(struct fb_info *fb_info); |
| 638 | extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, | 614 | extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, |
| 639 | const char *name); | 615 | const char *name); |
| 640 | extern int remove_conflicting_framebuffers(struct apertures_struct *a, | 616 | extern int remove_conflicting_framebuffers(struct apertures_struct *a, |
| @@ -660,7 +636,10 @@ extern struct class *fb_class; · 19 unmodified lines | |||
| 660 | for (i = 0; i < FB_MAX; i++) \ | 636 | for (i = 0; i < FB_MAX; i++) \ |
| 661 | if (!registered_fb[i]) {} else | 637 | if (!registered_fb[i]) {} else |
| 662 | 638 | ||
| 663 | extern int lock_fb_info(struct fb_info *info); | 639 | static inline void lock_fb_info(struct fb_info *info) |
| 640 | { | ||
| 641 | mutex_lock(&info->lock); | ||
| 642 | } | ||
| 664 | 643 | ||
| 665 | static inline void unlock_fb_info(struct fb_info *info) | 644 | static inline void unlock_fb_info(struct fb_info *info) |
| 666 | { | 645 | { |
| @@ -4,9 +4,39 @@ · 3 unmodified lines | |||
| 4 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE | 4 | #ifdef CONFIG_FRAMEBUFFER_CONSOLE |
| 5 | void __init fb_console_init(void); | 5 | void __init fb_console_init(void); |
| 6 | void __exit fb_console_exit(void); | 6 | void __exit fb_console_exit(void); |
| 7 | int fbcon_fb_registered(struct fb_info *info); | ||
| 8 | void fbcon_fb_unregistered(struct fb_info *info); | ||
| 9 | void fbcon_fb_unbind(struct fb_info *info); | ||
| 10 | void fbcon_suspended(struct fb_info *info); | ||
| 11 | void fbcon_resumed(struct fb_info *info); | ||
| 12 | int fbcon_mode_deleted(struct fb_info *info, | ||
| 13 | struct fb_videomode *mode); | ||
| 14 | void fbcon_new_modelist(struct fb_info *info); | ||
| 15 | void fbcon_get_requirement(struct fb_info *info, | ||
| 16 | struct fb_blit_caps *caps); | ||
| 17 | void fbcon_fb_blanked(struct fb_info *info, int blank); | ||
| 18 | void fbcon_update_vcs(struct fb_info *info, bool all); | ||
| 19 | void fbcon_remap_all(struct fb_info *info); | ||
| 20 | int fbcon_set_con2fb_map_ioctl(void __user *argp); | ||
| 21 | int fbcon_get_con2fb_map_ioctl(void __user *argp); | ||
| 7 | #else | 22 | #else |
| 8 | static inline void fb_console_init(void) {} | 23 | static inline void fb_console_init(void) {} |
| 9 | static inline void fb_console_exit(void) {} | 24 | static inline void fb_console_exit(void) {} |
| 25 | static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } | ||
| 26 | static inline void fbcon_fb_unregistered(struct fb_info *info) {} | ||
| 27 | static inline void fbcon_fb_unbind(struct fb_info *info) {} | ||
| 28 | static inline void fbcon_suspended(struct fb_info *info) {} | ||
| 29 | static inline void fbcon_resumed(struct fb_info *info) {} | ||
| 30 | static inline int fbcon_mode_deleted(struct fb_info *info, | ||
| 31 | struct fb_videomode *mode) { return 0; } | ||
| 32 | static inline void fbcon_new_modelist(struct fb_info *info) {} | ||
| 33 | static inline void fbcon_get_requirement(struct fb_info *info, | ||
| 34 | struct fb_blit_caps *caps) {} | ||
| 35 | static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} | ||
| 36 | static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} | ||
| 37 | static inline void fbcon_remap_all(struct fb_info *info) {} | ||
| 38 | static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; } | ||
| 39 | static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; } | ||
| 10 | #endif | 40 | #endif |
| 11 | 41 | ||
| 12 | #endif /* _LINUX_FBCON_H */ | 42 | #endif /* _LINUX_FBCON_H */ |
| @@ -114,11 +114,6 @@ enum omap_dss_trans_key_type { · 113 unmodified lines | |||
| 114 | OMAP_DSS_COLOR_KEY_VID_SRC = 1, | 114 | OMAP_DSS_COLOR_KEY_VID_SRC = 1, |
| 115 | }; | 115 | }; |
| 116 | 116 | ||
| 117 | enum omap_rfbi_te_mode { | ||
| 118 | OMAP_DSS_RFBI_TE_MODE_1 = 1, | ||
| 119 | OMAP_DSS_RFBI_TE_MODE_2 = 2, | ||
| 120 | }; | ||
| 121 | |||
| 122 | enum omap_dss_signal_level { | 117 | enum omap_dss_signal_level { |
| 123 | OMAPDSS_SIG_ACTIVE_LOW, | 118 | OMAPDSS_SIG_ACTIVE_LOW, |
| 124 | OMAPDSS_SIG_ACTIVE_HIGH, | 119 | OMAPDSS_SIG_ACTIVE_HIGH, |
| @@ -189,27 +184,6 @@ enum omap_dss_output_id { · 64 unmodified lines | |||
| 189 | OMAP_DSS_OUTPUT_HDMI = 1 << 6, | 184 | OMAP_DSS_OUTPUT_HDMI = 1 << 6, |
| 190 | }; | 185 | }; |
| 191 | 186 | ||
| 192 | /* RFBI */ | ||
| 193 | |||
| 194 | struct rfbi_timings { | ||
| 195 | int cs_on_time; | ||
| 196 | int cs_off_time; | ||
| 197 | int we_on_time; | ||
| 198 | int we_off_time; | ||
| 199 | int re_on_time; | ||
| 200 | int re_off_time; | ||
| 201 | int we_cycle_time; | ||
| 202 | int re_cycle_time; | ||
| 203 | int cs_pulse_width; | ||
| 204 | int access_time; | ||
| 205 | |||
| 206 | int clk_div; | ||
| 207 | |||
| 208 | u32 tim[5]; /* set by rfbi_convert_timings() */ | ||
| 209 | |||
| 210 | int converted; | ||
| 211 | }; | ||
| 212 | |||
| 213 | /* DSI */ | 187 | /* DSI */ |
| 214 | 188 | ||
| 215 | enum omap_dss_dsi_trans_mode { | 189 | enum omap_dss_dsi_trans_mode { |
| @@ -640,11 +614,6 @@ struct omap_dss_device { · 424 unmodified lines | |||
| 640 | u8 data_lines; | 614 | u8 data_lines; |
| 641 | } dpi; | 615 | } dpi; |
| 642 | 616 | ||
| 643 | struct { | ||
| 644 | u8 channel; | ||
| 645 | u8 data_lines; | ||
| 646 | } rfbi; | ||
| 647 | |||
| 648 | struct { | 617 | struct { |
| 649 | u8 datapairs; | 618 | u8 datapairs; |
| 650 | } sdi; | 619 | } sdi; |
| @@ -668,7 +637,6 @@ struct omap_dss_device { · 17 unmodified lines | |||
| 668 | 637 | ||
| 669 | struct { | 638 | struct { |
| 670 | u8 pixel_size; | 639 | u8 pixel_size; |
| 671 | struct rfbi_timings rfbi_timings; | ||
| 672 | } ctrl; | 640 | } ctrl; |
| 673 | 641 | ||
| 674 | const char *name; | 642 | const char *name; |