diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2022-06-20 18:21:25 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2022-06-20 18:21:25 +0200 |
commit | 2b1333b80885b896807ffb6ccf4bc21d29aa65e0 (patch) | |
tree | 51cc2d13d65603383db82c87f01a0aa93bd26010 /drivers/video | |
parent | fbcon: Fix boundary checks for fbcon=vc:n1-n2 parameters (diff) | |
parent | Merge tag 'drm-misc-next-2022-06-08' of git://anongit.freedesktop.org/drm/drm... (diff) | |
download | linux-2b1333b80885b896807ffb6ccf4bc21d29aa65e0.tar.xz linux-2b1333b80885b896807ffb6ccf4bc21d29aa65e0.zip |
Merge drm/drm-next into drm-misc-next
Backmerging to get new regmap APIs of v5.19-rc1.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Diffstat (limited to 'drivers/video')
33 files changed, 878 insertions, 146 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index e32694c13da5..a003e02e13ce 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -211,8 +211,8 @@ config BACKLIGHT_LOCOMO config BACKLIGHT_OMAP1 tristate "OMAP1 PWL-based LCD Backlight" - depends on ARCH_OMAP1 - default y + depends on ARCH_OMAP1 || COMPILE_TEST + default ARCH_OMAP1 help This driver controls the LCD backlight level and power for the PWL module of OMAP1 processors. Say Y if your board diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 74263021b1b3..69a49384b3de 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -14,8 +14,8 @@ #include <linux/slab.h> #include <linux/platform_data/omap1_bl.h> -#include <mach/hardware.h> -#include <mach/mux.h> +#include <linux/soc/ti/omap1-io.h> +#include <linux/soc/ti/omap1-mux.h> #define OMAPBL_MAX_INTENSITY 0xff diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 40496e9e9b43..f304163e87e9 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -46,6 +46,7 @@ #include <linux/slab.h> #include <linux/font.h> #include <linux/crc32.h> +#include <linux/fb.h> #include <asm/io.h> @@ -392,7 +393,9 @@ static int __init sticonsole_init(void) for (i = 0; i < MAX_NR_CONSOLES; i++) font_data[i] = STI_DEF_FONT; - pr_info("sticon: Initializing STI text console.\n"); + pr_info("sticon: Initializing STI text console on %s at [%s]\n", + sticon_sti->sti_data->inq_outptr.dev_name, + sticon_sti->pa_path); console_lock(); err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, PAGE0->mem_cons.cl_class != CL_DUPLEX); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index f869b723494f..fa23bf0247b0 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -30,10 +30,11 @@ #include <asm/pdc.h> #include <asm/cacheflush.h> #include <asm/grfioctl.h> +#include <asm/fb.h> #include "../fbdev/sticore.h" -#define STI_DRIVERVERSION "Version 0.9b" +#define STI_DRIVERVERSION "Version 0.9c" static struct sti_struct *default_sti __read_mostly; @@ -502,7 +503,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) if (!fbfont) return NULL; - pr_info("STI selected %ux%u framebuffer font %s for sticon\n", + pr_info(" using %ux%u framebuffer font %s\n", fbfont->width, fbfont->height, fbfont->name); bpc = ((fbfont->width+7)/8) * fbfont->height; @@ -549,6 +550,26 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } #endif +static void sti_dump_font(struct sti_cooked_font *font) +{ +#ifdef STI_DUMP_FONT + unsigned char *p = (unsigned char *)font->raw; + int n; + + p += sizeof(struct sti_rom_font); + pr_debug(" w %d h %d bpc %d\n", font->width, font->height, + font->raw->bytes_per_char); + + for (n = 0; n < 256 * font->raw->bytes_per_char; n += 16, p += 16) { + pr_debug(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x," + " 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x," + " 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], + p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + } +#endif +} + static int sti_search_font(struct sti_cooked_rom *rom, int height, int width) { struct sti_cooked_font *font; @@ -796,6 +817,7 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, sti->font->width = sti->font->raw->width; sti->font->height = sti->font->raw->height; sti_font_convert_bytemode(sti, sti->font); + sti_dump_font(sti->font); sti->sti_mem_request = raw->sti_mem_req; sti->graphics_id[0] = raw->graphics_id[0]; @@ -946,6 +968,7 @@ out_err: static void sticore_check_for_default_sti(struct sti_struct *sti, char *path) { + pr_info(" located at [%s]\n", sti->pa_path); if (strcmp (path, default_sti_path) == 0) default_sti = sti; } @@ -957,7 +980,6 @@ static void sticore_check_for_default_sti(struct sti_struct *sti, char *path) */ static int __init sticore_pa_init(struct parisc_device *dev) { - char pa_path[21]; struct sti_struct *sti = NULL; int hpa = dev->hpa.start; @@ -970,8 +992,8 @@ static int __init sticore_pa_init(struct parisc_device *dev) if (!sti) return 1; - print_pa_hwpath(dev, pa_path); - sticore_check_for_default_sti(sti, pa_path); + print_pa_hwpath(dev, sti->pa_path); + sticore_check_for_default_sti(sti, sti->pa_path); return 0; } @@ -1007,9 +1029,8 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) sti = sti_try_rom_generic(rom_base, fb_base, pd); if (sti) { - char pa_path[30]; - print_pci_hwpath(pd, pa_path); - sticore_check_for_default_sti(sti, pa_path); + print_pci_hwpath(pd, sti->pa_path); + sticore_check_for_default_sti(sti, sti->pa_path); } if (!sti) { @@ -1127,6 +1148,22 @@ int sti_call(const struct sti_struct *sti, unsigned long func, return ret; } +/* check if given fb_info is the primary device */ +int fb_is_primary_device(struct fb_info *info) +{ + struct sti_struct *sti; + + sti = sti_get_rom(0); + + /* if no built-in graphics card found, allow any fb driver as default */ + if (!sti) + return true; + + /* return true if it's the default built-in framebuffer driver */ + return (sti->info == info); +} +EXPORT_SYMBOL(fb_is_primary_device); + MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer"); MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 477b9624b703..7795c4126706 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -110,7 +110,7 @@ obj-$(CONFIG_FB_UDL) += udlfb.o obj-$(CONFIG_FB_SMSCUFX) += smscufx.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o -obj-$(CONFIG_FB_OMAP) += omap/ +obj-y += omap/ obj-y += omap2/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c index 9ec969e136bf..8080116aea84 100644 --- a/drivers/video/fbdev/amba-clcd.c +++ b/drivers/video/fbdev/amba-clcd.c @@ -758,12 +758,15 @@ static int clcdfb_of_vram_setup(struct clcd_fb *fb) return -ENODEV; fb->fb.screen_base = of_iomap(memory, 0); - if (!fb->fb.screen_base) + if (!fb->fb.screen_base) { + of_node_put(memory); return -ENOMEM; + } fb->fb.fix.smem_start = of_translate_address(memory, of_get_address(memory, 0, &size, NULL)); fb->fb.fix.smem_len = size; + of_node_put(memory); return 0; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index e0720fef0ee6..c4a18322dee9 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1788,53 +1788,6 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, EXPORT_SYMBOL(remove_conflicting_framebuffers); /** - * is_firmware_framebuffer - detect if firmware-configured framebuffer matches - * @a: memory range, users of which are to be checked - * - * This function checks framebuffer devices (initialized by firmware/bootloader) - * which use memory range described by @a. If @a matchesm the function returns - * true, otherwise false. - */ -bool is_firmware_framebuffer(struct apertures_struct *a) -{ - bool do_free = false; - bool found = false; - int i; - - if (!a) { - a = alloc_apertures(1); - if (!a) - return false; - - a->ranges[0].base = 0; - a->ranges[0].size = ~0; - do_free = true; - } - - mutex_lock(®istration_lock); - /* check all firmware fbs and kick off if the base addr overlaps */ - for_each_registered_fb(i) { - struct apertures_struct *gen_aper; - - if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) - continue; - - gen_aper = registered_fb[i]->apertures; - if (fb_do_apertures_overlap(gen_aper, a)) { - found = true; - break; - } - } - mutex_unlock(®istration_lock); - - if (do_free) - kfree(a); - - return found; -} -EXPORT_SYMBOL(is_firmware_framebuffer); - -/** * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices * @pdev: PCI device * @name: requesting driver name diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index 8c1ee9ecec3d..c2a60b187467 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c @@ -80,6 +80,10 @@ void framebuffer_release(struct fb_info *info) { if (!info) return; + + if (WARN_ON(refcount_read(&info->count))) + return; + kfree(info->apertures); kfree(info); } diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index edca3703b964..16c1aaae9afa 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c @@ -243,6 +243,10 @@ error: static inline void efifb_show_boot_graphics(struct fb_info *info) {} #endif +/* + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end + * of unregister_framebuffer() or fb_release(). Do any cleanup here. + */ static void efifb_destroy(struct fb_info *info) { if (efifb_pci_dev) @@ -254,10 +258,13 @@ static void efifb_destroy(struct fb_info *info) else memunmap(info->screen_base); } + if (request_mem_succeeded) release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); fb_dealloc_cmap(&info->cmap); + + framebuffer_release(info); } static const struct fb_ops efifb_ops = { @@ -609,9 +616,9 @@ static int efifb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); + /* efifb_destroy takes care of info cleanup */ unregister_framebuffer(info); sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); - framebuffer_release(info); return 0; } diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 8359a513b600..886c564787f1 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -63,6 +63,7 @@ #define MAX_VMBUS_PKT_SIZE 0x4000 #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) +/* Support for VERSION_WIN7 is removed. #define is retained for reference. */ #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) #define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5) @@ -70,13 +71,7 @@ #define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff) #define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16) -#define SYNTHVID_DEPTH_WIN7 16 #define SYNTHVID_DEPTH_WIN8 32 - -#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024) -#define SYNTHVID_WIDTH_MAX_WIN7 1600 -#define SYNTHVID_HEIGHT_MAX_WIN7 1200 - #define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024) #define PCI_VENDOR_ID_MICROSOFT 0x1414 @@ -643,12 +638,6 @@ static int synthvid_connect_vsp(struct hv_device *hdev) case VERSION_WIN8: case VERSION_WIN8_1: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8); - if (!ret) - break; - fallthrough; - case VERSION_WS2008: - case VERSION_WIN7: - ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); break; default: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10); @@ -660,11 +649,7 @@ static int synthvid_connect_vsp(struct hv_device *hdev) goto error; } - if (par->synthvid_version == SYNTHVID_VERSION_WIN7) - screen_depth = SYNTHVID_DEPTH_WIN7; - else - screen_depth = SYNTHVID_DEPTH_WIN8; - + screen_depth = SYNTHVID_DEPTH_WIN8; if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) { ret = synthvid_get_supported_resolution(hdev); if (ret) @@ -933,9 +918,7 @@ static void hvfb_get_option(struct fb_info *info) (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && (x * y * screen_depth / 8 > screen_fb_size)) || (par->synthvid_version == SYNTHVID_VERSION_WIN8 && - x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) || - (par->synthvid_version == SYNTHVID_VERSION_WIN7 && - (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) { + x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8)) { pr_err("Screen resolution option is out of range: skipped\n"); return; } @@ -1009,7 +992,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) struct pci_dev *pdev = NULL; void __iomem *fb_virt; int gen2vm = efi_enabled(EFI_BOOT); - resource_size_t pot_start, pot_end; phys_addr_t paddr; int ret; @@ -1060,23 +1042,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) dio_fb_size = screen_width * screen_height * screen_depth / 8; - if (gen2vm) { - pot_start = 0; - pot_end = -1; - } else { - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || - pci_resource_len(pdev, 0) < screen_fb_size) { - pr_err("Resource not available or (0x%lx < 0x%lx)\n", - (unsigned long) pci_resource_len(pdev, 0), - (unsigned long) screen_fb_size); - goto err1; - } - - pot_end = pci_resource_end(pdev, 0); - pot_start = pot_end - screen_fb_size + 1; - } - - ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end, + ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1, screen_fb_size, 0x100000, true); if (ret != 0) { pr_err("Unable to allocate framebuffer memory\n"); diff --git a/drivers/video/fbdev/mx3fb.c b/drivers/video/fbdev/mx3fb.c index fabb271337ed..b945b68984b9 100644 --- a/drivers/video/fbdev/mx3fb.c +++ b/drivers/video/fbdev/mx3fb.c @@ -26,7 +26,7 @@ #include <linux/dma/ipu-dma.h> #include <linux/backlight.h> -#include <linux/platform_data/dma-imx.h> +#include <linux/dma/imx-dma.h> #include <linux/platform_data/video-mx3fb.h> #include <asm/io.h> diff --git a/drivers/video/fbdev/omap/Kconfig b/drivers/video/fbdev/omap/Kconfig index df2a5d0d4aa2..b1786cf1b486 100644 --- a/drivers/video/fbdev/omap/Kconfig +++ b/drivers/video/fbdev/omap/Kconfig @@ -2,7 +2,7 @@ config FB_OMAP tristate "OMAP frame buffer support" depends on FB - depends on ARCH_OMAP1 + depends on ARCH_OMAP1 || (ARM && COMPILE_TEST) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -42,7 +42,7 @@ config FB_OMAP_LCD_MIPID config FB_OMAP_LCD_H3 bool "TPS65010 LCD controller on OMAP-H3" - depends on MACH_OMAP_H3 + depends on MACH_OMAP_H3 || COMPILE_TEST depends on TPS65010=y default y help diff --git a/drivers/video/fbdev/omap/Makefile b/drivers/video/fbdev/omap/Makefile index daaa73a94e7f..b88e02f5cb1f 100644 --- a/drivers/video/fbdev/omap/Makefile +++ b/drivers/video/fbdev/omap/Makefile @@ -5,6 +5,11 @@ obj-$(CONFIG_FB_OMAP) += omapfb.o +ifdef CONFIG_FB_OMAP +# must be built-in +obj-y += lcd_dma.o +endif + objs-yy := omapfb_main.o lcdc.o objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c index bbf871f9d862..6f860c814d2c 100644 --- a/drivers/video/fbdev/omap/lcd_ams_delta.c +++ b/drivers/video/fbdev/omap/lcd_ams_delta.c @@ -14,7 +14,7 @@ #include <linux/gpio/consumer.h> #include <linux/lcd.h> -#include <mach/hardware.h> +#include <linux/soc/ti/omap1-io.h> #include "omapfb.h" @@ -128,7 +128,6 @@ static struct lcd_panel ams_delta_panel = { static int ams_delta_panel_probe(struct platform_device *pdev) { struct lcd_device *lcd_device = NULL; - int ret; gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW); if (IS_ERR(gpiod_vblen)) @@ -145,7 +144,8 @@ static int ams_delta_panel_probe(struct platform_device *pdev) &ams_delta_lcd_ops); if (IS_ERR(lcd_device)) { - ret = PTR_ERR(lcd_device); + int ret = PTR_ERR(lcd_device); + dev_err(&pdev->dev, "failed to register device\n"); return ret; } diff --git a/drivers/video/fbdev/omap/lcd_dma.c b/drivers/video/fbdev/omap/lcd_dma.c new file mode 100644 index 000000000000..f85817635a8c --- /dev/null +++ b/drivers/video/fbdev/omap/lcd_dma.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * linux/arch/arm/mach-omap1/lcd_dma.c + * + * Extracted from arch/arm/plat-omap/dma.c + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä <juha.yrjola@nokia.com> + * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak <imre.deak@nokia.com> + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com> + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * Support functions for the OMAP internal DMA channels. + */ + +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/io.h> + +#include <linux/omap-dma.h> + +#include <linux/soc/ti/omap1-soc.h> +#include <linux/soc/ti/omap1-io.h> + +#include "lcdc.h" +#include "lcd_dma.h" + +int omap_lcd_dma_running(void) +{ + /* + * On OMAP1510, internal LCD controller will start the transfer + * when it gets enabled, so assume DMA running if LCD enabled. + */ + if (cpu_is_omap15xx()) + if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN) + return 1; + + /* Check if LCD DMA is running */ + if (cpu_is_omap16xx()) + if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) + return 1; + + return 0; +} + +static struct lcd_dma_info { + spinlock_t lock; + int reserved; + void (*callback)(u16 status, void *data); + void *cb_data; + + int active; + unsigned long addr; + int rotate, data_type, xres, yres; + int vxres; + int mirror; + int xscale, yscale; + int ext_ctrl; + int src_port; + int single_transfer; +} lcd_dma; + +void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, + int data_type) +{ + lcd_dma.addr = addr; + lcd_dma.data_type = data_type; + lcd_dma.xres = fb_xres; + lcd_dma.yres = fb_yres; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1); + +void omap_set_lcd_dma_ext_controller(int external) +{ + lcd_dma.ext_ctrl = external; +} +EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); + +void omap_set_lcd_dma_single_transfer(int single) +{ + lcd_dma.single_transfer = single; +} +EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); + +void omap_set_lcd_dma_b1_rotation(int rotate) +{ + if (cpu_is_omap15xx()) { + printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); + BUG(); + return; + } + lcd_dma.rotate = rotate; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); + +void omap_set_lcd_dma_b1_mirror(int mirror) +{ + if (cpu_is_omap15xx()) { + printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.mirror = mirror; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); + +void omap_set_lcd_dma_b1_vxres(unsigned long vxres) +{ + if (cpu_is_omap15xx()) { + pr_err("DMA virtual resolution is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.vxres = vxres; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); + +void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) +{ + if (cpu_is_omap15xx()) { + printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); + BUG(); + } + lcd_dma.xscale = xscale; + lcd_dma.yscale = yscale; +} +EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); + +static void set_b1_regs(void) +{ + unsigned long top, bottom; + int es; + u16 w; + unsigned long en, fn; + long ei, fi; + unsigned long vxres; + unsigned int xscale, yscale; + + switch (lcd_dma.data_type) { + case OMAP_DMA_DATA_TYPE_S8: + es = 1; + break; + case OMAP_DMA_DATA_TYPE_S16: + es = 2; + break; + case OMAP_DMA_DATA_TYPE_S32: + es = 4; + break; + default: + BUG(); + return; + } + + vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; + xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; + yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; + BUG_ON(vxres < lcd_dma.xres); + +#define PIXADDR(x, y) (lcd_dma.addr + \ + ((y) * vxres * yscale + (x) * xscale) * es) +#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) + + switch (lcd_dma.rotate) { + case 0: + if (!lcd_dma.mirror) { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + /* 1510 DMA requires the bottom address to be 2 more + * than the actual last memory access location. */ + if (cpu_is_omap15xx() && + lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) + bottom += 2; + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); + } + en = lcd_dma.xres; + fn = lcd_dma.yres; + break; + case 90: + if (!lcd_dma.mirror) { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); + } else { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(0, 1, 0, 0); + fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); + } + en = lcd_dma.yres; + fn = lcd_dma.xres; + break; + case 180: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + bottom = PIXADDR(0, 0); + ei = PIXSTEP(1, 0, 0, 0); + fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); + } else { + top = PIXADDR(0, lcd_dma.yres - 1); + bottom = PIXADDR(lcd_dma.xres - 1, 0); + ei = PIXSTEP(0, 0, 1, 0); + fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); + } + en = lcd_dma.xres; + fn = lcd_dma.yres; + break; + case 270: + if (!lcd_dma.mirror) { + top = PIXADDR(lcd_dma.xres - 1, 0); + bottom = PIXADDR(0, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); + } else { + top = PIXADDR(0, 0); + bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); + ei = PIXSTEP(0, 0, 0, 1); + fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); + } + en = lcd_dma.yres; + fn = lcd_dma.xres; + break; + default: + BUG(); + return; /* Suppress warning about uninitialized vars */ + } + + if (cpu_is_omap15xx()) { + omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); + omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); + omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); + omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L); + + return; + } + + /* 1610 regs */ + omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U); + omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L); + omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U); + omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L); + + omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1); + omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1); + + w = omap_readw(OMAP1610_DMA_LCD_CSDP); + w &= ~0x03; + w |= lcd_dma.data_type; + omap_writew(w, OMAP1610_DMA_LCD_CSDP); + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + /* Always set the source port as SDRAM for now*/ + w &= ~(0x03 << 6); + if (lcd_dma.callback != NULL) + w |= 1 << 1; /* Block interrupt enable */ + else + w &= ~(1 << 1); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + + if (!(lcd_dma.rotate || lcd_dma.mirror || + lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + /* Set the double-indexed addressing mode */ + w |= (0x03 << 12); + omap_writew(w, OMAP1610_DMA_LCD_CCR); + + omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); + omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); + omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); +} + +static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id) +{ + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + if (unlikely(!(w & (1 << 3)))) { + printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); + return IRQ_NONE; + } + /* Ack the IRQ */ + w |= (1 << 3); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + lcd_dma.active = 0; + if (lcd_dma.callback != NULL) + lcd_dma.callback(w, lcd_dma.cb_data); + + return IRQ_HANDLED; +} + +int omap_request_lcd_dma(void (*callback)(u16 status, void *data), + void *data) +{ + spin_lock_irq(&lcd_dma.lock); + if (lcd_dma.reserved) { + spin_unlock_irq(&lcd_dma.lock); + printk(KERN_ERR "LCD DMA channel already reserved\n"); + BUG(); + return -EBUSY; + } + lcd_dma.reserved = 1; + spin_unlock_irq(&lcd_dma.lock); + lcd_dma.callback = callback; + lcd_dma.cb_data = data; + lcd_dma.active = 0; + lcd_dma.single_transfer = 0; + lcd_dma.rotate = 0; + lcd_dma.vxres = 0; + lcd_dma.mirror = 0; + lcd_dma.xscale = 0; + lcd_dma.yscale = 0; + lcd_dma.ext_ctrl = 0; + lcd_dma.src_port = 0; + + return 0; +} +EXPORT_SYMBOL(omap_request_lcd_dma); + +void omap_free_lcd_dma(void) +{ + spin_lock(&lcd_dma.lock); + if (!lcd_dma.reserved) { + spin_unlock(&lcd_dma.lock); + printk(KERN_ERR "LCD DMA is not reserved\n"); + BUG(); + return; + } + if (!cpu_is_omap15xx()) + omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, + OMAP1610_DMA_LCD_CCR); + lcd_dma.reserved = 0; + spin_unlock(&lcd_dma.lock); +} +EXPORT_SYMBOL(omap_free_lcd_dma); + +void omap_enable_lcd_dma(void) +{ + u16 w; + + /* + * Set the Enable bit only if an external controller is + * connected. Otherwise the OMAP internal controller will + * start the transfer when it gets enabled. + */ + if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w |= 1 << 8; + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + + lcd_dma.active = 1; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + w |= 1 << 7; + omap_writew(w, OMAP1610_DMA_LCD_CCR); +} +EXPORT_SYMBOL(omap_enable_lcd_dma); + +void omap_setup_lcd_dma(void) +{ + BUG_ON(lcd_dma.active); + if (!cpu_is_omap15xx()) { + /* Set some reasonable defaults */ + omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); + omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); + omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); + } + set_b1_regs(); + if (!cpu_is_omap15xx()) { + u16 w; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + /* + * If DMA was already active set the end_prog bit to have + * the programmed register set loaded into the active + * register set. + */ + w |= 1 << 11; /* End_prog */ + if (!lcd_dma.single_transfer) + w |= (3 << 8); /* Auto_init, repeat */ + omap_writew(w, OMAP1610_DMA_LCD_CCR); + } +} +EXPORT_SYMBOL(omap_setup_lcd_dma); + +void omap_stop_lcd_dma(void) +{ + u16 w; + + lcd_dma.active = 0; + if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) + return; + + w = omap_readw(OMAP1610_DMA_LCD_CCR); + w &= ~(1 << 7); + omap_writew(w, OMAP1610_DMA_LCD_CCR); + + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w &= ~(1 << 8); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); +} +EXPORT_SYMBOL(omap_stop_lcd_dma); + +static int __init omap_init_lcd_dma(void) +{ + int r; + + if (!cpu_class_is_omap1()) + return -ENODEV; + + if (cpu_is_omap16xx()) { + u16 w; + + /* this would prevent OMAP sleep */ + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w &= ~(1 << 8); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + } + + spin_lock_init(&lcd_dma.lock); + + r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, + "LCD DMA", NULL); + if (r != 0) + pr_err("unable to request IRQ for LCD DMA (error %d)\n", r); + + return r; +} + +arch_initcall(omap_init_lcd_dma); + diff --git a/drivers/video/fbdev/omap/lcd_dma.h b/drivers/video/fbdev/omap/lcd_dma.h new file mode 100644 index 000000000000..1b4780197381 --- /dev/null +++ b/drivers/video/fbdev/omap/lcd_dma.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * arch/arm/mach-omap1/include/mach/lcd_dma.h + * + * Extracted from arch/arm/plat-omap/include/plat/dma.h + * Copyright (C) 2003 Nokia Corporation + * Author: Juha Yrjölä <juha.yrjola@nokia.com> + */ +#ifndef __MACH_OMAP1_LCD_DMA_H__ +#define __MACH_OMAP1_LCD_DMA_H__ + +/* Hardware registers for LCD DMA */ +#define OMAP1510_DMA_LCD_BASE (0xfffedb00) +#define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00) +#define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02) +#define OMAP1510_DMA_LCD_TOP_F1_U (OMAP1510_DMA_LCD_BASE + 0x04) +#define OMAP1510_DMA_LCD_BOT_F1_L (OMAP1510_DMA_LCD_BASE + 0x06) +#define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08) + +#define OMAP1610_DMA_LCD_BASE (0xfffee300) +#define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0) +#define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2) +#define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4) +#define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8) +#define OMAP1610_DMA_LCD_TOP_B1_U (OMAP1610_DMA_LCD_BASE + 0xca) +#define OMAP1610_DMA_LCD_BOT_B1_L (OMAP1610_DMA_LCD_BASE + 0xcc) +#define OMAP1610_DMA_LCD_BOT_B1_U (OMAP1610_DMA_LCD_BASE + 0xce) +#define OMAP1610_DMA_LCD_TOP_B2_L (OMAP1610_DMA_LCD_BASE + 0xd0) +#define OMAP1610_DMA_LCD_TOP_B2_U (OMAP1610_DMA_LCD_BASE + 0xd2) +#define OMAP1610_DMA_LCD_BOT_B2_L (OMAP1610_DMA_LCD_BASE + 0xd4) +#define OMAP1610_DMA_LCD_BOT_B2_U (OMAP1610_DMA_LCD_BASE + 0xd6) +#define OMAP1610_DMA_LCD_SRC_EI_B1 (OMAP1610_DMA_LCD_BASE + 0xd8) +#define OMAP1610_DMA_LCD_SRC_FI_B1_L (OMAP1610_DMA_LCD_BASE + 0xda) +#define OMAP1610_DMA_LCD_SRC_EN_B1 (OMAP1610_DMA_LCD_BASE + 0xe0) +#define OMAP1610_DMA_LCD_SRC_FN_B1 (OMAP1610_DMA_LCD_BASE + 0xe4) +#define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) +#define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) + +/* LCD DMA block numbers */ +enum { + OMAP_LCD_DMA_B1_TOP, + OMAP_LCD_DMA_B1_BOTTOM, + OMAP_LCD_DMA_B2_TOP, + OMAP_LCD_DMA_B2_BOTTOM +}; + +/* LCD DMA functions */ +extern int omap_request_lcd_dma(void (*callback)(u16 status, void *data), + void *data); +extern void omap_free_lcd_dma(void); +extern void omap_setup_lcd_dma(void); +extern void omap_enable_lcd_dma(void); +extern void omap_stop_lcd_dma(void); +extern void omap_set_lcd_dma_ext_controller(int external); +extern void omap_set_lcd_dma_single_transfer(int single); +extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, + int data_type); +extern void omap_set_lcd_dma_b1_rotation(int rotate); +extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres); +extern void omap_set_lcd_dma_b1_mirror(int mirror); +extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale); + +#endif /* __MACH_OMAP1_LCD_DMA_H__ */ diff --git a/drivers/video/fbdev/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c index 776e7f8d656e..bb915637e9b6 100644 --- a/drivers/video/fbdev/omap/lcd_inn1510.c +++ b/drivers/video/fbdev/omap/lcd_inn1510.c @@ -10,19 +10,21 @@ #include <linux/platform_device.h> #include <linux/io.h> -#include <mach/hardware.h> +#include <linux/soc/ti/omap1-soc.h> #include "omapfb.h" +static void __iomem *omap1510_fpga_lcd_panel_control; + static int innovator1510_panel_enable(struct lcd_panel *panel) { - __raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL); + __raw_writeb(0x7, omap1510_fpga_lcd_panel_control); return 0; } static void innovator1510_panel_disable(struct lcd_panel *panel) { - __raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL); + __raw_writeb(0x0, omap1510_fpga_lcd_panel_control); } static struct lcd_panel innovator1510_panel = { @@ -48,6 +50,7 @@ static struct lcd_panel innovator1510_panel = { static int innovator1510_panel_probe(struct platform_device *pdev) { + omap1510_fpga_lcd_panel_control = (void __iomem *)pdev->dev.platform_data; omapfb_register_panel(&innovator1510_panel); return 0; } diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c index 5d5762128c8d..8168ba0d47fd 100644 --- a/drivers/video/fbdev/omap/lcd_osk.c +++ b/drivers/video/fbdev/omap/lcd_osk.c @@ -11,8 +11,8 @@ #include <linux/platform_device.h> #include <linux/gpio.h> -#include <mach/hardware.h> -#include <mach/mux.h> +#include <linux/soc/ti/omap1-io.h> +#include <linux/soc/ti/omap1-mux.h> #include "omapfb.h" diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c index 97d20dc0d1d0..e7ce783e5215 100644 --- a/drivers/video/fbdev/omap/lcdc.c +++ b/drivers/video/fbdev/omap/lcdc.c @@ -17,7 +17,8 @@ #include <linux/clk.h> #include <linux/gfp.h> -#include <mach/lcdc.h> +#include <linux/soc/ti/omap1-io.h> +#include <linux/soc/ti/omap1-soc.h> #include <linux/omap-dma.h> #include <asm/mach-types.h> @@ -25,6 +26,7 @@ #include "omapfb.h" #include "lcdc.h" +#include "lcd_dma.h" #define MODULE_NAME "lcdc" @@ -713,7 +715,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, } clk_prepare_enable(lcdc.lcd_ck); - r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev); + r = request_irq(fbdev->int_irq, lcdc_irq_handler, 0, MODULE_NAME, fbdev); if (r) { dev_err(fbdev->dev, "unable to get IRQ\n"); goto fail2; @@ -744,7 +746,7 @@ fail5: fail4: omap_free_lcd_dma(); fail3: - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); + free_irq(fbdev->int_irq, lcdc.fbdev); fail2: clk_disable_unprepare(lcdc.lcd_ck); fail1: @@ -759,7 +761,7 @@ static void omap_lcdc_cleanup(void) free_palette_ram(); free_fbmem(); omap_free_lcd_dma(); - free_irq(OMAP_LCDC_IRQ, lcdc.fbdev); + free_irq(lcdc.fbdev->int_irq, lcdc.fbdev); clk_disable_unprepare(lcdc.lcd_ck); clk_put(lcdc.lcd_ck); } diff --git a/drivers/video/fbdev/omap/lcdc.h b/drivers/video/fbdev/omap/lcdc.h index 8a7607d861c1..cbbfd9b9e949 100644 --- a/drivers/video/fbdev/omap/lcdc.h +++ b/drivers/video/fbdev/omap/lcdc.h @@ -1,6 +1,41 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef LCDC_H #define LCDC_H +/* + * Copyright (C) 2004 Nokia Corporation + * Author: Imre Deak <imre.deak@nokia.com> + */ +#define OMAP_LCDC_BASE 0xfffec000 +#define OMAP_LCDC_SIZE 256 +#define OMAP_LCDC_IRQ INT_LCD_CTRL + +#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00) +#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04) +#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08) +#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c) +#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10) +#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14) +#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18) +#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c) + +#define OMAP_LCDC_STAT_DONE (1 << 0) +#define OMAP_LCDC_STAT_VSYNC (1 << 1) +#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2) +#define OMAP_LCDC_STAT_ABC (1 << 3) +#define OMAP_LCDC_STAT_LINE_INT (1 << 4) +#define OMAP_LCDC_STAT_FUF (1 << 5) +#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6) + +#define OMAP_LCDC_CTRL_LCD_EN (1 << 0) +#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7) +#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10) + +#define OMAP_LCDC_IRQ_VSYNC (1 << 2) +#define OMAP_LCDC_IRQ_DONE (1 << 3) +#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4) +#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5) +#define OMAP_LCDC_IRQ_LINE (1 << 6) +#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2) int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data); void omap_lcdc_free_dma_callback(void); diff --git a/drivers/video/fbdev/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h index d930152c289c..beb841ccb99c 100644 --- a/drivers/video/fbdev/omap/omapfb.h +++ b/drivers/video/fbdev/omap/omapfb.h @@ -204,6 +204,8 @@ struct omapfb_device { struct lcd_panel *panel; /* LCD panel */ const struct lcd_ctrl *ctrl; /* LCD controller */ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ + int ext_irq; + int int_irq; struct lcd_ctrl_extif *ext_if; /* LCD ctrl external interface */ struct device *dev; @@ -229,5 +231,9 @@ extern int omapfb_update_window_async(struct fb_info *fbi, struct omapfb_update_window *win, void (*callback)(void *), void *callback_data); +extern int hwa742_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data); #endif /* __OMAPFB_H */ diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 083388a4ceeb..292fcb0a24fc 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -20,8 +20,7 @@ #include <linux/omap-dma.h> -#include <mach/hardware.h> - +#include <linux/soc/ti/omap1-soc.h> #include "omapfb.h" #include "lcdc.h" @@ -1624,7 +1623,7 @@ static int omapfb_do_probe(struct platform_device *pdev, init_state = 0; - if (pdev->num_resources != 0) { + if (pdev->num_resources != 2) { dev_err(&pdev->dev, "probed for an unknown device\n"); r = -ENODEV; goto cleanup; @@ -1643,6 +1642,20 @@ static int omapfb_do_probe(struct platform_device *pdev, r = -ENOMEM; goto cleanup; } + fbdev->int_irq = platform_get_irq(pdev, 0); + if (!fbdev->int_irq) { + dev_err(&pdev->dev, "unable to get irq\n"); + r = ENXIO; + goto cleanup; + } + + fbdev->ext_irq = platform_get_irq(pdev, 1); + if (!fbdev->ext_irq) { + dev_err(&pdev->dev, "unable to get irq\n"); + r = ENXIO; + goto cleanup; + } + init_state++; fbdev->dev = &pdev->dev; diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c index b9cb8b386627..c90eb8ca58af 100644 --- a/drivers/video/fbdev/omap/sossi.c +++ b/drivers/video/fbdev/omap/sossi.c @@ -13,8 +13,10 @@ #include <linux/interrupt.h> #include <linux/omap-dma.h> +#include <linux/soc/ti/omap1-io.h> #include "omapfb.h" +#include "lcd_dma.h" #include "lcdc.h" #define MODULE_NAME "omapfb-sossi" @@ -638,7 +640,7 @@ static int sossi_init(struct omapfb_device *fbdev) l &= ~(1 << 31); /* REORDERING */ sossi_write_reg(SOSSI_INIT1_REG, l); - if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq, + if ((r = request_irq(fbdev->ext_irq, sossi_match_irq, IRQ_TYPE_EDGE_FALLING, "sossi_match", sossi.fbdev->dev)) < 0) { dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n"); diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c index be9910ff6e62..b407173e27b1 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c @@ -117,16 +117,11 @@ static int nec_8048_connect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - int r; if (omapdss_device_is_connected(dssdev)) return 0; - r = in->ops.dpi->connect(in, dssdev); - if (r) - return r; - - return 0; + return in->ops.dpi->connect(in, dssdev); } static void nec_8048_disconnect(struct omap_dss_device *dssdev) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c index c5f89129dcdd..531b36d2232b 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c @@ -173,7 +173,6 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data { struct dss_pll *pll = &hpll->pll; struct clk *clk; - int r; clk = devm_clk_get(&pdev->dev, "sys_clk"); if (IS_ERR(clk)) { @@ -203,12 +202,7 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data } pll->ops = &dsi_pll_ops; - - r = dss_pll_register(pll); - if (r) - return r; - - return 0; + return dss_pll_register(pll); } int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c index 350b3139c863..043cc8f9ef1c 100644 --- a/drivers/video/fbdev/pxa3xx-gcu.c +++ b/drivers/video/fbdev/pxa3xx-gcu.c @@ -646,6 +646,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) for (i = 0; i < 8; i++) { ret = pxa3xx_gcu_add_buffer(dev, priv); if (ret) { + pxa3xx_gcu_free_buffers(dev, priv); dev_err(dev, "failed to allocate DMA memory\n"); goto err_disable_clk; } @@ -662,15 +663,15 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) SHARED_SIZE, irq); return 0; -err_free_dma: - dma_free_coherent(dev, SHARED_SIZE, - priv->shared, priv->shared_phys); +err_disable_clk: + clk_disable_unprepare(priv->clk); err_misc_deregister: misc_deregister(&priv->misc_dev); -err_disable_clk: - clk_disable_unprepare(priv->clk); +err_free_dma: + dma_free_coherent(dev, SHARED_SIZE, + priv->shared, priv->shared_phys); return ret; } @@ -683,6 +684,7 @@ static int pxa3xx_gcu_remove(struct platform_device *pdev) pxa3xx_gcu_wait_idle(priv); misc_deregister(&priv->misc_dev); dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys); + clk_disable_unprepare(priv->clk); pxa3xx_gcu_free_buffers(dev, priv); return 0; diff --git a/drivers/video/fbdev/pxa3xx-regs.h b/drivers/video/fbdev/pxa3xx-regs.h new file mode 100644 index 000000000000..6a96610ef9b5 --- /dev/null +++ b/drivers/video/fbdev/pxa3xx-regs.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_ARCH_REGS_LCD_H +#define __ASM_ARCH_REGS_LCD_H + +/* + * LCD Controller Registers and Bits Definitions + */ +#define LCCR0 (0x000) /* LCD Controller Control Register 0 */ +#define LCCR1 (0x004) /* LCD Controller Control Register 1 */ +#define LCCR2 (0x008) /* LCD Controller Control Register 2 */ +#define LCCR3 (0x00C) /* LCD Controller Control Register 3 */ +#define LCCR4 (0x010) /* LCD Controller Control Register 4 */ +#define LCCR5 (0x014) /* LCD Controller Control Register 5 */ +#define LCSR (0x038) /* LCD Controller Status Register 0 */ +#define LCSR1 (0x034) /* LCD Controller Status Register 1 */ +#define LIIDR (0x03C) /* LCD Controller Interrupt ID Register */ +#define TMEDRGBR (0x040) /* TMED RGB Seed Register */ +#define TMEDCR (0x044) /* TMED Control Register */ + +#define FBR0 (0x020) /* DMA Channel 0 Frame Branch Register */ +#define FBR1 (0x024) /* DMA Channel 1 Frame Branch Register */ +#define FBR2 (0x028) /* DMA Channel 2 Frame Branch Register */ +#define FBR3 (0x02C) /* DMA Channel 2 Frame Branch Register */ +#define FBR4 (0x030) /* DMA Channel 2 Frame Branch Register */ +#define FBR5 (0x110) /* DMA Channel 2 Frame Branch Register */ +#define FBR6 (0x114) /* DMA Channel 2 Frame Branch Register */ + +#define OVL1C1 (0x050) /* Overlay 1 Control Register 1 */ +#define OVL1C2 (0x060) /* Overlay 1 Control Register 2 */ +#define OVL2C1 (0x070) /* Overlay 2 Control Register 1 */ +#define OVL2C2 (0x080) /* Overlay 2 Control Register 2 */ + +#define CMDCR (0x100) /* Command Control Register */ +#define PRSR (0x104) /* Panel Read Status Register */ + +#define LCCR3_BPP(x) ((((x) & 0x7) << 24) | (((x) & 0x8) ? (1 << 29) : 0)) + +#define LCCR3_PDFOR_0 (0 << 30) +#define LCCR3_PDFOR_1 (1 << 30) +#define LCCR3_PDFOR_2 (2 << 30) +#define LCCR3_PDFOR_3 (3 << 30) + +#define LCCR4_PAL_FOR_0 (0 << 15) +#define LCCR4_PAL_FOR_1 (1 << 15) +#define LCCR4_PAL_FOR_2 (2 << 15) +#define LCCR4_PAL_FOR_3 (3 << 15) +#define LCCR4_PAL_FOR_MASK (3 << 15) + +#define FDADR0 (0x200) /* DMA Channel 0 Frame Descriptor Address Register */ +#define FDADR1 (0x210) /* DMA Channel 1 Frame Descriptor Address Register */ +#define FDADR2 (0x220) /* DMA Channel 2 Frame Descriptor Address Register */ +#define FDADR3 (0x230) /* DMA Channel 3 Frame Descriptor Address Register */ +#define FDADR4 (0x240) /* DMA Channel 4 Frame Descriptor Address Register */ +#define FDADR5 (0x250) /* DMA Channel 5 Frame Descriptor Address Register */ +#define FDADR6 (0x260) /* DMA Channel 6 Frame Descriptor Address Register */ + +#define LCCR0_ENB (1 << 0) /* LCD Controller enable */ +#define LCCR0_CMS (1 << 1) /* Color/Monochrome Display Select */ +#define LCCR0_Color (LCCR0_CMS*0) /* Color display */ +#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */ +#define LCCR0_SDS (1 << 2) /* Single/Dual Panel Display Select */ +#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */ +#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */ + +#define LCCR0_LDM (1 << 3) /* LCD Disable Done Mask */ +#define LCCR0_SFM (1 << 4) /* Start of frame mask */ +#define LCCR0_IUM (1 << 5) /* Input FIFO underrun mask */ +#define LCCR0_EFM (1 << 6) /* End of Frame mask */ +#define LCCR0_PAS (1 << 7) /* Passive/Active display Select */ +#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */ +#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */ +#define LCCR0_DPD (1 << 9) /* Double Pixel Data (monochrome) */ +#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome display */ +#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome display */ +#define LCCR0_DIS (1 << 10) /* LCD Disable */ +#define LCCR0_QDM (1 << 11) /* LCD Quick Disable mask */ +#define LCCR0_PDD (0xff << 12) /* Palette DMA request delay */ +#define LCCR0_PDD_S 12 +#define LCCR0_BM (1 << 20) /* Branch mask */ +#define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */ +#define LCCR0_LCDT (1 << 22) /* LCD panel type */ +#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */ +#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */ +#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */ +#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */ + +#define Fld(Size, Shft) (((Size) << 16) + (Shft)) +#define FShft(Field) ((Field) & 0x0000FFFF) + +#define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */ +#define LCCR1_DisWdth(Pixel) (((Pixel) - 1) << FShft (LCCR1_PPL)) + +#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */ +#define LCCR1_HorSnchWdth(Tpix) (((Tpix) - 1) << FShft (LCCR1_HSW)) + +#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait - 1 */ +#define LCCR1_EndLnDel(Tpix) (((Tpix) - 1) << FShft (LCCR1_ELW)) + +#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */ +#define LCCR1_BegLnDel(Tpix) (((Tpix) - 1) << FShft (LCCR1_BLW)) + +#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */ +#define LCCR2_DisHght(Line) (((Line) - 1) << FShft (LCCR2_LPP)) + +#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse - 1 */ +#define LCCR2_VrtSnchWdth(Tln) (((Tln) - 1) << FShft (LCCR2_VSW)) + +#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */ +#define LCCR2_EndFrmDel(Tln) ((Tln) << FShft (LCCR2_EFW)) + +#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */ +#define LCCR2_BegFrmDel(Tln) ((Tln) << FShft (LCCR2_BFW)) + +#define LCCR3_API (0xf << 16) /* AC Bias pin trasitions per interrupt */ +#define LCCR3_API_S 16 +#define LCCR3_VSP (1 << 20) /* vertical sync polarity */ +#define LCCR3_HSP (1 << 21) /* horizontal sync polarity */ +#define LCCR3_PCP (1 << 22) /* Pixel Clock Polarity (L_PCLK) */ +#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */ +#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */ + +#define LCCR3_OEP (1 << 23) /* Output Enable Polarity */ +#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */ +#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */ + +#define LCCR3_DPC (1 << 27) /* double pixel clock mode */ +#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor */ +#define LCCR3_PixClkDiv(Div) (((Div) << FShft (LCCR3_PCD))) + +#define LCCR3_ACB Fld (8, 8) /* AC Bias */ +#define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB))) + +#define LCCR3_HorSnchH (LCCR3_HSP*0) /* HSP Active High */ +#define LCCR3_HorSnchL (LCCR3_HSP*1) /* HSP Active Low */ + +#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* VSP Active High */ +#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* VSP Active Low */ + +#define LCCR5_IUM(x) (1 << ((x) + 23)) /* input underrun mask */ +#define LCCR5_BSM(x) (1 << ((x) + 15)) /* branch mask */ +#define LCCR5_EOFM(x) (1 << ((x) + 7)) /* end of frame mask */ +#define LCCR5_SOFM(x) (1 << ((x) + 0)) /* start of frame mask */ + +#define LCSR_LDD (1 << 0) /* LCD Disable Done */ +#define LCSR_SOF (1 << 1) /* Start of frame */ +#define LCSR_BER (1 << 2) /* Bus error */ +#define LCSR_ABC (1 << 3) /* AC Bias count */ +#define LCSR_IUL (1 << 4) /* input FIFO underrun Lower panel */ +#define LCSR_IUU (1 << 5) /* input FIFO underrun Upper panel */ +#define LCSR_OU (1 << 6) /* output FIFO underrun */ +#define LCSR_QD (1 << 7) /* quick disable */ +#define LCSR_EOF (1 << 8) /* end of frame */ +#define LCSR_BS (1 << 9) /* branch status */ +#define LCSR_SINT (1 << 10) /* subsequent interrupt */ +#define LCSR_RD_ST (1 << 11) /* read status */ +#define LCSR_CMD_INT (1 << 12) /* command interrupt */ + +#define LCSR1_IU(x) (1 << ((x) + 23)) /* Input FIFO underrun */ +#define LCSR1_BS(x) (1 << ((x) + 15)) /* Branch Status */ +#define LCSR1_EOF(x) (1 << ((x) + 7)) /* End of Frame Status */ +#define LCSR1_SOF(x) (1 << ((x) - 1)) /* Start of Frame Status */ + +#define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */ + +/* overlay control registers */ +#define OVLxC1_PPL(x) ((((x) - 1) & 0x3ff) << 0) /* Pixels Per Line */ +#define OVLxC1_LPO(x) ((((x) - 1) & 0x3ff) << 10) /* Number of Lines */ +#define OVLxC1_BPP(x) (((x) & 0xf) << 20) /* Bits Per Pixel */ +#define OVLxC1_OEN (1 << 31) /* Enable bit for Overlay */ +#define OVLxC2_XPOS(x) (((x) & 0x3ff) << 0) /* Horizontal Position */ +#define OVLxC2_YPOS(x) (((x) & 0x3ff) << 10) /* Vertical Position */ +#define OVL2C2_PFOR(x) (((x) & 0x7) << 20) /* Pixel Format */ + +/* smartpanel related */ +#define PRSR_DATA(x) ((x) & 0xff) /* Panel Data */ +#define PRSR_A0 (1 << 8) /* Read Data Source */ +#define PRSR_ST_OK (1 << 9) /* Status OK */ +#define PRSR_CON_NT (1 << 10) /* Continue to Next Command */ + +#endif /* __ASM_ARCH_REGS_LCD_H */ diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 8ad91c251fe6..66cfc3e9d3cf 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -57,14 +57,13 @@ #include <linux/console.h> #include <linux/of_graph.h> #include <linux/regulator/consumer.h> +#include <linux/soc/pxa/cpu.h> #include <video/of_display_timing.h> #include <video/videomode.h> -#include <mach/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/div64.h> -#include <mach/bitfield.h> #include <linux/platform_data/video-pxafb.h> /* @@ -73,6 +72,7 @@ #define DEBUG_VAR 1 #include "pxafb.h" +#include "pxa3xx-regs.h" /* Bits which should not be set in machine configuration structures */ #define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\ diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c index 0ef41173325a..991a31846ae7 100644 --- a/drivers/video/fbdev/simplefb.c +++ b/drivers/video/fbdev/simplefb.c @@ -84,6 +84,10 @@ struct simplefb_par { static void simplefb_clocks_destroy(struct simplefb_par *par); static void simplefb_regulators_destroy(struct simplefb_par *par); +/* + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end + * of unregister_framebuffer() or fb_release(). Do any cleanup here. + */ static void simplefb_destroy(struct fb_info *info) { struct simplefb_par *par = info->par; @@ -94,6 +98,8 @@ static void simplefb_destroy(struct fb_info *info) if (info->screen_base) iounmap(info->screen_base); + framebuffer_release(info); + if (mem) release_mem_region(mem->start, resource_size(mem)); } @@ -534,8 +540,8 @@ static int simplefb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); + /* simplefb_destroy takes care of info cleanup */ unregister_framebuffer(info); - framebuffer_release(info); return 0; } diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h index c338f7848ae2..0ebdd28a0b81 100644 --- a/drivers/video/fbdev/sticore.h +++ b/drivers/video/fbdev/sticore.h @@ -370,6 +370,9 @@ struct sti_struct { /* pointer to all internal data */ struct sti_all_data *sti_data; + + /* pa_path of this device */ + char pa_path[24]; }; diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index bebb2eea6448..38a861e22c33 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -1358,11 +1358,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) goto out_err3; } + /* save for primary gfx device detection & unregister_framebuffer() */ + sti->info = info; if (register_framebuffer(&fb->info) < 0) goto out_err4; - sti->info = info; /* save for unregister_framebuffer() */ - fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n", fix->id, var->xres, diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c index df6de5a9dd4c..929d4775cb4b 100644 --- a/drivers/video/fbdev/vesafb.c +++ b/drivers/video/fbdev/vesafb.c @@ -179,6 +179,10 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, return err; } +/* + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end + * of unregister_framebuffer() or fb_release(). Do any cleanup here. + */ static void vesafb_destroy(struct fb_info *info) { struct vesafb_par *par = info->par; @@ -188,6 +192,8 @@ static void vesafb_destroy(struct fb_info *info) if (info->screen_base) iounmap(info->screen_base); release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); + + framebuffer_release(info); } static struct fb_ops vesafb_ops = { @@ -484,10 +490,11 @@ static int vesafb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); - unregister_framebuffer(info); if (((struct vesafb_par *)(info->par))->region) release_region(0x3c0, 32); - framebuffer_release(info); + + /* vesafb_destroy takes care of info cleanup */ + unregister_framebuffer(info); return 0; } diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 3bed357a9870..4d2694d904aa 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -223,7 +223,6 @@ static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green, red = CNVT_TOHW(red, info->var.red.length); green = CNVT_TOHW(green, info->var.green.length); blue = CNVT_TOHW(blue, info->var.blue.length); - transp = CNVT_TOHW(transp, info->var.transp.length); #undef CNVT_TOHW v = (red << info->var.red.offset) | |