diff options
Diffstat (limited to 'drivers/video')
225 files changed, 5880 insertions, 4525 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index fa44fbed397d..552258c8f99d 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -478,11 +478,10 @@ int __init mc68x328fb_init(void) return -EINVAL; } - printk(KERN_INFO - "fb%d: %s frame buffer device\n", fb_info.node, fb_info.fix.id); - printk(KERN_INFO - "fb%d: %dx%dx%d at 0x%08lx\n", fb_info.node, - mc68x328fb_default.xres_virtual, mc68x328fb_default.yres_virtual, + fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id); + fb_info(&fb_info, "%dx%dx%d at 0x%08lx\n", + mc68x328fb_default.xres_virtual, + mc68x328fb_default.yres_virtual, 1 << mc68x328fb_default.bits_per_pixel, videomemory); return 0; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 84b685f7ab6e..22262a3a0e2d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -19,10 +19,10 @@ source "drivers/char/agp/Kconfig" source "drivers/gpu/vga/Kconfig" -source "drivers/gpu/drm/Kconfig" - source "drivers/gpu/host1x/Kconfig" +source "drivers/gpu/drm/Kconfig" + config VGASTATE tristate default n @@ -312,7 +312,8 @@ config FB_PM2_FIFO_DISCONNECT config FB_ARMCLCD tristate "ARM PrimeCell PL110 support" - depends on FB && ARM && ARM_AMBA + depends on ARM || ARM64 || COMPILE_TEST + depends on FB && ARM_AMBA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -979,6 +980,22 @@ config FB_PVR2 (<file:drivers/video/pvr2fb.c>). Please see the file <file:Documentation/fb/pvr2fb.txt>. +config FB_OPENCORES + tristate "OpenCores VGA/LCD core 2.0 framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the OpenCores VGA/LCD core. + + The OpenCores VGA/LCD core is typically used together with + softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor + systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs. + + The source code and specification for the core is available at + <http://opencores.org/project,vga_lcd> + config FB_S1D13XXX tristate "Epson S1D13XXX framebuffer support" depends on FB @@ -996,6 +1013,8 @@ config FB_ATMEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS help This enables support for the AT91/AT32 LCD Controller. diff --git a/drivers/video/Makefile b/drivers/video/Makefile index e8bae8dd4804..ae17ddf49a00 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -150,6 +150,7 @@ obj-$(CONFIG_FB_NUC900) += nuc900fb.o obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o +obj-$(CONFIG_FB_OPENCORES) += ocfb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 7e8346ec9cdc..a305caea58ee 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -949,9 +949,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) * the page. */ page = virt_to_page(virtual_start); - ClearPageReserved(page); - init_page_count(page); - free_page(virtual_start); + __free_reserved_page(page); virtual_start += PAGE_SIZE; mb_freed += PAGE_SIZE / 1024; diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 0a2cce7285be..14d6b3793e0a 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -10,6 +10,7 @@ * * ARM PrimeCell PL110 Color LCD Controller */ +#include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -544,13 +545,17 @@ static int clcdfb_register(struct clcd_fb *fb) static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) { - struct clcd_board *board = dev->dev.platform_data; + struct clcd_board *board = dev_get_platdata(&dev->dev); struct clcd_fb *fb; int ret; if (!board) return -EINVAL; + ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)); + if (ret) + goto out; + ret = amba_request_regions(dev, NULL); if (ret) { printk(KERN_ERR "CLCD: unable to reserve regs region\n"); @@ -594,8 +599,6 @@ static int clcdfb_remove(struct amba_device *dev) { struct clcd_fb *fb = amba_get_drvdata(dev); - amba_set_drvdata(dev, NULL); - clcdfb_disable(fb); unregister_framebuffer(&fb->fb); if (fb->fb.cmap.len) diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index a6780eecff0e..0dac36ce09d6 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -3742,13 +3742,12 @@ default_chipset: if (err) goto unset_drvdata; - printk("fb%d: %s frame buffer device, using %dK of video memory\n", - info->node, info->fix.id, info->fix.smem_len>>10); + fb_info(info, "%s frame buffer device, using %dK of video memory\n", + info->fix.id, info->fix.smem_len>>10); return 0; unset_drvdata: - dev_set_drvdata(&pdev->dev, NULL); fb_dealloc_cmap(&info->cmap); free_irq: free_irq(IRQ_AMIGA_COPPER, info->par); @@ -3768,7 +3767,6 @@ static int __exit amifb_remove(struct platform_device *pdev) struct fb_info *info = dev_get_drvdata(&pdev->dev); unregister_framebuffer(info); - dev_set_drvdata(&pdev->dev, NULL); fb_dealloc_cmap(&info->cmap); free_irq(IRQ_AMIGA_COPPER, info->par); custom.dmacon = DMAF_ALL | DMAF_MASTER; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index e43401afdd03..1b0b233b8b39 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -556,9 +556,8 @@ static int arcfb_probe(struct platform_device *dev) goto err1; } } - printk(KERN_INFO - "fb%d: Arc frame buffer device, using %dK of video memory\n", - info->node, videomemorysize >> 10); + fb_info(info, "Arc frame buffer device, using %dK of video memory\n", + videomemorysize >> 10); /* this inits the lcd but doesn't clear dirty pixels */ for (i = 0; i < num_cols * num_rows; i++) { @@ -572,8 +571,7 @@ static int arcfb_probe(struct platform_device *dev) /* if we were told to splash the screen, we just clear it */ if (!nosplash) { for (i = 0; i < num_cols * num_rows; i++) { - printk(KERN_INFO "fb%d: splashing lcd %d\n", - info->node, i); + fb_info(info, "splashing lcd %d\n", i); ks108_set_start_line(par, i, 0); ks108_clear_lcd(par, i); } diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 94a51f1ef904..a6b29bd4a12a 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c @@ -137,8 +137,7 @@ static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map) if ((map->width != 8) || (map->height != 16) || (map->depth != 1) || (map->length != 256)) { - printk(KERN_ERR "fb%d: unsupported font parameters: width %d, " - "height %d, depth %d, length %d\n", info->node, + fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n", map->width, map->height, map->depth, map->length); return; } @@ -517,7 +516,7 @@ static void ark_set_pixclock(struct fb_info *info, u32 pixclock) int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock); if (rv < 0) { - printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + fb_err(info, "cannot set requested pixclock, keeping old value\n"); return; } @@ -584,7 +583,7 @@ static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) rv = svga_match_format (arkfb_formats, var, NULL); if (rv < 0) { - printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node); + fb_err(info, "unsupported mode requested\n"); return rv; } @@ -604,14 +603,15 @@ static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual; if (mem > info->screen_size) { - printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10)); + fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n", + mem >> 10, (unsigned int) (info->screen_size >> 10)); return -EINVAL; } rv = svga_check_timings (&ark_timing_regs, var, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: invalid timings requested\n", info->node); + fb_err(info, "invalid timings requested\n"); return rv; } @@ -693,7 +693,7 @@ static int arkfb_set_par(struct fb_info *info) vga_wseq(par->state.vgabase, 0x18, regval); /* Set the offset register */ - pr_debug("fb%d: offset register : %d\n", info->node, offset_value); + fb_dbg(info, "offset register : %d\n", offset_value); svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value); /* fix for hi-res textmode */ @@ -716,7 +716,7 @@ static int arkfb_set_par(struct fb_info *info) /* Set mode-specific register values */ switch (mode) { case 0: - pr_debug("fb%d: text mode\n", info->node); + fb_dbg(info, "text mode\n"); svga_set_textmode_vga_regs(par->state.vgabase); vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ @@ -725,7 +725,7 @@ static int arkfb_set_par(struct fb_info *info) break; case 1: - pr_debug("fb%d: 4 bit pseudocolor\n", info->node); + fb_dbg(info, "4 bit pseudocolor\n"); vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ @@ -733,44 +733,44 @@ static int arkfb_set_par(struct fb_info *info) dac_set_mode(par->dac, DAC_PSEUDO8_8); break; case 2: - pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); + fb_dbg(info, "4 bit pseudocolor, planar\n"); vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */ svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ dac_set_mode(par->dac, DAC_PSEUDO8_8); break; case 3: - pr_debug("fb%d: 8 bit pseudocolor\n", info->node); + fb_dbg(info, "8 bit pseudocolor\n"); vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */ if (info->var.pixclock > 20000) { - pr_debug("fb%d: not using multiplex\n", info->node); + fb_dbg(info, "not using multiplex\n"); svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */ dac_set_mode(par->dac, DAC_PSEUDO8_8); } else { - pr_debug("fb%d: using multiplex\n", info->node); + fb_dbg(info, "using multiplex\n"); svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ dac_set_mode(par->dac, DAC_PSEUDO8_16); hdiv = 2; } break; case 4: - pr_debug("fb%d: 5/5/5 truecolor\n", info->node); + fb_dbg(info, "5/5/5 truecolor\n"); vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */ svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ dac_set_mode(par->dac, DAC_RGB1555_16); break; case 5: - pr_debug("fb%d: 5/6/5 truecolor\n", info->node); + fb_dbg(info, "5/6/5 truecolor\n"); vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */ svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ dac_set_mode(par->dac, DAC_RGB0565_16); break; case 6: - pr_debug("fb%d: 8/8/8 truecolor\n", info->node); + fb_dbg(info, "8/8/8 truecolor\n"); vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */ svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ @@ -779,7 +779,7 @@ static int arkfb_set_par(struct fb_info *info) hdiv = 2; break; case 7: - pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); + fb_dbg(info, "8/8/8/8 truecolor\n"); vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */ svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */ @@ -787,7 +787,7 @@ static int arkfb_set_par(struct fb_info *info) hmul = 2; break; default: - printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); + fb_err(info, "unsupported mode - bug\n"); return -EINVAL; } @@ -879,19 +879,19 @@ static int arkfb_blank(int blank_mode, struct fb_info *info) switch (blank_mode) { case FB_BLANK_UNBLANK: - pr_debug("fb%d: unblank\n", info->node); + fb_dbg(info, "unblank\n"); svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); break; case FB_BLANK_NORMAL: - pr_debug("fb%d: blank\n", info->node); + fb_dbg(info, "blank\n"); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); break; case FB_BLANK_POWERDOWN: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND: - pr_debug("fb%d: sync down\n", info->node); + fb_dbg(info, "sync down\n"); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); break; @@ -1048,12 +1048,12 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) rc = register_framebuffer(info); if (rc < 0) { - dev_err(info->device, "cannot register framebugger\n"); + dev_err(info->device, "cannot register framebuffer\n"); goto err_reg_fb; } - printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id, - pci_name(dev), info->fix.smem_len >> 20); + fb_info(info, "%s on %s, %d MB RAM\n", + info->fix.id, pci_name(dev), info->fix.smem_len >> 20); /* Record a reference to the driver data */ pci_set_drvdata(dev, info); @@ -1108,7 +1108,6 @@ static void ark_pci_remove(struct pci_dev *dev) pci_release_regions(dev); /* pci_disable_device(dev); */ - pci_set_drvdata(dev, NULL); framebuffer_release(info); } } diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index d5a37d62847b..7e8ddf00ccc2 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -527,8 +527,8 @@ static int init_asiliant(struct fb_info *p, unsigned long addr) return err; } - printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", - p->node, p->fix.smem_len / 1024); + fb_info(p, "Asiliant 69000 frame buffer (%dK RAM detected)\n", + p->fix.smem_len / 1024); writeb(0xff, mmio_base + 0x78c); chips_hw_init(p); @@ -589,7 +589,6 @@ static void asiliantfb_remove(struct pci_dev *dp) fb_dealloc_cmap(&p->cmap); iounmap(p->screen_base); release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); - pci_set_drvdata(dp, NULL); framebuffer_release(p); } diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 64e41f5448c4..e21d1f58554c 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -3246,11 +3246,8 @@ int __init atafb_init(void) return -EINVAL; } - // FIXME: mode needs setting! - //printk("fb%d: %s frame buffer device, using %dK of video memory\n", - // fb_info.node, fb_info.mode->name, screen_len>>10); - printk("fb%d: frame buffer device, using %dK of video memory\n", - fb_info.node, screen_len >> 10); + fb_info(&fb_info, "frame buffer device, using %dK of video memory\n", + screen_len >> 10); /* TODO: This driver cannot be unloaded yet */ return 0; diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 088511a58a26..cd961622f9c1 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -20,12 +20,55 @@ #include <linux/gfp.h> #include <linux/module.h> #include <linux/platform_data/atmel.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <video/of_display_timing.h> +#include <video/videomode.h> #include <mach/cpu.h> #include <asm/gpio.h> #include <video/atmel_lcdc.h> +struct atmel_lcdfb_config { + bool have_alt_pixclock; + bool have_hozval; + bool have_intensity_bit; +}; + + /* LCD Controller info data structure, stored in device platform_data */ +struct atmel_lcdfb_info { + spinlock_t lock; + struct fb_info *info; + void __iomem *mmio; + int irq_base; + struct work_struct task; + + unsigned int smem_len; + struct platform_device *pdev; + struct clk *bus_clk; + struct clk *lcdc_clk; + + struct backlight_device *backlight; + u8 bl_power; + u8 saved_lcdcon; + + u32 pseudo_palette[16]; + bool have_intensity_bit; + + struct atmel_lcdfb_pdata pdata; + + struct atmel_lcdfb_config *config; +}; + +struct atmel_lcdfb_power_ctrl_gpio { + int gpio; + int active_low; + + struct list_head list; +}; + #define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg)) #define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg)) @@ -34,12 +77,6 @@ #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ #define ATMEL_LCDC_FIFO_SIZE 512 /* words */ -struct atmel_lcdfb_config { - bool have_alt_pixclock; - bool have_hozval; - bool have_intensity_bit; -}; - static struct atmel_lcdfb_config at91sam9261_config = { .have_hozval = true, .have_intensity_bit = true, @@ -94,6 +131,7 @@ static const struct platform_device_id atmel_lcdfb_devtypes[] = { /* terminator */ } }; +MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes); static struct atmel_lcdfb_config * atmel_lcdfb_get_config(struct platform_device *pdev) @@ -248,18 +286,27 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo) static void init_contrast(struct atmel_lcdfb_info *sinfo) { + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; + /* contrast pwm can be 'inverted' */ - if (sinfo->lcdcon_pol_negative) + if (pdata->lcdcon_pol_negative) contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE); /* have some default contrast/backlight settings */ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); - if (sinfo->lcdcon_is_backlight) + if (pdata->lcdcon_is_backlight) init_backlight(sinfo); } +static inline void atmel_lcdfb_power_control(struct atmel_lcdfb_info *sinfo, int on) +{ + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; + + if (pdata->atmel_lcdfb_power_control) + pdata->atmel_lcdfb_power_control(pdata, on); +} static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { .type = FB_TYPE_PACKED_PIXELS, @@ -299,9 +346,11 @@ static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo, static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo) { + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; + /* Turn off the LCD controller and the DMA controller */ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, - sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET); /* Wait for the LCDC core to become idle */ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) @@ -321,9 +370,11 @@ static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo) static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo) { - lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; + + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, pdata->default_dmacon); lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, - (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) + (pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); } @@ -424,6 +475,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, { struct device *dev = info->device; struct atmel_lcdfb_info *sinfo = info->par; + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; unsigned long clk_value_khz; clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; @@ -510,7 +562,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, else var->green.length = 6; - if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { + if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { /* RGB:5X5 mode */ var->red.offset = var->green.length + 5; var->blue.offset = 0; @@ -527,7 +579,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, var->transp.length = 8; /* fall through */ case 24: - if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { + if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { /* RGB:888 mode */ var->red.offset = 16; var->blue.offset = 0; @@ -576,6 +628,7 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) static int atmel_lcdfb_set_par(struct fb_info *info) { struct atmel_lcdfb_info *sinfo = info->par; + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; unsigned long hozval_linesz; unsigned long value; unsigned long clk_value_khz; @@ -637,7 +690,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) /* Initialize control register 2 */ - value = sinfo->default_lcdcon2; + value = pdata->default_lcdcon2; if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) value |= ATMEL_LCDC_INVLINE_INVERTED; @@ -741,6 +794,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int transp, struct fb_info *info) { struct atmel_lcdfb_info *sinfo = info->par; + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; unsigned int val; u32 *pal; int ret = 1; @@ -777,8 +831,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, */ } else { /* new style BGR:565 / RGB:565 */ - if (sinfo->lcd_wiring_mode == - ATMEL_LCDC_WIRING_RGB) { + if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { val = ((blue >> 11) & 0x001f); val |= ((red >> 0) & 0xf800); } else { @@ -912,16 +965,187 @@ static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) clk_disable_unprepare(sinfo->lcdc_clk); } +#ifdef CONFIG_OF +static const struct of_device_id atmel_lcdfb_dt_ids[] = { + { .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, }, + { .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, }, + { .compatible = "atmel,at91sam9g10-lcdc" , .data = &at91sam9g10_config, }, + { .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, }, + { .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, }, + { .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, }, + { .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_lcdfb_dt_ids); + +static const char *atmel_lcdfb_wiring_modes[] = { + [ATMEL_LCDC_WIRING_BGR] = "BRG", + [ATMEL_LCDC_WIRING_RGB] = "RGB", +}; + +const int atmel_lcdfb_get_of_wiring_modes(struct device_node *np) +{ + const char *mode; + int err, i; + + err = of_property_read_string(np, "atmel,lcd-wiring-mode", &mode); + if (err < 0) + return ATMEL_LCDC_WIRING_BGR; + + for (i = 0; i < ARRAY_SIZE(atmel_lcdfb_wiring_modes); i++) + if (!strcasecmp(mode, atmel_lcdfb_wiring_modes[i])) + return i; + + return -ENODEV; +} + +static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int on) +{ + struct atmel_lcdfb_power_ctrl_gpio *og; + + list_for_each_entry(og, &pdata->pwr_gpios, list) + gpio_set_value(og->gpio, on); +} + +static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo) +{ + struct fb_info *info = sinfo->info; + struct atmel_lcdfb_pdata *pdata = &sinfo->pdata; + struct fb_var_screeninfo *var = &info->var; + struct device *dev = &sinfo->pdev->dev; + struct device_node *np =dev->of_node; + struct device_node *display_np; + struct device_node *timings_np; + struct display_timings *timings; + enum of_gpio_flags flags; + struct atmel_lcdfb_power_ctrl_gpio *og; + bool is_gpio_power = false; + int ret = -ENOENT; + int i, gpio; + + sinfo->config = (struct atmel_lcdfb_config*) + of_match_device(atmel_lcdfb_dt_ids, dev)->data; + + display_np = of_parse_phandle(np, "display", 0); + if (!display_np) { + dev_err(dev, "failed to find display phandle\n"); + return -ENOENT; + } + + ret = of_property_read_u32(display_np, "bits-per-pixel", &var->bits_per_pixel); + if (ret < 0) { + dev_err(dev, "failed to get property bits-per-pixel\n"); + goto put_display_node; + } + + ret = of_property_read_u32(display_np, "atmel,guard-time", &pdata->guard_time); + if (ret < 0) { + dev_err(dev, "failed to get property atmel,guard-time\n"); + goto put_display_node; + } + + ret = of_property_read_u32(display_np, "atmel,lcdcon2", &pdata->default_lcdcon2); + if (ret < 0) { + dev_err(dev, "failed to get property atmel,lcdcon2\n"); + goto put_display_node; + } + + ret = of_property_read_u32(display_np, "atmel,dmacon", &pdata->default_dmacon); + if (ret < 0) { + dev_err(dev, "failed to get property bits-per-pixel\n"); + goto put_display_node; + } + + ret = -ENOMEM; + for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) { + gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio", + i, &flags); + if (gpio < 0) + continue; + + og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL); + if (!og) + goto put_display_node; + + og->gpio = gpio; + og->active_low = flags & OF_GPIO_ACTIVE_LOW; + is_gpio_power = true; + ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio"); + if (ret) { + dev_err(dev, "request gpio %d failed\n", gpio); + goto put_display_node; + } + + ret = gpio_direction_output(gpio, og->active_low); + if (ret) { + dev_err(dev, "set direction output gpio %d failed\n", gpio); + goto put_display_node; + } + } + + if (is_gpio_power) + pdata->atmel_lcdfb_power_control = atmel_lcdfb_power_control_gpio; + + ret = atmel_lcdfb_get_of_wiring_modes(display_np); + if (ret < 0) { + dev_err(dev, "invalid atmel,lcd-wiring-mode\n"); + goto put_display_node; + } + pdata->lcd_wiring_mode = ret; + + pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight"); + + timings = of_get_display_timings(display_np); + if (!timings) { + dev_err(dev, "failed to get display timings\n"); + goto put_display_node; + } + + timings_np = of_find_node_by_name(display_np, "display-timings"); + if (!timings_np) { + dev_err(dev, "failed to find display-timings node\n"); + goto put_display_node; + } + + for (i = 0; i < of_get_child_count(timings_np); i++) { + struct videomode vm; + struct fb_videomode fb_vm; + + ret = videomode_from_timings(timings, &vm, i); + if (ret < 0) + goto put_timings_node; + ret = fb_videomode_from_videomode(&vm, &fb_vm); + if (ret < 0) + goto put_timings_node; + + fb_add_videomode(&fb_vm, &info->modelist); + } + + return 0; + +put_timings_node: + of_node_put(timings_np); +put_display_node: + of_node_put(display_np); + return ret; +} +#else +static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo) +{ + return 0; +} +#endif static int __init atmel_lcdfb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fb_info *info; struct atmel_lcdfb_info *sinfo; - struct atmel_lcdfb_info *pdata_sinfo; - struct fb_videomode fbmode; + struct atmel_lcdfb_pdata *pdata = NULL; struct resource *regs = NULL; struct resource *map = NULL; + struct fb_modelist *modelist; int ret; dev_dbg(dev, "%s BEGIN\n", __func__); @@ -934,26 +1158,35 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) } sinfo = info->par; + sinfo->pdev = pdev; + sinfo->info = info; + + INIT_LIST_HEAD(&info->modelist); - if (dev->platform_data) { - pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data; - sinfo->default_bpp = pdata_sinfo->default_bpp; - sinfo->default_dmacon = pdata_sinfo->default_dmacon; - sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2; - sinfo->default_monspecs = pdata_sinfo->default_monspecs; - sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; - sinfo->guard_time = pdata_sinfo->guard_time; - sinfo->smem_len = pdata_sinfo->smem_len; - sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; - sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative; - sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; + if (pdev->dev.of_node) { + ret = atmel_lcdfb_of_init(sinfo); + if (ret) + goto free_info; + } else if (dev_get_platdata(dev)) { + struct fb_monspecs *monspecs; + int i; + + pdata = dev_get_platdata(dev); + monspecs = pdata->default_monspecs; + sinfo->pdata = *pdata; + + for (i = 0; i < monspecs->modedb_len; i++) + fb_add_videomode(&monspecs->modedb[i], &info->modelist); + + sinfo->config = atmel_lcdfb_get_config(pdev); + + info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16; + memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs)); } else { dev_err(dev, "cannot get default configuration\n"); goto free_info; } - sinfo->info = info; - sinfo->pdev = pdev; - sinfo->config = atmel_lcdfb_get_config(pdev); + if (!sinfo->config) goto free_info; @@ -962,7 +1195,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) info->pseudo_palette = sinfo->pseudo_palette; info->fbops = &atmel_lcdfb_ops; - memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs)); info->fix = atmel_lcdfb_fix; /* Enable LCDC Clocks */ @@ -978,14 +1210,11 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) } atmel_lcdfb_start_clock(sinfo); - ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb, - info->monspecs.modedb_len, info->monspecs.modedb, - sinfo->default_bpp); - if (!ret) { - dev_err(dev, "no suitable video mode found\n"); - goto stop_clk; - } + modelist = list_first_entry(&info->modelist, + struct fb_modelist, list); + fb_videomode_to_var(&info->var, &modelist->mode); + atmel_lcdfb_check_var(&info->var, info); regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { @@ -1069,18 +1298,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) goto unregister_irqs; } - /* - * This makes sure that our colour bitfield - * descriptors are correctly initialised. - */ - atmel_lcdfb_check_var(&info->var, info); - - ret = fb_set_var(info, &info->var); - if (ret) { - dev_warn(dev, "unable to set display parameters\n"); - goto free_cmap; - } - dev_set_drvdata(dev, info); /* @@ -1092,13 +1309,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) goto reset_drvdata; } - /* add selected videomode to modelist */ - fb_var_to_videomode(&fbmode, &info->var); - fb_add_videomode(&fbmode, &info->modelist); - /* Power up the LCDC screen */ - if (sinfo->atmel_lcdfb_power_control) - sinfo->atmel_lcdfb_power_control(1); + atmel_lcdfb_power_control(sinfo, 1); dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n", info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base); @@ -1107,7 +1319,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) reset_drvdata: dev_set_drvdata(dev, NULL); -free_cmap: fb_dealloc_cmap(&info->cmap); unregister_irqs: cancel_work_sync(&sinfo->task); @@ -1143,15 +1354,16 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct fb_info *info = dev_get_drvdata(dev); struct atmel_lcdfb_info *sinfo; + struct atmel_lcdfb_pdata *pdata; if (!info || !info->par) return 0; sinfo = info->par; + pdata = &sinfo->pdata; cancel_work_sync(&sinfo->task); exit_backlight(sinfo); - if (sinfo->atmel_lcdfb_power_control) - sinfo->atmel_lcdfb_power_control(0); + atmel_lcdfb_power_control(sinfo, 0); unregister_framebuffer(info); atmel_lcdfb_stop_clock(sinfo); clk_put(sinfo->lcdc_clk); @@ -1167,7 +1379,6 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) atmel_lcdfb_free_video_memory(sinfo); } - dev_set_drvdata(dev, NULL); framebuffer_release(info); return 0; @@ -1188,9 +1399,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); - if (sinfo->atmel_lcdfb_power_control) - sinfo->atmel_lcdfb_power_control(0); - + atmel_lcdfb_power_control(sinfo, 0); atmel_lcdfb_stop(sinfo); atmel_lcdfb_stop_clock(sinfo); @@ -1204,8 +1413,7 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) atmel_lcdfb_start_clock(sinfo); atmel_lcdfb_start(sinfo); - if (sinfo->atmel_lcdfb_power_control) - sinfo->atmel_lcdfb_power_control(1); + atmel_lcdfb_power_control(sinfo, 1); lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); /* Enable FIFO & DMA errors */ @@ -1228,6 +1436,7 @@ static struct platform_driver atmel_lcdfb_driver = { .driver = { .name = "atmel_lcdfb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_lcdfb_dt_ids), }, }; diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index a4dfe8cb0a0a..12ca031877d4 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -413,7 +413,6 @@ struct aty128fb_par { int blitter_may_be_busy; int fifo_slots; /* free slots in FIFO (64 max) */ - int pm_reg; int crt_on, lcd_on; struct pci_dev *pdev; struct fb_info *next; @@ -2016,7 +2015,6 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) aty128_init_engine(par); - par->pm_reg = pdev->pm_cap; par->pdev = pdev; par->asleep = 0; par->lock_blank = 0; @@ -2029,8 +2027,8 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) if (register_framebuffer(info) < 0) return 0; - printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", - info->node, info->fix.id, video_card); + fb_info(info, "%s frame buffer device on %s\n", + info->fix.id, video_card); return 1; /* success! */ } @@ -2397,7 +2395,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) u32 pmgt; struct pci_dev *pdev = par->pdev; - if (!par->pm_reg) + if (!par->pdev->pm_cap) return; /* Set the chip into the appropriate suspend mode (we use D2, diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 9b0f12c5c284..28fafbf864a5 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -1848,7 +1848,6 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) return aty_waitforvblank(par, crtc); } - break; #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) case ATYIO_CLKR: diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 1e30b2b3e79f..26d80a4486fb 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -819,11 +819,6 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in if (v.xres_virtual < v.xres) v.xres = v.xres_virtual; - if (v.xoffset < 0) - v.xoffset = 0; - if (v.yoffset < 0) - v.yoffset = 0; - if (v.xoffset > v.xres_virtual - v.xres) v.xoffset = v.xres_virtual - v.xres - 1; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index f7091ece580d..46a12f1a93c3 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -1427,6 +1427,8 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) mdelay( 15); } +#if defined(CONFIG_PM) +#if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC) static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo) { u32 tmp, tmp2; @@ -1939,9 +1941,10 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo) */ radeon_pm_m10_enable_lvds_spread_spectrum(rinfo); } +#endif #ifdef CONFIG_PPC_OF - +#ifdef CONFIG_PPC_PMAC static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo) { OUTREG(MC_CNTL, rinfo->save_regs[46]); @@ -2202,6 +2205,8 @@ static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo) radeon_pm_restore_pixel_pll(rinfo); radeon_pm_m10_enable_lvds_spread_spectrum(rinfo); } +#endif +#endif #if 0 /* Not ready yet */ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) @@ -2515,13 +2520,13 @@ static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t for (;;) { pci_read_config_word(rinfo->pdev, - rinfo->pm_reg+PCI_PM_CTRL, + rinfo->pdev->pm_cap + PCI_PM_CTRL, &pwr_cmd); - if (pwr_cmd & 2) + if (pwr_cmd & state) break; - pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state; pci_write_config_word(rinfo->pdev, - rinfo->pm_reg+PCI_PM_CTRL, + rinfo->pdev->pm_cap + PCI_PM_CTRL, pwr_cmd); msleep(500); } @@ -2532,7 +2537,7 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u32 tmp; - if (!rinfo->pm_reg) + if (!rinfo->pdev->pm_cap) return; /* Set the chip into appropriate suspend mode (we use D2, @@ -2804,9 +2809,6 @@ static void radeonfb_early_resume(void *data) void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep) { - /* Find PM registers in config space if any*/ - rinfo->pm_reg = rinfo->pdev->pm_cap; - /* Enable/Disable dynamic clocks: TODO add sysfs access */ if (rinfo->family == CHIP_FAMILY_RS480) rinfo->dynclk = -1; @@ -2830,7 +2832,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis * reason. --BenH */ if (machine_is(powermac) && rinfo->of_node) { - if (rinfo->is_mobility && rinfo->pm_reg && + if (rinfo->is_mobility && rinfo->pdev->pm_cap && rinfo->family <= CHIP_FAMILY_RV250) rinfo->pm_mode |= radeon_pm_d2; diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 7351e66c7f54..cb846044f57c 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -342,7 +342,6 @@ struct radeonfb_info { int mtrr_hdl; - int pm_reg; u32 save_regs[100]; int asleep; int lock_blank; diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 22ad85242e5b..372d4aea9d1c 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -564,7 +564,7 @@ int au1100fb_drv_remove(struct platform_device *dev) if (!dev) return -ENODEV; - fbdev = (struct au1100fb_device *) platform_get_drvdata(dev); + fbdev = platform_get_drvdata(dev); #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); @@ -636,19 +636,7 @@ static struct platform_driver au1100fb_driver = { .suspend = au1100fb_drv_suspend, .resume = au1100fb_drv_resume, }; - -static int __init au1100fb_load(void) -{ - return platform_driver_register(&au1100fb_driver); -} - -static void __exit au1100fb_unload(void) -{ - platform_driver_unregister(&au1100fb_driver); -} - -module_init(au1100fb_load); -module_exit(au1100fb_unload); +module_platform_driver(au1100fb_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 1d02897d17f2..4cfba78a1458 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1853,21 +1853,7 @@ static struct platform_driver au1200fb_driver = { .probe = au1200fb_drv_probe, .remove = au1200fb_drv_remove, }; - -/*-------------------------------------------------------------------------*/ - -static int __init au1200fb_init(void) -{ - return platform_driver_register(&au1200fb_driver); -} - -static void __exit au1200fb_cleanup(void) -{ - platform_driver_unregister(&au1200fb_driver); -} - -module_init(au1200fb_init); -module_exit(au1200fb_cleanup); +module_platform_driver(au1200fb_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 2cd63507ed74..7db5234462d0 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -196,7 +196,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, static int pm860x_backlight_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_backlight_pdata *pdata = pdev->dev.platform_data; + struct pm860x_backlight_pdata *pdata = dev_get_platdata(&pdev->dev); struct pm860x_backlight_data *data; struct backlight_device *bl; struct resource *res; @@ -243,7 +243,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; - bl = backlight_device_register(name, &pdev->dev, data, + bl = devm_backlight_device_register(&pdev->dev, name, &pdev->dev, data, &pm860x_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); @@ -256,21 +256,10 @@ static int pm860x_backlight_probe(struct platform_device *pdev) /* read current backlight */ ret = pm860x_backlight_get_brightness(bl); if (ret < 0) - goto out_brt; + return ret; backlight_update_status(bl); return 0; -out_brt: - backlight_device_unregister(bl); - return ret; -} - -static int pm860x_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - - backlight_device_unregister(bl); - return 0; } static struct platform_driver pm860x_backlight_driver = { @@ -279,7 +268,6 @@ static struct platform_driver pm860x_backlight_driver = { .owner = THIS_MODULE, }, .probe = pm860x_backlight_probe, - .remove = pm860x_backlight_remove, }; module_platform_driver(pm860x_backlight_driver); diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index d4a7a351d67c..5a3eb2ecb525 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -368,12 +368,12 @@ config BACKLIGHT_AAT2870 If you have a AnalogicTech AAT2870 say Y to enable the backlight driver. -config BACKLIGHT_LM3630 - tristate "Backlight Driver for LM3630" +config BACKLIGHT_LM3630A + tristate "Backlight Driver for LM3630A" depends on BACKLIGHT_CLASS_DEVICE && I2C select REGMAP_I2C help - This supports TI LM3630 Backlight Driver + This supports TI LM3630A Backlight Driver config BACKLIGHT_LM3639 tristate "Backlight Driver for LM3639" @@ -388,8 +388,8 @@ config BACKLIGHT_LP855X tristate "Backlight driver for TI LP855X" depends on BACKLIGHT_CLASS_DEVICE && I2C help - This supports TI LP8550, LP8551, LP8552, LP8553, LP8556 and LP8557 - backlight driver. + This supports TI LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and + LP8557 backlight driver. config BACKLIGHT_LP8788 tristate "Backlight driver for TI LP8788 MFD" diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 38e1babb1946..bb820024f346 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -37,7 +37,7 @@ obj-$(CONFIG_BACKLIGHT_GPIO) += gpio_backlight.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o -obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o +obj-$(CONFIG_BACKLIGHT_LM3630A) += lm3630a_bl.o obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c index c6fc668d6236..ee0c0a982e4e 100644 --- a/drivers/video/backlight/aat2870_bl.c +++ b/drivers/video/backlight/aat2870_bl.c @@ -127,7 +127,7 @@ static const struct backlight_ops aat2870_bl_ops = { static int aat2870_bl_probe(struct platform_device *pdev) { - struct aat2870_bl_platform_data *pdata = pdev->dev.platform_data; + struct aat2870_bl_platform_data *pdata = dev_get_platdata(&pdev->dev); struct aat2870_bl_driver_data *aat2870_bl; struct backlight_device *bd; struct backlight_properties props; @@ -158,8 +158,9 @@ static int aat2870_bl_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; - bd = backlight_device_register("aat2870-backlight", &pdev->dev, - aat2870_bl, &aat2870_bl_ops, &props); + bd = devm_backlight_device_register(&pdev->dev, "aat2870-backlight", + &pdev->dev, aat2870_bl, &aat2870_bl_ops, + &props); if (IS_ERR(bd)) { dev_err(&pdev->dev, "Failed allocate memory for backlight device\n"); @@ -194,13 +195,11 @@ static int aat2870_bl_probe(struct platform_device *pdev) ret = aat2870_bl_update_status(bd); if (ret < 0) { dev_err(&pdev->dev, "Failed to initialize\n"); - goto out_bl_dev_unregister; + return ret; } return 0; -out_bl_dev_unregister: - backlight_device_unregister(bd); out: return ret; } @@ -214,8 +213,6 @@ static int aat2870_bl_remove(struct platform_device *pdev) bd->props.brightness = 0; backlight_update_status(bd); - backlight_device_unregister(bd); - return 0; } diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index c84701b7ca6e..f37097a261a2 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -297,7 +297,7 @@ static int adp5520_bl_probe(struct platform_device *pdev) return -ENOMEM; data->master = pdev->dev.parent; - data->pdata = pdev->dev.platform_data; + data->pdata = dev_get_platdata(&pdev->dev); if (data->pdata == NULL) { dev_err(&pdev->dev, "missing platform data\n"); @@ -312,8 +312,9 @@ static int adp5520_bl_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = ADP5020_MAX_BRIGHTNESS; - bl = backlight_device_register(pdev->name, data->master, data, - &adp5520_bl_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + data->master, data, &adp5520_bl_ops, + &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -326,7 +327,7 @@ static int adp5520_bl_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to register sysfs\n"); - backlight_device_unregister(bl); + return ret; } platform_set_drvdata(pdev, bl); @@ -347,8 +348,6 @@ static int adp5520_bl_remove(struct platform_device *pdev) sysfs_remove_group(&bl->dev.kobj, &adp5520_bl_attr_group); - backlight_device_unregister(bl); - return 0; } diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 75b10f876127..9d656717d0f7 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -216,7 +216,7 @@ static int adp8860_led_setup(struct adp8860_led *led) static int adp8860_led_probe(struct i2c_client *client) { struct adp8860_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct adp8860_bl *data = i2c_get_clientdata(client); struct adp8860_led *led, *led_dat; struct led_info *cur_led; @@ -300,7 +300,7 @@ static int adp8860_led_probe(struct i2c_client *client) static int adp8860_led_remove(struct i2c_client *client) { struct adp8860_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct adp8860_bl *data = i2c_get_clientdata(client); int i; @@ -658,7 +658,7 @@ static int adp8860_probe(struct i2c_client *client, struct backlight_device *bl; struct adp8860_bl *data; struct adp8860_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct backlight_properties props; uint8_t reg_val; int ret; @@ -711,8 +711,9 @@ static int adp8860_probe(struct i2c_client *client, mutex_init(&data->lock); - bl = backlight_device_register(dev_driver_string(&client->dev), - &client->dev, data, &adp8860_bl_ops, &props); + bl = devm_backlight_device_register(&client->dev, + dev_driver_string(&client->dev), + &client->dev, data, &adp8860_bl_ops, &props); if (IS_ERR(bl)) { dev_err(&client->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -728,7 +729,7 @@ static int adp8860_probe(struct i2c_client *client, if (ret) { dev_err(&client->dev, "failed to register sysfs\n"); - goto out1; + return ret; } ret = adp8860_bl_setup(bl); @@ -751,8 +752,6 @@ out: if (data->en_ambl_sens) sysfs_remove_group(&data->bl->dev.kobj, &adp8860_bl_attr_group); -out1: - backlight_device_unregister(bl); return ret; } @@ -770,8 +769,6 @@ static int adp8860_remove(struct i2c_client *client) sysfs_remove_group(&data->bl->dev.kobj, &adp8860_bl_attr_group); - backlight_device_unregister(data->bl); - return 0; } diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 90049d7b5c60..63707205326b 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -238,7 +238,7 @@ static int adp8870_led_setup(struct adp8870_led *led) static int adp8870_led_probe(struct i2c_client *client) { struct adp8870_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct adp8870_bl *data = i2c_get_clientdata(client); struct adp8870_led *led, *led_dat; struct led_info *cur_led; @@ -325,7 +325,7 @@ static int adp8870_led_probe(struct i2c_client *client) static int adp8870_led_remove(struct i2c_client *client) { struct adp8870_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); struct adp8870_bl *data = i2c_get_clientdata(client); int i; @@ -848,7 +848,7 @@ static int adp8870_probe(struct i2c_client *client, struct backlight_device *bl; struct adp8870_bl *data; struct adp8870_backlight_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(&client->dev); uint8_t reg_val; int ret; @@ -888,8 +888,9 @@ static int adp8870_probe(struct i2c_client *client, memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; - bl = backlight_device_register(dev_driver_string(&client->dev), - &client->dev, data, &adp8870_bl_ops, &props); + bl = devm_backlight_device_register(&client->dev, + dev_driver_string(&client->dev), + &client->dev, data, &adp8870_bl_ops, &props); if (IS_ERR(bl)) { dev_err(&client->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -902,7 +903,7 @@ static int adp8870_probe(struct i2c_client *client, &adp8870_bl_attr_group); if (ret) { dev_err(&client->dev, "failed to register sysfs\n"); - goto out1; + return ret; } } @@ -925,8 +926,6 @@ out: if (data->pdata->en_ambl_sens) sysfs_remove_group(&data->bl->dev.kobj, &adp8870_bl_attr_group); -out1: - backlight_device_unregister(bl); return ret; } @@ -944,8 +943,6 @@ static int adp8870_remove(struct i2c_client *client) sysfs_remove_group(&data->bl->dev.kobj, &adp8870_bl_attr_group); - backlight_device_unregister(data->bl); - return 0; } diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 319fef6cb422..d8952c4aa689 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -471,14 +471,14 @@ static int ams369fg06_probe(struct spi_device *spi) lcd->spi = spi; lcd->dev = &spi->dev; - lcd->lcd_pd = spi->dev.platform_data; + lcd->lcd_pd = dev_get_platdata(&spi->dev); if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL\n"); return -EINVAL; } - ld = lcd_device_register("ams369fg06", &spi->dev, lcd, - &ams369fg06_lcd_ops); + ld = devm_lcd_device_register(&spi->dev, "ams369fg06", &spi->dev, lcd, + &ams369fg06_lcd_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -488,12 +488,11 @@ static int ams369fg06_probe(struct spi_device *spi) props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; - bd = backlight_device_register("ams369fg06-bl", &spi->dev, lcd, - &ams369fg06_backlight_ops, &props); - if (IS_ERR(bd)) { - ret = PTR_ERR(bd); - goto out_lcd_unregister; - } + bd = devm_backlight_device_register(&spi->dev, "ams369fg06-bl", + &spi->dev, lcd, + &ams369fg06_backlight_ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); bd->props.brightness = DEFAULT_BRIGHTNESS; lcd->bd = bd; @@ -516,10 +515,6 @@ static int ams369fg06_probe(struct spi_device *spi) dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); return 0; - -out_lcd_unregister: - lcd_device_unregister(ld); - return ret; } static int ams369fg06_remove(struct spi_device *spi) @@ -527,9 +522,6 @@ static int ams369fg06_remove(struct spi_device *spi) struct ams369fg06 *lcd = spi_get_drvdata(spi); ams369fg06_power(lcd, FB_BLANK_POWERDOWN); - backlight_device_unregister(lcd->bd); - lcd_device_unregister(lcd->ld); - return 0; } diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c index 123887cd76bd..bb1fc45b7549 100644 --- a/drivers/video/backlight/as3711_bl.c +++ b/drivers/video/backlight/as3711_bl.c @@ -240,7 +240,8 @@ static int as3711_bl_register(struct platform_device *pdev, /* max tuning I = 31uA for voltage- and 38250uA for current-feedback */ props.max_brightness = max_brightness; - bl = backlight_device_register(su->type == AS3711_BL_SU1 ? + bl = devm_backlight_device_register(&pdev->dev, + su->type == AS3711_BL_SU1 ? "as3711-su1" : "as3711-su2", &pdev->dev, su, &as3711_bl_ops, &props); @@ -432,8 +433,7 @@ static int as3711_backlight_probe(struct platform_device *pdev) case AS3711_SU2_LX_SD4: break; default: - ret = -EINVAL; - goto esu2; + return -EINVAL; } switch (pdata->su2_feedback) { @@ -447,8 +447,7 @@ static int as3711_backlight_probe(struct platform_device *pdev) max_brightness = min(pdata->su2_max_uA / 150, 255); break; default: - ret = -EINVAL; - goto esu2; + return -EINVAL; } ret = as3711_bl_init_su2(supply); @@ -457,26 +456,12 @@ static int as3711_backlight_probe(struct platform_device *pdev) ret = as3711_bl_register(pdev, max_brightness, su); if (ret < 0) - goto esu2; + return ret; } platform_set_drvdata(pdev, supply); return 0; - -esu2: - backlight_device_unregister(supply->su1.bl); - return ret; -} - -static int as3711_backlight_remove(struct platform_device *pdev) -{ - struct as3711_bl_supply *supply = platform_get_drvdata(pdev); - - backlight_device_unregister(supply->su1.bl); - backlight_device_unregister(supply->su2.bl); - - return 0; } static struct platform_driver as3711_backlight_driver = { @@ -485,7 +470,6 @@ static struct platform_driver as3711_backlight_driver = { .owner = THIS_MODULE, }, .probe = as3711_backlight_probe, - .remove = as3711_backlight_remove, }; module_platform_driver(as3711_backlight_driver); diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index 0393d827dd44..261b1a4ec3d8 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/fb.h> -#include <linux/clk.h> #include <linux/gpio.h> #include <linux/backlight.h> #include <linux/atmel_pwm.h> @@ -27,6 +26,14 @@ struct atmel_pwm_bl { int gpio_on; }; +static void atmel_pwm_bl_set_gpio_on(struct atmel_pwm_bl *pwmbl, int on) +{ + if (!gpio_is_valid(pwmbl->gpio_on)) + return; + + gpio_set_value(pwmbl->gpio_on, on ^ pwmbl->pdata->on_active_low); +} + static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) { struct atmel_pwm_bl *pwmbl = bl_get_data(bd); @@ -49,19 +56,13 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) pwm_duty = pwmbl->pdata->pwm_duty_min; if (!intensity) { - if (pwmbl->gpio_on != -1) { - gpio_set_value(pwmbl->gpio_on, - 0 ^ pwmbl->pdata->on_active_low); - } + atmel_pwm_bl_set_gpio_on(pwmbl, 0); pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty); pwm_channel_disable(&pwmbl->pwmc); } else { pwm_channel_enable(&pwmbl->pwmc); pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty); - if (pwmbl->gpio_on != -1) { - gpio_set_value(pwmbl->gpio_on, - 1 ^ pwmbl->pdata->on_active_low); - } + atmel_pwm_bl_set_gpio_on(pwmbl, 1); } return 0; @@ -70,17 +71,16 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) { struct atmel_pwm_bl *pwmbl = bl_get_data(bd); - u8 intensity; + u32 cdty; + u32 intensity; - if (pwmbl->pdata->pwm_active_low) { - intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) - - pwmbl->pdata->pwm_duty_min; - } else { - intensity = pwmbl->pdata->pwm_duty_max - - pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY); - } + cdty = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY); + if (pwmbl->pdata->pwm_active_low) + intensity = cdty - pwmbl->pdata->pwm_duty_min; + else + intensity = pwmbl->pdata->pwm_duty_max - cdty; - return intensity; + return intensity & 0xffff; } static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) @@ -118,52 +118,46 @@ static const struct backlight_ops atmel_pwm_bl_ops = { .update_status = atmel_pwm_bl_set_intensity, }; -static int __init atmel_pwm_bl_probe(struct platform_device *pdev) +static int atmel_pwm_bl_probe(struct platform_device *pdev) { struct backlight_properties props; const struct atmel_pwm_bl_platform_data *pdata; struct backlight_device *bldev; struct atmel_pwm_bl *pwmbl; + unsigned long flags; int retval; + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) + return -ENODEV; + + if (pdata->pwm_compare_max < pdata->pwm_duty_max || + pdata->pwm_duty_min > pdata->pwm_duty_max || + pdata->pwm_frequency == 0) + return -EINVAL; + pwmbl = devm_kzalloc(&pdev->dev, sizeof(struct atmel_pwm_bl), GFP_KERNEL); if (!pwmbl) return -ENOMEM; pwmbl->pdev = pdev; - - pdata = pdev->dev.platform_data; - if (!pdata) { - retval = -ENODEV; - goto err_free_mem; - } - - if (pdata->pwm_compare_max < pdata->pwm_duty_max || - pdata->pwm_duty_min > pdata->pwm_duty_max || - pdata->pwm_frequency == 0) { - retval = -EINVAL; - goto err_free_mem; - } - pwmbl->pdata = pdata; pwmbl->gpio_on = pdata->gpio_on; retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc); if (retval) - goto err_free_mem; - - if (pwmbl->gpio_on != -1) { - retval = devm_gpio_request(&pdev->dev, pwmbl->gpio_on, - "gpio_atmel_pwm_bl"); - if (retval) { - pwmbl->gpio_on = -1; - goto err_free_pwm; - } + return retval; + if (gpio_is_valid(pwmbl->gpio_on)) { /* Turn display off by default. */ - retval = gpio_direction_output(pwmbl->gpio_on, - 0 ^ pdata->on_active_low); + if (pdata->on_active_low) + flags = GPIOF_OUT_INIT_HIGH; + else + flags = GPIOF_OUT_INIT_LOW; + + retval = devm_gpio_request_one(&pdev->dev, pwmbl->gpio_on, + flags, "gpio_atmel_pwm_bl"); if (retval) goto err_free_pwm; } @@ -171,8 +165,9 @@ static int __init atmel_pwm_bl_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min; - bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl, - &atmel_pwm_bl_ops, &props); + bldev = devm_backlight_device_register(&pdev->dev, "atmel-pwm-bl", + &pdev->dev, pwmbl, &atmel_pwm_bl_ops, + &props); if (IS_ERR(bldev)) { retval = PTR_ERR(bldev); goto err_free_pwm; @@ -188,29 +183,25 @@ static int __init atmel_pwm_bl_probe(struct platform_device *pdev) retval = atmel_pwm_bl_init_pwm(pwmbl); if (retval) - goto err_free_bl_dev; + goto err_free_pwm; atmel_pwm_bl_set_intensity(bldev); return 0; -err_free_bl_dev: - backlight_device_unregister(bldev); err_free_pwm: pwm_channel_free(&pwmbl->pwmc); -err_free_mem: + return retval; } -static int __exit atmel_pwm_bl_remove(struct platform_device *pdev) +static int atmel_pwm_bl_remove(struct platform_device *pdev) { struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev); - if (pwmbl->gpio_on != -1) - gpio_set_value(pwmbl->gpio_on, 0); + atmel_pwm_bl_set_gpio_on(pwmbl, 0); pwm_channel_disable(&pwmbl->pwmc); pwm_channel_free(&pwmbl->pwmc); - backlight_device_unregister(pwmbl->bldev); return 0; } @@ -220,11 +211,13 @@ static struct platform_driver atmel_pwm_bl_driver = { .name = "atmel-pwm-bl", }, /* REVISIT add suspend() and resume() */ - .remove = __exit_p(atmel_pwm_bl_remove), + .probe = atmel_pwm_bl_probe, + .remove = atmel_pwm_bl_remove, }; -module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe); +module_platform_driver(atmel_pwm_bl_driver); MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); MODULE_DESCRIPTION("Atmel PWM backlight driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:atmel-pwm-bl"); diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 94a403a9717a..5d05555fe841 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -21,6 +21,9 @@ #include <asm/backlight.h> #endif +static struct list_head backlight_dev_list; +static struct mutex backlight_dev_list_mutex; + static const char *const backlight_types[] = { [BACKLIGHT_RAW] = "raw", [BACKLIGHT_PLATFORM] = "platform", @@ -349,10 +352,32 @@ struct backlight_device *backlight_device_register(const char *name, mutex_unlock(&pmac_backlight_mutex); #endif + mutex_lock(&backlight_dev_list_mutex); + list_add(&new_bd->entry, &backlight_dev_list); + mutex_unlock(&backlight_dev_list_mutex); + return new_bd; } EXPORT_SYMBOL(backlight_device_register); +bool backlight_device_registered(enum backlight_type type) +{ + bool found = false; + struct backlight_device *bd; + + mutex_lock(&backlight_dev_list_mutex); + list_for_each_entry(bd, &backlight_dev_list, entry) { + if (bd->props.type == type) { + found = true; + break; + } + } + mutex_unlock(&backlight_dev_list_mutex); + + return found; +} +EXPORT_SYMBOL(backlight_device_registered); + /** * backlight_device_unregister - unregisters a backlight device object. * @bd: the backlight device object to be unregistered and freed. @@ -364,6 +389,10 @@ void backlight_device_unregister(struct backlight_device *bd) if (!bd) return; + mutex_lock(&backlight_dev_list_mutex); + list_del(&bd->entry); + mutex_unlock(&backlight_dev_list_mutex); + #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); if (pmac_backlight == bd) @@ -499,6 +528,8 @@ static int __init backlight_class_init(void) backlight_class->dev_groups = bl_device_groups; backlight_class->pm = &backlight_class_dev_pm_ops; + INIT_LIST_HEAD(&backlight_dev_list); + mutex_init(&backlight_dev_list_mutex); return 0; } diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c index 15e3294b29fe..16dd9bc625bd 100644 --- a/drivers/video/backlight/bd6107.c +++ b/drivers/video/backlight/bd6107.c @@ -128,7 +128,7 @@ static const struct backlight_ops bd6107_backlight_ops = { static int bd6107_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct bd6107_platform_data *pdata = client->dev.platform_data; + struct bd6107_platform_data *pdata = dev_get_platdata(&client->dev); struct backlight_device *backlight; struct backlight_properties props; struct bd6107 *bd; @@ -166,7 +166,8 @@ static int bd6107_probe(struct i2c_client *client, props.brightness = clamp_t(unsigned int, pdata->def_value, 0, props.max_brightness); - backlight = backlight_device_register(dev_name(&client->dev), + backlight = devm_backlight_device_register(&client->dev, + dev_name(&client->dev), &bd->client->dev, bd, &bd6107_backlight_ops, &props); if (IS_ERR(backlight)) { @@ -186,7 +187,6 @@ static int bd6107_remove(struct i2c_client *client) backlight->props.brightness = 0; backlight_update_status(backlight); - backlight_device_unregister(backlight); return 0; } diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index c97867a717a7..db8db5fa6583 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -533,7 +533,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, static int corgi_lcd_probe(struct spi_device *spi) { struct backlight_properties props; - struct corgi_lcd_platform_data *pdata = spi->dev.platform_data; + struct corgi_lcd_platform_data *pdata = dev_get_platdata(&spi->dev); struct corgi_lcd *lcd; int ret = 0; @@ -550,8 +550,8 @@ static int corgi_lcd_probe(struct spi_device *spi) lcd->spi_dev = spi; - lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev, - lcd, &corgi_lcd_ops); + lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "corgi_lcd", + &spi->dev, lcd, &corgi_lcd_ops); if (IS_ERR(lcd->lcd_dev)) return PTR_ERR(lcd->lcd_dev); @@ -561,18 +561,18 @@ static int corgi_lcd_probe(struct spi_device *spi) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = pdata->max_intensity; - lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd, - &corgi_bl_ops, &props); - if (IS_ERR(lcd->bl_dev)) { - ret = PTR_ERR(lcd->bl_dev); - goto err_unregister_lcd; - } + lcd->bl_dev = devm_backlight_device_register(&spi->dev, "corgi_bl", + &spi->dev, lcd, &corgi_bl_ops, + &props); + if (IS_ERR(lcd->bl_dev)) + return PTR_ERR(lcd->bl_dev); + lcd->bl_dev->props.brightness = pdata->default_intensity; lcd->bl_dev->props.power = FB_BLANK_UNBLANK; ret = setup_gpio_backlight(lcd, pdata); if (ret) - goto err_unregister_bl; + return ret; lcd->kick_battery = pdata->kick_battery; @@ -583,12 +583,6 @@ static int corgi_lcd_probe(struct spi_device *spi) lcd->limit_mask = pdata->limit_mask; the_corgi_lcd = lcd; return 0; - -err_unregister_bl: - backlight_device_unregister(lcd->bl_dev); -err_unregister_lcd: - lcd_device_unregister(lcd->lcd_dev); - return ret; } static int corgi_lcd_remove(struct spi_device *spi) @@ -598,11 +592,7 @@ static int corgi_lcd_remove(struct spi_device *spi) lcd->bl_dev->props.power = FB_BLANK_UNBLANK; lcd->bl_dev->props.brightness = 0; backlight_update_status(lcd->bl_dev); - backlight_device_unregister(lcd->bl_dev); - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); - lcd_device_unregister(lcd->lcd_dev); - return 0; } diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c index 37bae801e23b..f3fed9ef745f 100644 --- a/drivers/video/backlight/cr_bllcd.c +++ b/drivers/video/backlight/cr_bllcd.c @@ -195,16 +195,17 @@ static int cr_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; - bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL, - &cr_backlight_ops, &props); + bdp = devm_backlight_device_register(&pdev->dev, "cr-backlight", + &pdev->dev, NULL, &cr_backlight_ops, + &props); if (IS_ERR(bdp)) { pci_dev_put(lpc_dev); return PTR_ERR(bdp); } - ldp = lcd_device_register("cr-lcd", &pdev->dev, NULL, &cr_lcd_ops); + ldp = devm_lcd_device_register(&pdev->dev, "cr-lcd", &pdev->dev, NULL, + &cr_lcd_ops); if (IS_ERR(ldp)) { - backlight_device_unregister(bdp); pci_dev_put(lpc_dev); return PTR_ERR(ldp); } @@ -215,8 +216,6 @@ static int cr_backlight_probe(struct platform_device *pdev) crp = devm_kzalloc(&pdev->dev, sizeof(*crp), GFP_KERNEL); if (!crp) { - lcd_device_unregister(ldp); - backlight_device_unregister(bdp); pci_dev_put(lpc_dev); return -ENOMEM; } @@ -241,8 +240,6 @@ static int cr_backlight_remove(struct platform_device *pdev) crp->cr_backlight_device->props.max_brightness = 0; cr_backlight_set_intensity(crp->cr_backlight_device); cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN); - backlight_device_unregister(crp->cr_backlight_device); - lcd_device_unregister(crp->cr_lcd_device); pci_dev_put(lpc_dev); return 0; diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 67cadd30e273..12c5d840c590 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -109,7 +109,7 @@ static const struct backlight_ops da903x_backlight_ops = { static int da903x_backlight_probe(struct platform_device *pdev) { - struct da9034_backlight_pdata *pdata = pdev->dev.platform_data; + struct da9034_backlight_pdata *pdata = dev_get_platdata(&pdev->dev); struct da903x_backlight_data *data; struct backlight_device *bl; struct backlight_properties props; @@ -144,8 +144,9 @@ static int da903x_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.max_brightness = max_brightness; - bl = backlight_device_register(pdev->name, data->da903x_dev, data, - &da903x_backlight_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + data->da903x_dev, data, + &da903x_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -158,21 +159,12 @@ static int da903x_backlight_probe(struct platform_device *pdev) return 0; } -static int da903x_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - - backlight_device_unregister(bl); - return 0; -} - static struct platform_driver da903x_backlight_driver = { .driver = { .name = "da903x-backlight", .owner = THIS_MODULE, }, .probe = da903x_backlight_probe, - .remove = da903x_backlight_remove, }; module_platform_driver(da903x_backlight_driver); diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index 842da5a3ac4f..20d55becaa74 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c @@ -125,8 +125,9 @@ static int da9052_backlight_probe(struct platform_device *pdev) props.type = BACKLIGHT_RAW; props.max_brightness = DA9052_MAX_BRIGHTNESS; - bl = backlight_device_register(pdev->name, wleds->da9052->dev, wleds, - &da9052_backlight_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + wleds->da9052->dev, wleds, + &da9052_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "Failed to register backlight\n"); return PTR_ERR(bl); @@ -147,7 +148,6 @@ static int da9052_backlight_remove(struct platform_device *pdev) wleds->brightness = 0; wleds->state = DA9052_WLEDS_OFF; da9052_adjust_wled_brightness(wleds); - backlight_device_unregister(bl); return 0; } diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index 018368ba4124..0d1f633c6480 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c @@ -92,8 +92,8 @@ static int ep93xxbl_probe(struct platform_device *dev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = EP93XX_MAX_BRIGHT; - bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl, - &ep93xxbl_ops, &props); + bl = devm_backlight_device_register(&dev->dev, dev->name, &dev->dev, + ep93xxbl, &ep93xxbl_ops, &props); if (IS_ERR(bl)) return PTR_ERR(bl); @@ -106,14 +106,6 @@ static int ep93xxbl_probe(struct platform_device *dev) return 0; } -static int ep93xxbl_remove(struct platform_device *dev) -{ - struct backlight_device *bl = platform_get_drvdata(dev); - - backlight_device_unregister(bl); - return 0; -} - #ifdef CONFIG_PM_SLEEP static int ep93xxbl_suspend(struct device *dev) { @@ -140,7 +132,6 @@ static struct platform_driver ep93xxbl_driver = { .pm = &ep93xxbl_pm_ops, }, .probe = ep93xxbl_probe, - .remove = ep93xxbl_remove, }; module_platform_driver(ep93xxbl_driver); diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 19e393b41438..5d8d65200db7 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c @@ -79,7 +79,7 @@ static const struct backlight_ops genericbl_ops = { static int genericbl_probe(struct platform_device *pdev) { struct backlight_properties props; - struct generic_bl_info *machinfo = pdev->dev.platform_data; + struct generic_bl_info *machinfo = dev_get_platdata(&pdev->dev); const char *name = "generic-bl"; struct backlight_device *bd; @@ -93,8 +93,8 @@ static int genericbl_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = machinfo->max_intensity; - bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, - &props); + bd = devm_backlight_device_register(&pdev->dev, name, &pdev->dev, + NULL, &genericbl_ops, &props); if (IS_ERR(bd)) return PTR_ERR(bd); @@ -118,8 +118,6 @@ static int genericbl_remove(struct platform_device *pdev) bd->props.brightness = 0; backlight_update_status(bd); - backlight_device_unregister(bd); - dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n"); return 0; } diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index 5fa217f9f445..81fb12770c2a 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -62,7 +62,8 @@ static const struct backlight_ops gpio_backlight_ops = { static int gpio_backlight_probe(struct platform_device *pdev) { - struct gpio_backlight_platform_data *pdata = pdev->dev.platform_data; + struct gpio_backlight_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct backlight_properties props; struct backlight_device *bl; struct gpio_backlight *gbl; @@ -94,8 +95,9 @@ static int gpio_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.max_brightness = 1; - bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, gbl, - &gpio_backlight_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), + &pdev->dev, gbl, &gpio_backlight_ops, + &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -108,21 +110,12 @@ static int gpio_backlight_probe(struct platform_device *pdev) return 0; } -static int gpio_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - - backlight_device_unregister(bl); - return 0; -} - static struct platform_driver gpio_backlight_driver = { .driver = { .name = "gpio-backlight", .owner = THIS_MODULE, }, .probe = gpio_backlight_probe, - .remove = gpio_backlight_remove, }; module_platform_driver(gpio_backlight_driver); diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c index c7af8c45ab8a..985e854e244b 100644 --- a/drivers/video/backlight/hx8357.c +++ b/drivers/video/backlight/hx8357.c @@ -648,7 +648,8 @@ static int hx8357_probe(struct spi_device *spi) lcd->use_im_pins = 0; } - lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops); + lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd, + &hx8357_ops); if (IS_ERR(lcdev)) { ret = PTR_ERR(lcdev); return ret; @@ -660,32 +661,19 @@ static int hx8357_probe(struct spi_device *spi) ret = ((int (*)(struct lcd_device *))match->data)(lcdev); if (ret) { dev_err(&spi->dev, "Couldn't initialize panel\n"); - goto init_error; + return ret; } dev_info(&spi->dev, "Panel probed\n"); return 0; - -init_error: - lcd_device_unregister(lcdev); - return ret; -} - -static int hx8357_remove(struct spi_device *spi) -{ - struct lcd_device *lcdev = spi_get_drvdata(spi); - - lcd_device_unregister(lcdev); - return 0; } static struct spi_driver hx8357_driver = { .probe = hx8357_probe, - .remove = hx8357_remove, .driver = { .name = "hx8357", - .of_match_table = of_match_ptr(hx8357_dt_ids), + .of_match_table = hx8357_dt_ids, }, }; diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index d9f65c2d9b01..73464e4b4c74 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -513,8 +513,8 @@ static int ili922x_probe(struct spi_device *spi) ili->power = FB_BLANK_POWERDOWN; - lcd = lcd_device_register("ili922xlcd", &spi->dev, ili, - &ili922x_ops); + lcd = devm_lcd_device_register(&spi->dev, "ili922xlcd", &spi->dev, ili, + &ili922x_ops); if (IS_ERR(lcd)) { dev_err(&spi->dev, "cannot register LCD\n"); return PTR_ERR(lcd); @@ -530,10 +530,7 @@ static int ili922x_probe(struct spi_device *spi) static int ili922x_remove(struct spi_device *spi) { - struct ili922x *ili = spi_get_drvdata(spi); - ili922x_poweroff(spi); - lcd_device_unregister(ili->ld); return 0; } diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index f8be90c5dedc..e2b8b40a9bd9 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c @@ -198,7 +198,7 @@ static void ili9320_setup_spi(struct ili9320 *ili, int ili9320_probe_spi(struct spi_device *spi, struct ili9320_client *client) { - struct ili9320_platdata *cfg = spi->dev.platform_data; + struct ili9320_platdata *cfg = dev_get_platdata(&spi->dev); struct device *dev = &spi->dev; struct ili9320 *ili; struct lcd_device *lcd; @@ -235,7 +235,8 @@ int ili9320_probe_spi(struct spi_device *spi, ili9320_setup_spi(ili, spi); - lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops); + lcd = devm_lcd_device_register(&spi->dev, "ili9320", dev, ili, + &ili9320_ops); if (IS_ERR(lcd)) { dev_err(dev, "failed to register lcd device\n"); return PTR_ERR(lcd); @@ -248,24 +249,16 @@ int ili9320_probe_spi(struct spi_device *spi, ret = ili9320_power(ili, FB_BLANK_UNBLANK); if (ret != 0) { dev_err(dev, "failed to set lcd power state\n"); - goto err_unregister; + return ret; } return 0; - - err_unregister: - lcd_device_unregister(lcd); - - return ret; } EXPORT_SYMBOL_GPL(ili9320_probe_spi); int ili9320_remove(struct ili9320 *ili) { ili9320_power(ili, FB_BLANK_POWERDOWN); - - lcd_device_unregister(ili->lcd); - return 0; } EXPORT_SYMBOL_GPL(ili9320_remove); diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index bca6ccc74dfb..7592cc25c963 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -141,7 +141,7 @@ static const struct backlight_ops kb3886bl_ops = { static int kb3886bl_probe(struct platform_device *pdev) { struct backlight_properties props; - struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data; + struct kb3886bl_machinfo *machinfo = dev_get_platdata(&pdev->dev); bl_machinfo = machinfo; if (!machinfo->limit_mask) @@ -150,10 +150,10 @@ static int kb3886bl_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = machinfo->max_intensity; - kb3886_backlight_device = backlight_device_register("kb3886-bl", - &pdev->dev, NULL, - &kb3886bl_ops, - &props); + kb3886_backlight_device = devm_backlight_device_register(&pdev->dev, + "kb3886-bl", &pdev->dev, + NULL, &kb3886bl_ops, + &props); if (IS_ERR(kb3886_backlight_device)) return PTR_ERR(kb3886_backlight_device); @@ -166,18 +166,8 @@ static int kb3886bl_probe(struct platform_device *pdev) return 0; } -static int kb3886bl_remove(struct platform_device *pdev) -{ - struct backlight_device *bd = platform_get_drvdata(pdev); - - backlight_device_unregister(bd); - - return 0; -} - static struct platform_driver kb3886bl_driver = { .probe = kb3886bl_probe, - .remove = kb3886bl_remove, .driver = { .name = "kb3886-bl", .pm = &kb3886bl_pm_ops, diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index a35a38c709cf..b5fc13bc24e7 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -48,7 +48,7 @@ static void l4f00242t03_reset(unsigned int gpio) static void l4f00242t03_lcd_init(struct spi_device *spi) { - struct l4f00242t03_pdata *pdata = spi->dev.platform_data; + struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev); struct l4f00242t03_priv *priv = spi_get_drvdata(spi); const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; int ret; @@ -88,7 +88,7 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) static void l4f00242t03_lcd_powerdown(struct spi_device *spi) { - struct l4f00242t03_pdata *pdata = spi->dev.platform_data; + struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev); struct l4f00242t03_priv *priv = spi_get_drvdata(spi); dev_dbg(&spi->dev, "Powering down LCD\n"); @@ -171,7 +171,7 @@ static struct lcd_ops l4f_ops = { static int l4f00242t03_probe(struct spi_device *spi) { struct l4f00242t03_priv *priv; - struct l4f00242t03_pdata *pdata = spi->dev.platform_data; + struct l4f00242t03_pdata *pdata = dev_get_platdata(&spi->dev); int ret; if (pdata == NULL) { @@ -244,7 +244,6 @@ static int l4f00242t03_remove(struct spi_device *spi) l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); lcd_device_unregister(priv->ld); - spi_set_drvdata(spi, NULL); return 0; } diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index 1e0a3093ce50..506a6c236039 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c @@ -702,7 +702,7 @@ static int ld9040_probe(struct spi_device *spi) lcd->spi = spi; lcd->dev = &spi->dev; - lcd->lcd_pd = spi->dev.platform_data; + lcd->lcd_pd = dev_get_platdata(&spi->dev); if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL.\n"); return -EINVAL; @@ -716,7 +716,8 @@ static int ld9040_probe(struct spi_device *spi) return ret; } - ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); + ld = devm_lcd_device_register(&spi->dev, "ld9040", &spi->dev, lcd, + &ld9040_lcd_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -726,12 +727,10 @@ static int ld9040_probe(struct spi_device *spi) props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; - bd = backlight_device_register("ld9040-bl", &spi->dev, - lcd, &ld9040_backlight_ops, &props); - if (IS_ERR(bd)) { - ret = PTR_ERR(bd); - goto out_unregister_lcd; - } + bd = devm_backlight_device_register(&spi->dev, "ld9040-bl", &spi->dev, + lcd, &ld9040_backlight_ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); bd->props.brightness = MAX_BRIGHTNESS; lcd->bd = bd; @@ -757,11 +756,6 @@ static int ld9040_probe(struct spi_device *spi) dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); return 0; - -out_unregister_lcd: - lcd_device_unregister(lcd->ld); - - return ret; } static int ld9040_remove(struct spi_device *spi) @@ -769,9 +763,6 @@ static int ld9040_remove(struct spi_device *spi) struct ld9040 *lcd = spi_get_drvdata(spi); ld9040_power(lcd, FB_BLANK_POWERDOWN); - backlight_device_unregister(lcd->bd); - lcd_device_unregister(lcd->ld); - return 0; } diff --git a/drivers/video/backlight/ld9040_gamma.h b/drivers/video/backlight/ld9040_gamma.h index 038d9c86ec03..c5e586d97385 100644 --- a/drivers/video/backlight/ld9040_gamma.h +++ b/drivers/video/backlight/ld9040_gamma.h @@ -169,7 +169,9 @@ static const unsigned int ld9040_22_50[] = { struct ld9040_gamma { unsigned int *gamma_22_table[MAX_GAMMA_LEVEL]; -} gamma_table = { +}; + +static struct ld9040_gamma gamma_table = { .gamma_22_table[0] = (unsigned int *)&ld9040_22_50, .gamma_22_table[1] = (unsigned int *)&ld9040_22_70, .gamma_22_table[2] = (unsigned int *)&ld9040_22_80, diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index 1d1dbfb789e3..187d1c283c1d 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -284,7 +284,7 @@ static int lm3533_bl_probe(struct platform_device *pdev) if (!lm3533) return -EINVAL; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; @@ -313,8 +313,9 @@ static int lm3533_bl_probe(struct platform_device *pdev) props.type = BACKLIGHT_RAW; props.max_brightness = LM3533_BL_MAX_BRIGHTNESS; props.brightness = pdata->default_brightness; - bd = backlight_device_register(pdata->name, pdev->dev.parent, bl, - &lm3533_bl_ops, &props); + bd = devm_backlight_device_register(&pdev->dev, pdata->name, + pdev->dev.parent, bl, &lm3533_bl_ops, + &props); if (IS_ERR(bd)) { dev_err(&pdev->dev, "failed to register backlight device\n"); return PTR_ERR(bd); @@ -328,7 +329,7 @@ static int lm3533_bl_probe(struct platform_device *pdev) ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group); if (ret < 0) { dev_err(&pdev->dev, "failed to create sysfs attributes\n"); - goto err_unregister; + return ret; } backlight_update_status(bd); @@ -345,8 +346,6 @@ static int lm3533_bl_probe(struct platform_device *pdev) err_sysfs_remove: sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group); -err_unregister: - backlight_device_unregister(bd); return ret; } @@ -363,7 +362,6 @@ static int lm3533_bl_remove(struct platform_device *pdev) lm3533_ctrlbank_disable(&bl->cb); sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group); - backlight_device_unregister(bd); return 0; } diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c deleted file mode 100644 index 76a62e978fc3..000000000000 --- a/drivers/video/backlight/lm3630_bl.c +++ /dev/null @@ -1,475 +0,0 @@ -/* -* Simple driver for Texas Instruments LM3630 Backlight driver chip -* Copyright (C) 2012 Texas Instruments -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -*/ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/backlight.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/uaccess.h> -#include <linux/interrupt.h> -#include <linux/regmap.h> -#include <linux/platform_data/lm3630_bl.h> - -#define REG_CTRL 0x00 -#define REG_CONFIG 0x01 -#define REG_BRT_A 0x03 -#define REG_BRT_B 0x04 -#define REG_INT_STATUS 0x09 -#define REG_INT_EN 0x0A -#define REG_FAULT 0x0B -#define REG_PWM_OUTLOW 0x12 -#define REG_PWM_OUTHIGH 0x13 -#define REG_MAX 0x1F - -#define INT_DEBOUNCE_MSEC 10 - -enum lm3630_leds { - BLED_ALL = 0, - BLED_1, - BLED_2 -}; - -static const char * const bled_name[] = { - [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ - [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ - [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ -}; - -struct lm3630_chip_data { - struct device *dev; - struct delayed_work work; - int irq; - struct workqueue_struct *irqthread; - struct lm3630_platform_data *pdata; - struct backlight_device *bled1; - struct backlight_device *bled2; - struct regmap *regmap; -}; - -/* initialize chip */ -static int lm3630_chip_init(struct lm3630_chip_data *pchip) -{ - int ret; - unsigned int reg_val; - struct lm3630_platform_data *pdata = pchip->pdata; - - /*pwm control */ - reg_val = ((pdata->pwm_active & 0x01) << 2) | (pdata->pwm_ctrl & 0x03); - ret = regmap_update_bits(pchip->regmap, REG_CONFIG, 0x07, reg_val); - if (ret < 0) - goto out; - - /* bank control */ - reg_val = ((pdata->bank_b_ctrl & 0x01) << 1) | - (pdata->bank_a_ctrl & 0x07); - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x07, reg_val); - if (ret < 0) - goto out; - - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - - /* set initial brightness */ - if (pdata->bank_a_ctrl != BANK_A_CTRL_DISABLE) { - ret = regmap_write(pchip->regmap, - REG_BRT_A, pdata->init_brt_led1); - if (ret < 0) - goto out; - } - - if (pdata->bank_b_ctrl != BANK_B_CTRL_DISABLE) { - ret = regmap_write(pchip->regmap, - REG_BRT_B, pdata->init_brt_led2); - if (ret < 0) - goto out; - } - return ret; - -out: - dev_err(pchip->dev, "i2c failed to access register\n"); - return ret; -} - -/* interrupt handling */ -static void lm3630_delayed_func(struct work_struct *work) -{ - int ret; - unsigned int reg_val; - struct lm3630_chip_data *pchip; - - pchip = container_of(work, struct lm3630_chip_data, work.work); - - ret = regmap_read(pchip->regmap, REG_INT_STATUS, ®_val); - if (ret < 0) { - dev_err(pchip->dev, - "i2c failed to access REG_INT_STATUS Register\n"); - return; - } - - dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", reg_val); -} - -static irqreturn_t lm3630_isr_func(int irq, void *chip) -{ - int ret; - struct lm3630_chip_data *pchip = chip; - unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC); - - queue_delayed_work(pchip->irqthread, &pchip->work, delay); - - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - - return IRQ_HANDLED; -out: - dev_err(pchip->dev, "i2c failed to access register\n"); - return IRQ_HANDLED; -} - -static int lm3630_intr_config(struct lm3630_chip_data *pchip) -{ - INIT_DELAYED_WORK(&pchip->work, lm3630_delayed_func); - pchip->irqthread = create_singlethread_workqueue("lm3630-irqthd"); - if (!pchip->irqthread) { - dev_err(pchip->dev, "create irq thread fail...\n"); - return -1; - } - if (request_threaded_irq - (pchip->irq, NULL, lm3630_isr_func, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630_irq", pchip)) { - dev_err(pchip->dev, "request threaded irq fail..\n"); - return -1; - } - return 0; -} - -static bool -set_intensity(struct backlight_device *bl, struct lm3630_chip_data *pchip) -{ - if (!pchip->pdata->pwm_set_intensity) - return false; - pchip->pdata->pwm_set_intensity(bl->props.brightness - 1, - pchip->pdata->pwm_period); - return true; -} - -/* update and get brightness */ -static int lm3630_bank_a_update_status(struct backlight_device *bl) -{ - int ret; - struct lm3630_chip_data *pchip = bl_get_data(bl); - enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; - - /* brightness 0 means disable */ - if (!bl->props.brightness) { - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x04, 0x00); - if (ret < 0) - goto out; - return bl->props.brightness; - } - - /* pwm control */ - if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { - if (!set_intensity(bl, pchip)) - dev_err(pchip->dev, "No pwm control func. in plat-data\n"); - } else { - - /* i2c control */ - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - mdelay(1); - ret = regmap_write(pchip->regmap, - REG_BRT_A, bl->props.brightness - 1); - if (ret < 0) - goto out; - } - return bl->props.brightness; -out: - dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); - return bl->props.brightness; -} - -static int lm3630_bank_a_get_brightness(struct backlight_device *bl) -{ - unsigned int reg_val; - int brightness, ret; - struct lm3630_chip_data *pchip = bl_get_data(bl); - enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; - - if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { - ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); - if (ret < 0) - goto out; - brightness = reg_val & 0x01; - ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); - if (ret < 0) - goto out; - brightness = ((brightness << 8) | reg_val) + 1; - } else { - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - mdelay(1); - ret = regmap_read(pchip->regmap, REG_BRT_A, ®_val); - if (ret < 0) - goto out; - brightness = reg_val + 1; - } - bl->props.brightness = brightness; - return bl->props.brightness; -out: - dev_err(pchip->dev, "i2c failed to access register\n"); - return 0; -} - -static const struct backlight_ops lm3630_bank_a_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = lm3630_bank_a_update_status, - .get_brightness = lm3630_bank_a_get_brightness, -}; - -static int lm3630_bank_b_update_status(struct backlight_device *bl) -{ - int ret; - struct lm3630_chip_data *pchip = bl_get_data(bl); - enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; - - if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { - if (!set_intensity(bl, pchip)) - dev_err(pchip->dev, - "no pwm control func. in plat-data\n"); - } else { - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - mdelay(1); - ret = regmap_write(pchip->regmap, - REG_BRT_B, bl->props.brightness - 1); - } - return bl->props.brightness; -out: - dev_err(pchip->dev, "i2c failed to access register\n"); - return bl->props.brightness; -} - -static int lm3630_bank_b_get_brightness(struct backlight_device *bl) -{ - unsigned int reg_val; - int brightness, ret; - struct lm3630_chip_data *pchip = bl_get_data(bl); - enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; - - if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { - ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); - if (ret < 0) - goto out; - brightness = reg_val & 0x01; - ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); - if (ret < 0) - goto out; - brightness = ((brightness << 8) | reg_val) + 1; - } else { - ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); - if (ret < 0) - goto out; - mdelay(1); - ret = regmap_read(pchip->regmap, REG_BRT_B, ®_val); - if (ret < 0) - goto out; - brightness = reg_val + 1; - } - bl->props.brightness = brightness; - - return bl->props.brightness; -out: - dev_err(pchip->dev, "i2c failed to access register\n"); - return bl->props.brightness; -} - -static const struct backlight_ops lm3630_bank_b_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = lm3630_bank_b_update_status, - .get_brightness = lm3630_bank_b_get_brightness, -}; - -static int lm3630_backlight_register(struct lm3630_chip_data *pchip, - enum lm3630_leds ledno) -{ - const char *name = bled_name[ledno]; - struct backlight_properties props; - struct lm3630_platform_data *pdata = pchip->pdata; - - props.type = BACKLIGHT_RAW; - switch (ledno) { - case BLED_1: - case BLED_ALL: - props.brightness = pdata->init_brt_led1; - props.max_brightness = pdata->max_brt_led1; - pchip->bled1 = - backlight_device_register(name, pchip->dev, pchip, - &lm3630_bank_a_ops, &props); - if (IS_ERR(pchip->bled1)) - return PTR_ERR(pchip->bled1); - break; - case BLED_2: - props.brightness = pdata->init_brt_led2; - props.max_brightness = pdata->max_brt_led2; - pchip->bled2 = - backlight_device_register(name, pchip->dev, pchip, - &lm3630_bank_b_ops, &props); - if (IS_ERR(pchip->bled2)) - return PTR_ERR(pchip->bled2); - break; - } - return 0; -} - -static void lm3630_backlight_unregister(struct lm3630_chip_data *pchip) -{ - if (pchip->bled1) - backlight_device_unregister(pchip->bled1); - if (pchip->bled2) - backlight_device_unregister(pchip->bled2); -} - -static const struct regmap_config lm3630_regmap = { - .reg_bits = 8, - .val_bits = 8, - .max_register = REG_MAX, -}; - -static int lm3630_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm3630_platform_data *pdata = client->dev.platform_data; - struct lm3630_chip_data *pchip; - int ret; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "fail : i2c functionality check...\n"); - return -EOPNOTSUPP; - } - - if (pdata == NULL) { - dev_err(&client->dev, "fail : no platform data.\n"); - return -ENODATA; - } - - pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630_chip_data), - GFP_KERNEL); - if (!pchip) - return -ENOMEM; - pchip->pdata = pdata; - pchip->dev = &client->dev; - - pchip->regmap = devm_regmap_init_i2c(client, &lm3630_regmap); - if (IS_ERR(pchip->regmap)) { - ret = PTR_ERR(pchip->regmap); - dev_err(&client->dev, "fail : allocate register map: %d\n", - ret); - return ret; - } - i2c_set_clientdata(client, pchip); - - /* chip initialize */ - ret = lm3630_chip_init(pchip); - if (ret < 0) { - dev_err(&client->dev, "fail : init chip\n"); - goto err_chip_init; - } - - switch (pdata->bank_a_ctrl) { - case BANK_A_CTRL_ALL: - ret = lm3630_backlight_register(pchip, BLED_ALL); - pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; - break; - case BANK_A_CTRL_LED1: - ret = lm3630_backlight_register(pchip, BLED_1); - break; - case BANK_A_CTRL_LED2: - ret = lm3630_backlight_register(pchip, BLED_2); - pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; - break; - default: - break; - } - - if (ret < 0) - goto err_bl_reg; - - if (pdata->bank_b_ctrl && pchip->bled2 == NULL) { - ret = lm3630_backlight_register(pchip, BLED_2); - if (ret < 0) - goto err_bl_reg; - } - - /* interrupt enable : irq 0 is not allowed for lm3630 */ - pchip->irq = client->irq; - if (pchip->irq) - lm3630_intr_config(pchip); - - dev_info(&client->dev, "LM3630 backlight register OK.\n"); - return 0; - -err_bl_reg: - dev_err(&client->dev, "fail : backlight register.\n"); - lm3630_backlight_unregister(pchip); -err_chip_init: - return ret; -} - -static int lm3630_remove(struct i2c_client *client) -{ - int ret; - struct lm3630_chip_data *pchip = i2c_get_clientdata(client); - - ret = regmap_write(pchip->regmap, REG_BRT_A, 0); - if (ret < 0) - dev_err(pchip->dev, "i2c failed to access register\n"); - - ret = regmap_write(pchip->regmap, REG_BRT_B, 0); - if (ret < 0) - dev_err(pchip->dev, "i2c failed to access register\n"); - - lm3630_backlight_unregister(pchip); - if (pchip->irq) { - free_irq(pchip->irq, pchip); - flush_workqueue(pchip->irqthread); - destroy_workqueue(pchip->irqthread); - } - return 0; -} - -static const struct i2c_device_id lm3630_id[] = { - {LM3630_NAME, 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, lm3630_id); - -static struct i2c_driver lm3630_i2c_driver = { - .driver = { - .name = LM3630_NAME, - }, - .probe = lm3630_probe, - .remove = lm3630_remove, - .id_table = lm3630_id, -}; - -module_i2c_driver(lm3630_i2c_driver); - -MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630"); -MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); -MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c new file mode 100644 index 000000000000..35fe4825a454 --- /dev/null +++ b/drivers/video/backlight/lm3630a_bl.c @@ -0,0 +1,483 @@ +/* +* Simple driver for Texas Instruments LM3630A Backlight driver chip +* Copyright (C) 2012 Texas Instruments +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/backlight.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/uaccess.h> +#include <linux/interrupt.h> +#include <linux/regmap.h> +#include <linux/pwm.h> +#include <linux/platform_data/lm3630a_bl.h> + +#define REG_CTRL 0x00 +#define REG_BOOST 0x02 +#define REG_CONFIG 0x01 +#define REG_BRT_A 0x03 +#define REG_BRT_B 0x04 +#define REG_I_A 0x05 +#define REG_I_B 0x06 +#define REG_INT_STATUS 0x09 +#define REG_INT_EN 0x0A +#define REG_FAULT 0x0B +#define REG_PWM_OUTLOW 0x12 +#define REG_PWM_OUTHIGH 0x13 +#define REG_MAX 0x1F + +#define INT_DEBOUNCE_MSEC 10 +struct lm3630a_chip { + struct device *dev; + struct delayed_work work; + + int irq; + struct workqueue_struct *irqthread; + struct lm3630a_platform_data *pdata; + struct backlight_device *bleda; + struct backlight_device *bledb; + struct regmap *regmap; + struct pwm_device *pwmd; +}; + +/* i2c access */ +static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg) +{ + int rval; + unsigned int reg_val; + + rval = regmap_read(pchip->regmap, reg, ®_val); + if (rval < 0) + return rval; + return reg_val & 0xFF; +} + +static int lm3630a_write(struct lm3630a_chip *pchip, + unsigned int reg, unsigned int data) +{ + return regmap_write(pchip->regmap, reg, data); +} + +static int lm3630a_update(struct lm3630a_chip *pchip, + unsigned int reg, unsigned int mask, + unsigned int data) +{ + return regmap_update_bits(pchip->regmap, reg, mask, data); +} + +/* initialize chip */ +static int lm3630a_chip_init(struct lm3630a_chip *pchip) +{ + int rval; + struct lm3630a_platform_data *pdata = pchip->pdata; + + usleep_range(1000, 2000); + /* set Filter Strength Register */ + rval = lm3630a_write(pchip, 0x50, 0x03); + /* set Cofig. register */ + rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl); + /* set boost control */ + rval |= lm3630a_write(pchip, REG_BOOST, 0x38); + /* set current A */ + rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F); + /* set current B */ + rval |= lm3630a_write(pchip, REG_I_B, 0x1F); + /* set control */ + rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl); + rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl); + usleep_range(1000, 2000); + /* set brightness A and B */ + rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt); + rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt); + + if (rval < 0) + dev_err(pchip->dev, "i2c failed to access register\n"); + return rval; +} + +/* interrupt handling */ +static void lm3630a_delayed_func(struct work_struct *work) +{ + int rval; + struct lm3630a_chip *pchip; + + pchip = container_of(work, struct lm3630a_chip, work.work); + + rval = lm3630a_read(pchip, REG_INT_STATUS); + if (rval < 0) { + dev_err(pchip->dev, + "i2c failed to access REG_INT_STATUS Register\n"); + return; + } + + dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval); +} + +static irqreturn_t lm3630a_isr_func(int irq, void *chip) +{ + int rval; + struct lm3630a_chip *pchip = chip; + unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC); + + queue_delayed_work(pchip->irqthread, &pchip->work, delay); + + rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); + if (rval < 0) { + dev_err(pchip->dev, "i2c failed to access register\n"); + return IRQ_NONE; + } + return IRQ_HANDLED; +} + +static int lm3630a_intr_config(struct lm3630a_chip *pchip) +{ + int rval; + + rval = lm3630a_write(pchip, REG_INT_EN, 0x87); + if (rval < 0) + return rval; + + INIT_DELAYED_WORK(&pchip->work, lm3630a_delayed_func); + pchip->irqthread = create_singlethread_workqueue("lm3630a-irqthd"); + if (!pchip->irqthread) { + dev_err(pchip->dev, "create irq thread fail\n"); + return -ENOMEM; + } + if (request_threaded_irq + (pchip->irq, NULL, lm3630a_isr_func, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630a_irq", pchip)) { + dev_err(pchip->dev, "request threaded irq fail\n"); + destroy_workqueue(pchip->irqthread); + return -ENOMEM; + } + return rval; +} + +static void lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max) +{ + unsigned int period = pwm_get_period(pchip->pwmd); + unsigned int duty = br * period / br_max; + + pwm_config(pchip->pwmd, duty, period); + if (duty) + pwm_enable(pchip->pwmd); + else + pwm_disable(pchip->pwmd); +} + +/* update and get brightness */ +static int lm3630a_bank_a_update_status(struct backlight_device *bl) +{ + int ret; + struct lm3630a_chip *pchip = bl_get_data(bl); + enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; + + /* pwm control */ + if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) { + lm3630a_pwm_ctrl(pchip, bl->props.brightness, + bl->props.max_brightness); + return bl->props.brightness; + } + + /* disable sleep */ + ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); + if (ret < 0) + goto out_i2c_err; + usleep_range(1000, 2000); + /* minimum brightness is 0x04 */ + ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness); + if (bl->props.brightness < 0x4) + ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0); + else + ret |= lm3630a_update(pchip, REG_CTRL, + LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE); + if (ret < 0) + goto out_i2c_err; + return bl->props.brightness; + +out_i2c_err: + dev_err(pchip->dev, "i2c failed to access\n"); + return bl->props.brightness; +} + +static int lm3630a_bank_a_get_brightness(struct backlight_device *bl) +{ + int brightness, rval; + struct lm3630a_chip *pchip = bl_get_data(bl); + enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; + + if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) { + rval = lm3630a_read(pchip, REG_PWM_OUTHIGH); + if (rval < 0) + goto out_i2c_err; + brightness = (rval & 0x01) << 8; + rval = lm3630a_read(pchip, REG_PWM_OUTLOW); + if (rval < 0) + goto out_i2c_err; + brightness |= rval; + goto out; + } + + /* disable sleep */ + rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); + if (rval < 0) + goto out_i2c_err; + usleep_range(1000, 2000); + rval = lm3630a_read(pchip, REG_BRT_A); + if (rval < 0) + goto out_i2c_err; + brightness = rval; + +out: + bl->props.brightness = brightness; + return bl->props.brightness; +out_i2c_err: + dev_err(pchip->dev, "i2c failed to access register\n"); + return 0; +} + +static const struct backlight_ops lm3630a_bank_a_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3630a_bank_a_update_status, + .get_brightness = lm3630a_bank_a_get_brightness, +}; + +/* update and get brightness */ +static int lm3630a_bank_b_update_status(struct backlight_device *bl) +{ + int ret; + struct lm3630a_chip *pchip = bl_get_data(bl); + enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; + + /* pwm control */ + if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { + lm3630a_pwm_ctrl(pchip, bl->props.brightness, + bl->props.max_brightness); + return bl->props.brightness; + } + + /* disable sleep */ + ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); + if (ret < 0) + goto out_i2c_err; + usleep_range(1000, 2000); + /* minimum brightness is 0x04 */ + ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness); + if (bl->props.brightness < 0x4) + ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0); + else + ret |= lm3630a_update(pchip, REG_CTRL, + LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE); + if (ret < 0) + goto out_i2c_err; + return bl->props.brightness; + +out_i2c_err: + dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); + return bl->props.brightness; +} + +static int lm3630a_bank_b_get_brightness(struct backlight_device *bl) +{ + int brightness, rval; + struct lm3630a_chip *pchip = bl_get_data(bl); + enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; + + if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { + rval = lm3630a_read(pchip, REG_PWM_OUTHIGH); + if (rval < 0) + goto out_i2c_err; + brightness = (rval & 0x01) << 8; + rval = lm3630a_read(pchip, REG_PWM_OUTLOW); + if (rval < 0) + goto out_i2c_err; + brightness |= rval; + goto out; + } + + /* disable sleep */ + rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00); + if (rval < 0) + goto out_i2c_err; + usleep_range(1000, 2000); + rval = lm3630a_read(pchip, REG_BRT_B); + if (rval < 0) + goto out_i2c_err; + brightness = rval; + +out: + bl->props.brightness = brightness; + return bl->props.brightness; +out_i2c_err: + dev_err(pchip->dev, "i2c failed to access register\n"); + return 0; +} + +static const struct backlight_ops lm3630a_bank_b_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3630a_bank_b_update_status, + .get_brightness = lm3630a_bank_b_get_brightness, +}; + +static int lm3630a_backlight_register(struct lm3630a_chip *pchip) +{ + struct backlight_properties props; + struct lm3630a_platform_data *pdata = pchip->pdata; + + props.type = BACKLIGHT_RAW; + if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) { + props.brightness = pdata->leda_init_brt; + props.max_brightness = pdata->leda_max_brt; + pchip->bleda = + devm_backlight_device_register(pchip->dev, "lm3630a_leda", + pchip->dev, pchip, + &lm3630a_bank_a_ops, &props); + if (IS_ERR(pchip->bleda)) + return PTR_ERR(pchip->bleda); + } + + if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) && + (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) { + props.brightness = pdata->ledb_init_brt; + props.max_brightness = pdata->ledb_max_brt; + pchip->bledb = + devm_backlight_device_register(pchip->dev, "lm3630a_ledb", + pchip->dev, pchip, + &lm3630a_bank_b_ops, &props); + if (IS_ERR(pchip->bledb)) + return PTR_ERR(pchip->bledb); + } + return 0; +} + +static const struct regmap_config lm3630a_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, +}; + +static int lm3630a_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev); + struct lm3630a_chip *pchip; + int rval; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "fail : i2c functionality check\n"); + return -EOPNOTSUPP; + } + + pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip), + GFP_KERNEL); + if (!pchip) + return -ENOMEM; + pchip->dev = &client->dev; + + pchip->regmap = devm_regmap_init_i2c(client, &lm3630a_regmap); + if (IS_ERR(pchip->regmap)) { + rval = PTR_ERR(pchip->regmap); + dev_err(&client->dev, "fail : allocate reg. map: %d\n", rval); + return rval; + } + + i2c_set_clientdata(client, pchip); + if (pdata == NULL) { + pdata = devm_kzalloc(pchip->dev, + sizeof(struct lm3630a_platform_data), + GFP_KERNEL); + if (pdata == NULL) + return -ENOMEM; + /* default values */ + pdata->leda_ctrl = LM3630A_LEDA_ENABLE; + pdata->ledb_ctrl = LM3630A_LEDB_ENABLE; + pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS; + pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS; + pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS; + pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS; + } + pchip->pdata = pdata; + + /* chip initialize */ + rval = lm3630a_chip_init(pchip); + if (rval < 0) { + dev_err(&client->dev, "fail : init chip\n"); + return rval; + } + /* backlight register */ + rval = lm3630a_backlight_register(pchip); + if (rval < 0) { + dev_err(&client->dev, "fail : backlight register.\n"); + return rval; + } + /* pwm */ + if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) { + pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm"); + if (IS_ERR(pchip->pwmd)) { + dev_err(&client->dev, "fail : get pwm device\n"); + return PTR_ERR(pchip->pwmd); + } + } + pchip->pwmd->period = pdata->pwm_period; + + /* interrupt enable : irq 0 is not allowed */ + pchip->irq = client->irq; + if (pchip->irq) { + rval = lm3630a_intr_config(pchip); + if (rval < 0) + return rval; + } + dev_info(&client->dev, "LM3630A backlight register OK.\n"); + return 0; +} + +static int lm3630a_remove(struct i2c_client *client) +{ + int rval; + struct lm3630a_chip *pchip = i2c_get_clientdata(client); + + rval = lm3630a_write(pchip, REG_BRT_A, 0); + if (rval < 0) + dev_err(pchip->dev, "i2c failed to access register\n"); + + rval = lm3630a_write(pchip, REG_BRT_B, 0); + if (rval < 0) + dev_err(pchip->dev, "i2c failed to access register\n"); + + if (pchip->irq) { + free_irq(pchip->irq, pchip); + flush_workqueue(pchip->irqthread); + destroy_workqueue(pchip->irqthread); + } + return 0; +} + +static const struct i2c_device_id lm3630a_id[] = { + {LM3630A_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lm3630a_id); + +static struct i2c_driver lm3630a_i2c_driver = { + .driver = { + .name = LM3630A_NAME, + }, + .probe = lm3630a_probe, + .remove = lm3630a_remove, + .id_table = lm3630a_id, +}; + +module_i2c_driver(lm3630a_i2c_driver); + +MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630A"); +MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>"); +MODULE_AUTHOR("LDD MLP <ldd-mlp@list.ti.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index 053964da8dd3..6fd60adf922e 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -76,10 +76,13 @@ static int lm3639_chip_init(struct lm3639_chip_data *pchip) goto out; /* output pins config. */ - if (!pdata->init_brt_led) - reg_val = pdata->fled_pins | pdata->bled_pins; - else - reg_val = pdata->fled_pins | pdata->bled_pins | 0x01; + if (!pdata->init_brt_led) { + reg_val = pdata->fled_pins; + reg_val |= pdata->bled_pins; + } else { + reg_val = pdata->fled_pins; + reg_val |= pdata->bled_pins | 0x01; + } ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val); if (ret < 0) @@ -304,7 +307,7 @@ static int lm3639_probe(struct i2c_client *client, { int ret; struct lm3639_chip_data *pchip; - struct lm3639_platform_data *pdata = client->dev.platform_data; + struct lm3639_platform_data *pdata = dev_get_platdata(&client->dev); struct backlight_properties props; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 4eec47261cd3..de8832504f68 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -128,7 +128,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power) { struct lms283gf05_state *st = lcd_get_data(ld); struct spi_device *spi = st->spi; - struct lms283gf05_pdata *pdata = spi->dev.platform_data; + struct lms283gf05_pdata *pdata = dev_get_platdata(&spi->dev); if (power <= FB_BLANK_NORMAL) { if (pdata) @@ -153,7 +153,7 @@ static struct lcd_ops lms_ops = { static int lms283gf05_probe(struct spi_device *spi) { struct lms283gf05_state *st; - struct lms283gf05_pdata *pdata = spi->dev.platform_data; + struct lms283gf05_pdata *pdata = dev_get_platdata(&spi->dev); struct lcd_device *ld; int ret = 0; @@ -173,7 +173,8 @@ static int lms283gf05_probe(struct spi_device *spi) return -ENOMEM; } - ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops); + ld = devm_lcd_device_register(&spi->dev, "lms283gf05", &spi->dev, st, + &lms_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -190,22 +191,12 @@ static int lms283gf05_probe(struct spi_device *spi) return 0; } -static int lms283gf05_remove(struct spi_device *spi) -{ - struct lms283gf05_state *st = spi_get_drvdata(spi); - - lcd_device_unregister(st->ld); - - return 0; -} - static struct spi_driver lms283gf05_driver = { .driver = { .name = "lms283gf05", .owner = THIS_MODULE, }, .probe = lms283gf05_probe, - .remove = lms283gf05_remove, }; module_spi_driver(lms283gf05_driver); diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index cf01b9ac8131..77258b7b04be 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -344,14 +344,14 @@ static int lms501kf03_probe(struct spi_device *spi) lcd->spi = spi; lcd->dev = &spi->dev; - lcd->lcd_pd = spi->dev.platform_data; + lcd->lcd_pd = dev_get_platdata(&spi->dev); if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL\n"); return -EINVAL; } - ld = lcd_device_register("lms501kf03", &spi->dev, lcd, - &lms501kf03_lcd_ops); + ld = devm_lcd_device_register(&spi->dev, "lms501kf03", &spi->dev, lcd, + &lms501kf03_lcd_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -382,8 +382,6 @@ static int lms501kf03_remove(struct spi_device *spi) struct lms501kf03 *lcd = spi_get_drvdata(spi); lms501kf03_power(lcd, FB_BLANK_POWERDOWN); - lcd_device_unregister(lcd->ld); - return 0; } diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index c0b41f13bd4a..cae80d555e84 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c @@ -26,13 +26,15 @@ #define LP8556_EPROM_START 0xA0 #define LP8556_EPROM_END 0xAF -/* LP8557 Registers */ +/* LP8555/7 Registers */ #define LP8557_BL_CMD 0x00 #define LP8557_BL_MASK 0x01 #define LP8557_BL_ON 0x01 #define LP8557_BL_OFF 0x00 #define LP8557_BRIGHTNESS_CTRL 0x04 #define LP8557_CONFIG 0x10 +#define LP8555_EPROM_START 0x10 +#define LP8555_EPROM_END 0x7A #define LP8557_EPROM_START 0x10 #define LP8557_EPROM_END 0x1E @@ -111,6 +113,10 @@ static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) start = LP8556_EPROM_START; end = LP8556_EPROM_END; break; + case LP8555: + start = LP8555_EPROM_START; + end = LP8555_EPROM_END; + break; case LP8557: start = LP8557_EPROM_START; end = LP8557_EPROM_END; @@ -165,9 +171,14 @@ static int lp855x_configure(struct lp855x *lp) struct lp855x_platform_data *pd = lp->pdata; switch (lp->chip_id) { - case LP8550 ... LP8556: + case LP8550: + case LP8551: + case LP8552: + case LP8553: + case LP8556: lp->cfg = &lp855x_dev_cfg; break; + case LP8555: case LP8557: lp->cfg = &lp8557_dev_cfg; break; @@ -289,7 +300,7 @@ static int lp855x_backlight_register(struct lp855x *lp) props.brightness = pdata->initial_brightness; - bl = backlight_device_register(name, lp->dev, lp, + bl = devm_backlight_device_register(lp->dev, name, lp->dev, lp, &lp855x_bl_ops, &props); if (IS_ERR(bl)) return PTR_ERR(bl); @@ -299,12 +310,6 @@ static int lp855x_backlight_register(struct lp855x *lp) return 0; } -static void lp855x_backlight_unregister(struct lp855x *lp) -{ - if (lp->bl) - backlight_device_unregister(lp->bl); -} - static ssize_t lp855x_get_chip_id(struct device *dev, struct device_attribute *attr, char *buf) { @@ -394,7 +399,7 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node) static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp855x *lp; - struct lp855x_platform_data *pdata = cl->dev.platform_data; + struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev); struct device_node *node = cl->dev.of_node; int ret; @@ -403,7 +408,7 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) if (ret < 0) return ret; - pdata = cl->dev.platform_data; + pdata = dev_get_platdata(&cl->dev); } if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) @@ -428,29 +433,24 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) ret = lp855x_configure(lp); if (ret) { dev_err(lp->dev, "device config err: %d", ret); - goto err_dev; + return ret; } ret = lp855x_backlight_register(lp); if (ret) { dev_err(lp->dev, "failed to register backlight. err: %d\n", ret); - goto err_dev; + return ret; } ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group); if (ret) { dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret); - goto err_sysfs; + return ret; } backlight_update_status(lp->bl); return 0; - -err_sysfs: - lp855x_backlight_unregister(lp); -err_dev: - return ret; } static int lp855x_remove(struct i2c_client *cl) @@ -460,7 +460,6 @@ static int lp855x_remove(struct i2c_client *cl) lp->bl->props.brightness = 0; backlight_update_status(lp->bl); sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group); - lp855x_backlight_unregister(lp); return 0; } @@ -470,6 +469,7 @@ static const struct of_device_id lp855x_dt_ids[] = { { .compatible = "ti,lp8551", }, { .compatible = "ti,lp8552", }, { .compatible = "ti,lp8553", }, + { .compatible = "ti,lp8555", }, { .compatible = "ti,lp8556", }, { .compatible = "ti,lp8557", }, { } @@ -481,6 +481,7 @@ static const struct i2c_device_id lp855x_ids[] = { {"lp8551", LP8551}, {"lp8552", LP8552}, {"lp8553", LP8553}, + {"lp8555", LP8555}, {"lp8556", LP8556}, {"lp8557", LP8557}, { } diff --git a/drivers/video/backlight/lp8788_bl.c b/drivers/video/backlight/lp8788_bl.c index 980855ec9bb1..e49905d495dc 100644 --- a/drivers/video/backlight/lp8788_bl.c +++ b/drivers/video/backlight/lp8788_bl.c @@ -52,7 +52,7 @@ struct lp8788_bl { struct pwm_device *pwm; }; -struct lp8788_bl_config default_bl_config = { +static struct lp8788_bl_config default_bl_config = { .bl_mode = LP8788_BL_REGISTER_ONLY, .dim_mode = LP8788_DIM_EXPONENTIAL, .full_scale = LP8788_FULLSCALE_1900uA, diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index ed1b39268131..383f550e165e 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -242,7 +242,8 @@ static int ltv350qv_probe(struct spi_device *spi) if (!lcd->buffer) return -ENOMEM; - ld = lcd_device_register("ltv350qv", &spi->dev, lcd, <v_ops); + ld = devm_lcd_device_register(&spi->dev, "ltv350qv", &spi->dev, lcd, + <v_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -250,15 +251,11 @@ static int ltv350qv_probe(struct spi_device *spi) ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); if (ret) - goto out_unregister; + return ret; spi_set_drvdata(spi, lcd); return 0; - -out_unregister: - lcd_device_unregister(ld); - return ret; } static int ltv350qv_remove(struct spi_device *spi) @@ -266,8 +263,6 @@ static int ltv350qv_remove(struct spi_device *spi) struct ltv350qv *lcd = spi_get_drvdata(spi); ltv350qv_power(lcd, FB_BLANK_POWERDOWN); - lcd_device_unregister(lcd->ld); - return 0; } diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c index 498fd73d59b9..1802b2d1357d 100644 --- a/drivers/video/backlight/lv5207lp.c +++ b/drivers/video/backlight/lv5207lp.c @@ -93,7 +93,7 @@ static const struct backlight_ops lv5207lp_backlight_ops = { static int lv5207lp_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct lv5207lp_platform_data *pdata = client->dev.platform_data; + struct lv5207lp_platform_data *pdata = dev_get_platdata(&client->dev); struct backlight_device *backlight; struct backlight_properties props; struct lv5207lp *lv; @@ -124,9 +124,9 @@ static int lv5207lp_probe(struct i2c_client *client, props.brightness = clamp_t(unsigned int, pdata->def_value, 0, props.max_brightness); - backlight = backlight_device_register(dev_name(&client->dev), - &lv->client->dev, lv, - &lv5207lp_backlight_ops, &props); + backlight = devm_backlight_device_register(&client->dev, + dev_name(&client->dev), &lv->client->dev, + lv, &lv5207lp_backlight_ops, &props); if (IS_ERR(backlight)) { dev_err(&client->dev, "failed to register backlight\n"); return PTR_ERR(backlight); @@ -144,7 +144,6 @@ static int lv5207lp_remove(struct i2c_client *client) backlight->props.brightness = 0; backlight_update_status(backlight); - backlight_device_unregister(backlight); return 0; } diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 886e797f75f9..66fa08c920d2 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -163,7 +163,8 @@ static int max8925_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; - bl = backlight_device_register("max8925-backlight", &pdev->dev, data, + bl = devm_backlight_device_register(&pdev->dev, "max8925-backlight", + &pdev->dev, data, &max8925_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); @@ -188,20 +189,9 @@ static int max8925_backlight_probe(struct platform_device *pdev) } ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value); if (ret < 0) - goto out_brt; + return ret; backlight_update_status(bl); return 0; -out_brt: - backlight_device_unregister(bl); - return ret; -} - -static int max8925_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - - backlight_device_unregister(bl); - return 0; } static struct platform_driver max8925_backlight_driver = { @@ -210,7 +200,6 @@ static struct platform_driver max8925_backlight_driver = { .owner = THIS_MODULE, }, .probe = max8925_backlight_probe, - .remove = max8925_backlight_remove, }; module_platform_driver(max8925_backlight_driver); diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 812e22e35cab..ac11a4650c19 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -133,7 +133,7 @@ static int omapbl_probe(struct platform_device *pdev) struct backlight_properties props; struct backlight_device *dev; struct omap_backlight *bl; - struct omap_backlight_config *pdata = pdev->dev.platform_data; + struct omap_backlight_config *pdata = dev_get_platdata(&pdev->dev); if (!pdata) return -ENXIO; diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c index 633b0a22fd64..2098c5d6efb9 100644 --- a/drivers/video/backlight/pandora_bl.c +++ b/drivers/video/backlight/pandora_bl.c @@ -120,8 +120,8 @@ static int pandora_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(props)); props.max_brightness = MAX_USER_VALUE; props.type = BACKLIGHT_RAW; - bl = backlight_device_register(pdev->name, &pdev->dev, - NULL, &pandora_backlight_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, pdev->name, &pdev->dev, + NULL, &pandora_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -145,20 +145,12 @@ static int pandora_backlight_probe(struct platform_device *pdev) return 0; } -static int pandora_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - backlight_device_unregister(bl); - return 0; -} - static struct platform_driver pandora_backlight_driver = { .driver = { .name = "pandora-backlight", .owner = THIS_MODULE, }, .probe = pandora_backlight_probe, - .remove = pandora_backlight_remove, }; module_platform_driver(pandora_backlight_driver); diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index 6ed76be18f19..b95d3b0aaffe 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c @@ -103,7 +103,7 @@ static int pcf50633_bl_probe(struct platform_device *pdev) { struct pcf50633_bl *pcf_bl; struct device *parent = pdev->dev.parent; - struct pcf50633_platform_data *pcf50633_data = parent->platform_data; + struct pcf50633_platform_data *pcf50633_data = dev_get_platdata(parent); struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data; struct backlight_properties bl_props; @@ -126,7 +126,8 @@ static int pcf50633_bl_probe(struct platform_device *pdev) pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent); - pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl, + pcf_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name, + &pdev->dev, pcf_bl, &pcf50633_bl_ops, &bl_props); if (IS_ERR(pcf_bl->bl)) @@ -147,18 +148,8 @@ static int pcf50633_bl_probe(struct platform_device *pdev) return 0; } -static int pcf50633_bl_remove(struct platform_device *pdev) -{ - struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev); - - backlight_device_unregister(pcf_bl->bl); - - return 0; -} - static struct platform_driver pcf50633_bl_driver = { .probe = pcf50633_bl_probe, - .remove = pcf50633_bl_remove, .driver = { .name = "pcf50633-backlight", }, diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 056836706708..d01884d4f1bf 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c @@ -80,7 +80,7 @@ static int platform_lcd_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int err; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(dev, "no platform data supplied\n"); return -EINVAL; @@ -101,30 +101,17 @@ static int platform_lcd_probe(struct platform_device *pdev) plcd->us = dev; plcd->pdata = pdata; - plcd->lcd = lcd_device_register(dev_name(dev), dev, - plcd, &platform_lcd_ops); + plcd->lcd = devm_lcd_device_register(&pdev->dev, dev_name(dev), dev, + plcd, &platform_lcd_ops); if (IS_ERR(plcd->lcd)) { dev_err(dev, "cannot register lcd device\n"); - err = PTR_ERR(plcd->lcd); - goto err; + return PTR_ERR(plcd->lcd); } platform_set_drvdata(pdev, plcd); platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL); return 0; - - err: - return err; -} - -static int platform_lcd_remove(struct platform_device *pdev) -{ - struct platform_lcd *plcd = platform_get_drvdata(pdev); - - lcd_device_unregister(plcd->lcd); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -168,7 +155,6 @@ static struct platform_driver platform_lcd_driver = { .of_match_table = of_match_ptr(platform_lcd_of_match), }, .probe = platform_lcd_probe, - .remove = platform_lcd_remove, }; module_platform_driver(platform_lcd_driver); diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 1fea627394d7..fb80d68f4d33 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -19,6 +21,7 @@ #include <linux/err.h> #include <linux/pwm.h> #include <linux/pwm_backlight.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> struct pwm_bl_data { @@ -27,6 +30,11 @@ struct pwm_bl_data { unsigned int period; unsigned int lth_brightness; unsigned int *levels; + bool enabled; + struct regulator *power_supply; + int enable_gpio; + unsigned long enable_gpio_flags; + unsigned int scale; int (*notify)(struct device *, int brightness); void (*notify_after)(struct device *, @@ -35,11 +43,65 @@ struct pwm_bl_data { void (*exit)(struct device *); }; +static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness) +{ + int err; + + if (pb->enabled) + return; + + err = regulator_enable(pb->power_supply); + if (err < 0) + dev_err(pb->dev, "failed to enable power supply\n"); + + if (gpio_is_valid(pb->enable_gpio)) { + if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) + gpio_set_value(pb->enable_gpio, 0); + else + gpio_set_value(pb->enable_gpio, 1); + } + + pwm_enable(pb->pwm); + pb->enabled = true; +} + +static void pwm_backlight_power_off(struct pwm_bl_data *pb) +{ + if (!pb->enabled) + return; + + pwm_config(pb->pwm, 0, pb->period); + pwm_disable(pb->pwm); + + if (gpio_is_valid(pb->enable_gpio)) { + if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) + gpio_set_value(pb->enable_gpio, 1); + else + gpio_set_value(pb->enable_gpio, 0); + } + + regulator_disable(pb->power_supply); + pb->enabled = false; +} + +static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness) +{ + unsigned int lth = pb->lth_brightness; + int duty_cycle; + + if (pb->levels) + duty_cycle = pb->levels[brightness]; + else + duty_cycle = brightness; + + return (duty_cycle * (pb->period - lth) / pb->scale) + lth; +} + static int pwm_backlight_update_status(struct backlight_device *bl) { struct pwm_bl_data *pb = bl_get_data(bl); int brightness = bl->props.brightness; - int max = bl->props.max_brightness; + int duty_cycle; if (bl->props.power != FB_BLANK_UNBLANK || bl->props.fb_blank != FB_BLANK_UNBLANK || @@ -49,24 +111,12 @@ static int pwm_backlight_update_status(struct backlight_device *bl) if (pb->notify) brightness = pb->notify(pb->dev, brightness); - if (brightness == 0) { - pwm_config(pb->pwm, 0, pb->period); - pwm_disable(pb->pwm); - } else { - int duty_cycle; - - if (pb->levels) { - duty_cycle = pb->levels[brightness]; - max = pb->levels[max]; - } else { - duty_cycle = brightness; - } - - duty_cycle = pb->lth_brightness + - (duty_cycle * (pb->period - pb->lth_brightness) / max); + if (brightness > 0) { + duty_cycle = compute_duty_cycle(pb, brightness); pwm_config(pb->pwm, duty_cycle, pb->period); - pwm_enable(pb->pwm); - } + pwm_backlight_power_on(pb, brightness); + } else + pwm_backlight_power_off(pb); if (pb->notify_after) pb->notify_after(pb->dev, brightness); @@ -98,6 +148,7 @@ static int pwm_backlight_parse_dt(struct device *dev, struct platform_pwm_backlight_data *data) { struct device_node *node = dev->of_node; + enum of_gpio_flags flags; struct property *prop; int length; u32 value; @@ -138,11 +189,13 @@ static int pwm_backlight_parse_dt(struct device *dev, data->max_brightness--; } - /* - * TODO: Most users of this driver use a number of GPIOs to control - * backlight power. Support for specifying these needs to be - * added. - */ + data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0, + &flags); + if (data->enable_gpio == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (gpio_is_valid(data->enable_gpio) && (flags & OF_GPIO_ACTIVE_LOW)) + data->enable_gpio_flags |= PWM_BACKLIGHT_GPIO_ACTIVE_LOW; return 0; } @@ -163,12 +216,11 @@ static int pwm_backlight_parse_dt(struct device *dev, static int pwm_backlight_probe(struct platform_device *pdev) { - struct platform_pwm_backlight_data *data = pdev->dev.platform_data; + struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev); struct platform_pwm_backlight_data defdata; struct backlight_properties props; struct backlight_device *bl; struct pwm_bl_data *pb; - unsigned int max; int ret; if (!data) { @@ -195,16 +247,46 @@ static int pwm_backlight_probe(struct platform_device *pdev) } if (data->levels) { - max = data->levels[data->max_brightness]; + unsigned int i; + + for (i = 0; i <= data->max_brightness; i++) + if (data->levels[i] > pb->scale) + pb->scale = data->levels[i]; + pb->levels = data->levels; } else - max = data->max_brightness; + pb->scale = data->max_brightness; + pb->enable_gpio = data->enable_gpio; + pb->enable_gpio_flags = data->enable_gpio_flags; pb->notify = data->notify; pb->notify_after = data->notify_after; pb->check_fb = data->check_fb; pb->exit = data->exit; pb->dev = &pdev->dev; + pb->enabled = false; + + if (gpio_is_valid(pb->enable_gpio)) { + unsigned long flags; + + if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW) + flags = GPIOF_OUT_INIT_HIGH; + else + flags = GPIOF_OUT_INIT_LOW; + + ret = gpio_request_one(pb->enable_gpio, flags, "enable"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n", + pb->enable_gpio, ret); + goto err_alloc; + } + } + + pb->power_supply = devm_regulator_get(&pdev->dev, "power"); + if (IS_ERR(pb->power_supply)) { + ret = PTR_ERR(pb->power_supply); + goto err_gpio; + } pb->pwm = devm_pwm_get(&pdev->dev, NULL); if (IS_ERR(pb->pwm)) { @@ -214,7 +296,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) if (IS_ERR(pb->pwm)) { dev_err(&pdev->dev, "unable to request legacy PWM\n"); ret = PTR_ERR(pb->pwm); - goto err_alloc; + goto err_gpio; } } @@ -229,7 +311,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) pwm_set_period(pb->pwm, data->pwm_period_ns); pb->period = pwm_get_period(pb->pwm); - pb->lth_brightness = data->lth_brightness * (pb->period / max); + pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale); memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; @@ -239,7 +321,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); ret = PTR_ERR(bl); - goto err_alloc; + goto err_gpio; } if (data->dft_brightness > data->max_brightness) { @@ -255,6 +337,9 @@ static int pwm_backlight_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bl); return 0; +err_gpio: + if (gpio_is_valid(pb->enable_gpio)) + gpio_free(pb->enable_gpio); err_alloc: if (data->exit) data->exit(&pdev->dev); @@ -267,10 +352,11 @@ static int pwm_backlight_remove(struct platform_device *pdev) struct pwm_bl_data *pb = bl_get_data(bl); backlight_device_unregister(bl); - pwm_config(pb->pwm, 0, pb->period); - pwm_disable(pb->pwm); + pwm_backlight_power_off(pb); + if (pb->exit) pb->exit(&pdev->dev); + return 0; } @@ -282,10 +368,12 @@ static int pwm_backlight_suspend(struct device *dev) if (pb->notify) pb->notify(pb->dev, 0); - pwm_config(pb->pwm, 0, pb->period); - pwm_disable(pb->pwm); + + pwm_backlight_power_off(pb); + if (pb->notify_after) pb->notify_after(pb->dev, 0); + return 0; } @@ -294,12 +382,19 @@ static int pwm_backlight_resume(struct device *dev) struct backlight_device *bl = dev_get_drvdata(dev); backlight_update_status(bl); + return 0; } #endif -static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, - pwm_backlight_resume); +static const struct dev_pm_ops pwm_backlight_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = pwm_backlight_suspend, + .resume = pwm_backlight_resume, + .poweroff = pwm_backlight_suspend, + .restore = pwm_backlight_resume, +#endif +}; static struct platform_driver pwm_backlight_driver = { .driver = { @@ -317,4 +412,3 @@ module_platform_driver(pwm_backlight_driver); MODULE_DESCRIPTION("PWM based Backlight Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pwm-backlight"); - diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index b37bb1854bf4..510a1bcf76f1 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c @@ -735,13 +735,14 @@ static int s6e63m0_probe(struct spi_device *spi) lcd->spi = spi; lcd->dev = &spi->dev; - lcd->lcd_pd = spi->dev.platform_data; + lcd->lcd_pd = dev_get_platdata(&spi->dev); if (!lcd->lcd_pd) { dev_err(&spi->dev, "platform data is NULL.\n"); return -EINVAL; } - ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops); + ld = devm_lcd_device_register(&spi->dev, "s6e63m0", &spi->dev, lcd, + &s6e63m0_lcd_ops); if (IS_ERR(ld)) return PTR_ERR(ld); @@ -751,12 +752,11 @@ static int s6e63m0_probe(struct spi_device *spi) props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; - bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, - &s6e63m0_backlight_ops, &props); - if (IS_ERR(bd)) { - ret = PTR_ERR(bd); - goto out_lcd_unregister; - } + bd = devm_backlight_device_register(&spi->dev, "s6e63m0bl-bl", + &spi->dev, lcd, &s6e63m0_backlight_ops, + &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); bd->props.brightness = MAX_BRIGHTNESS; lcd->bd = bd; @@ -798,10 +798,6 @@ static int s6e63m0_probe(struct spi_device *spi) dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n"); return 0; - -out_lcd_unregister: - lcd_device_unregister(ld); - return ret; } static int s6e63m0_remove(struct spi_device *spi) @@ -811,8 +807,6 @@ static int s6e63m0_remove(struct spi_device *spi) s6e63m0_power(lcd, FB_BLANK_POWERDOWN); device_remove_file(&spi->dev, &dev_attr_gamma_table); device_remove_file(&spi->dev, &dev_attr_gamma_mode); - backlight_device_unregister(lcd->bd); - lcd_device_unregister(lcd->ld); return 0; } diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 18cdf466d50a..908016fc5829 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -338,7 +338,7 @@ static int tdo24m_probe(struct spi_device *spi) enum tdo24m_model model; int err; - pdata = spi->dev.platform_data; + pdata = dev_get_platdata(&spi->dev); if (pdata) model = pdata->model; else @@ -385,21 +385,17 @@ static int tdo24m_probe(struct spi_device *spi) return -EINVAL; } - lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev, - lcd, &tdo24m_ops); + lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "tdo24m", &spi->dev, + lcd, &tdo24m_ops); if (IS_ERR(lcd->lcd_dev)) return PTR_ERR(lcd->lcd_dev); spi_set_drvdata(spi, lcd); err = tdo24m_power(lcd, FB_BLANK_UNBLANK); if (err) - goto out_unregister; + return err; return 0; - -out_unregister: - lcd_device_unregister(lcd->lcd_dev); - return err; } static int tdo24m_remove(struct spi_device *spi) @@ -407,8 +403,6 @@ static int tdo24m_remove(struct spi_device *spi) struct tdo24m *lcd = spi_get_drvdata(spi); tdo24m_power(lcd, FB_BLANK_POWERDOWN); - lcd_device_unregister(lcd->lcd_dev); - return 0; } diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 9df66ac68b34..b8db9338cacd 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -38,7 +38,7 @@ struct tosa_bl_data { static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness) { - struct spi_device *spi = data->i2c->dev.platform_data; + struct spi_device *spi = dev_get_platdata(&data->i2c->dev); i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj); diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index bf081573e5b5..be5d636764bf 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -198,7 +198,7 @@ static int tosa_lcd_probe(struct spi_device *spi) ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, GPIOF_OUT_INIT_LOW, "tg #pwr"); if (ret < 0) - goto err_gpio_tg; + return ret; mdelay(60); @@ -219,8 +219,6 @@ static int tosa_lcd_probe(struct spi_device *spi) err_register: tosa_lcd_tg_off(data); -err_gpio_tg: - spi_set_drvdata(spi, NULL); return ret; } @@ -235,8 +233,6 @@ static int tosa_lcd_remove(struct spi_device *spi) tosa_lcd_tg_off(data); - spi_set_drvdata(spi, NULL); - return 0; } diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c index 05782312aeb3..cbba37e6836e 100644 --- a/drivers/video/backlight/tps65217_bl.c +++ b/drivers/video/backlight/tps65217_bl.c @@ -287,12 +287,11 @@ static int tps65217_bl_probe(struct platform_device *pdev) if (IS_ERR(pdata)) return PTR_ERR(pdata); } else { - if (!pdev->dev.platform_data) { + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { dev_err(&pdev->dev, "no platform data provided\n"); return -EINVAL; } - - pdata = pdev->dev.platform_data; } tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl), @@ -314,7 +313,7 @@ static int tps65217_bl_probe(struct platform_device *pdev) bl_props.type = BACKLIGHT_RAW; bl_props.max_brightness = 100; - tps65217_bl->bl = backlight_device_register(pdev->name, + tps65217_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name, tps65217_bl->dev, tps65217_bl, &tps65217_bl_ops, &bl_props); if (IS_ERR(tps65217_bl->bl)) { @@ -330,18 +329,8 @@ static int tps65217_bl_probe(struct platform_device *pdev) return 0; } -static int tps65217_bl_remove(struct platform_device *pdev) -{ - struct tps65217_bl *tps65217_bl = platform_get_drvdata(pdev); - - backlight_device_unregister(tps65217_bl->bl); - - return 0; -} - static struct platform_driver tps65217_bl_driver = { .probe = tps65217_bl_probe, - .remove = tps65217_bl_remove, .driver = { .owner = THIS_MODULE, .name = "tps65217-bl", diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index 9e5517a3a52b..8b9455e93069 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c @@ -123,7 +123,7 @@ static const struct backlight_ops wm831x_backlight_ops = { static int wm831x_backlight_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *wm831x_pdata; + struct wm831x_pdata *wm831x_pdata = dev_get_platdata(pdev->dev.parent); struct wm831x_backlight_pdata *pdata; struct wm831x_backlight_data *data; struct backlight_device *bl; @@ -131,12 +131,10 @@ static int wm831x_backlight_probe(struct platform_device *pdev) int ret, i, max_isel, isink_reg, dcdc_cfg; /* We need platform data */ - if (pdev->dev.parent->platform_data) { - wm831x_pdata = pdev->dev.parent->platform_data; + if (wm831x_pdata) pdata = wm831x_pdata->backlight; - } else { + else pdata = NULL; - } if (!pdata) { dev_err(&pdev->dev, "No platform data supplied\n"); @@ -197,8 +195,8 @@ static int wm831x_backlight_probe(struct platform_device *pdev) memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.max_brightness = max_isel; - bl = backlight_device_register("wm831x", &pdev->dev, data, - &wm831x_backlight_ops, &props); + bl = devm_backlight_device_register(&pdev->dev, "wm831x", &pdev->dev, + data, &wm831x_backlight_ops, &props); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); return PTR_ERR(bl); @@ -216,21 +214,12 @@ static int wm831x_backlight_probe(struct platform_device *pdev) return 0; } -static int wm831x_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bl = platform_get_drvdata(pdev); - - backlight_device_unregister(bl); - return 0; -} - static struct platform_driver wm831x_backlight_driver = { .driver = { .name = "wm831x-backlight", .owner = THIS_MODULE, }, .probe = wm831x_backlight_probe, - .remove = wm831x_backlight_remove, }; module_platform_driver(wm831x_backlight_driver); diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 87f288bfc58c..42b8f9d11018 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -761,19 +761,7 @@ static struct platform_driver bfin_bf54x_driver = { .owner = THIS_MODULE, }, }; - -static int __init bfin_bf54x_driver_init(void) -{ - return platform_driver_register(&bfin_bf54x_driver); -} - -static void __exit bfin_bf54x_driver_cleanup(void) -{ - platform_driver_unregister(&bfin_bf54x_driver); -} +module_platform_driver(bfin_bf54x_driver); MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver"); MODULE_LICENSE("GPL"); - -module_init(bfin_bf54x_driver_init); -module_exit(bfin_bf54x_driver_cleanup); diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 48c0c4e38a62..b5cf1307a3d9 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -664,19 +664,7 @@ static struct platform_driver bfin_t350mcqb_driver = { .owner = THIS_MODULE, }, }; - -static int __init bfin_t350mcqb_driver_init(void) -{ - return platform_driver_register(&bfin_t350mcqb_driver); -} - -static void __exit bfin_t350mcqb_driver_cleanup(void) -{ - platform_driver_unregister(&bfin_t350mcqb_driver); -} +module_platform_driver(bfin_t350mcqb_driver); MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); MODULE_LICENSE("GPL"); - -module_init(bfin_t350mcqb_driver_init); -module_exit(bfin_t350mcqb_driver_cleanup); diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index b09701c79432..8556264b16b7 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c @@ -1167,9 +1167,8 @@ static int broadsheetfb_probe(struct platform_device *dev) if (retval < 0) goto err_unreg_fb; - printk(KERN_INFO - "fb%d: Broadsheet frame buffer, using %dK of video memory\n", - info->node, videomemorysize >> 10); + fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n", + videomemorysize >> 10); return 0; @@ -1217,19 +1216,7 @@ static struct platform_driver broadsheetfb_driver = { .name = "broadsheetfb", }, }; - -static int __init broadsheetfb_init(void) -{ - return platform_driver_register(&broadsheetfb_driver); -} - -static void __exit broadsheetfb_exit(void) -{ - platform_driver_unregister(&broadsheetfb_driver); -} - -module_init(broadsheetfb_init); -module_exit(broadsheetfb_exit); +module_platform_driver(broadsheetfb_driver); MODULE_DESCRIPTION("fbdev driver for Broadsheet controller"); MODULE_AUTHOR("Jaya Kumar"); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 60017fc634b5..bc123d6947a4 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -363,8 +363,6 @@ static int bw2_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index 153dd65b0ae8..65f7c15f5fdb 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c @@ -585,8 +585,7 @@ static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base, if (ret < 0) goto err_dealloc_cmap; - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); *rinfo = info; return 0; @@ -746,7 +745,6 @@ static void carminefb_remove(struct pci_dev *dev) iounmap(hw->v_regs); release_mem_region(fix.mmio_start, fix.mmio_len); - pci_set_drvdata(dev, NULL); pci_disable_device(dev); kfree(hw); } diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index baed57d3cfff..a2bb276a8b24 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -181,7 +181,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * } shift += bpp; shift &= (32 - 1); - if (!l) { l = 8; s++; }; + if (!l) { l = 8; s++; } } /* write trailing bits */ diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index ed3b8891e006..c79745b136bb 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -330,7 +330,7 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) default: ret = -ENOSYS; break; - }; + } if (!ret) { sbus_writeb(cur_mode, ®s->mcr); par->mode = mode; @@ -343,7 +343,7 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) FBTYPE_MDICOLOR, 8, info->fix.smem_len); break; - }; + } return ret; } @@ -583,8 +583,6 @@ static int cg14_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 9f63507ded37..64a89d5747ed 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -446,8 +446,6 @@ static int cg3_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 3545decc7485..70781fea092a 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -624,7 +624,7 @@ static void cg6_init_fix(struct fb_info *info, int linebytes) default: cg6_cpu_name = "i386"; break; - }; + } if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { if (info->fix.smem_len <= 0x100000) cg6_card_name = "TGX"; @@ -839,8 +839,6 @@ static int cg6_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 97db3ba8f237..5aab9b9dc210 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -595,11 +595,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, return -EINVAL; } - if (var->xoffset < 0) - var->xoffset = 0; - if (var->yoffset < 0) - var->yoffset = 0; - /* truncate xoffset and yoffset to maximum if too high */ if (var->xoffset > var->xres_virtual - var->xres) var->xoffset = var->xres_virtual - var->xres - 1; @@ -2159,7 +2154,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, if (!ret) return 0; - pci_set_drvdata(pdev, NULL); iounmap(info->screen_base); err_release_legacy: if (release_io_ports) diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index a9031498e10c..d5533f4db1cf 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -368,8 +368,7 @@ static int cobalt_lcdfb_probe(struct platform_device *dev) lcd_clear(info); - printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n", - info->node); + fb_info(info, "Cobalt server LCD frame buffer device\n"); return 0; } @@ -395,19 +394,7 @@ static struct platform_driver cobalt_lcdfb_driver = { .owner = THIS_MODULE, }, }; - -static int __init cobalt_lcdfb_init(void) -{ - return platform_driver_register(&cobalt_lcdfb_driver); -} - -static void __exit cobalt_lcdfb_exit(void) -{ - platform_driver_unregister(&cobalt_lcdfb_driver); -} - -module_init(cobalt_lcdfb_init); -module_exit(cobalt_lcdfb_exit); +module_platform_driver(cobalt_lcdfb_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Yoichi Yuasa"); diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 846caab75a46..fe1cd0148e13 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -8,7 +8,8 @@ config VGA_CONSOLE bool "VGA text console" if EXPERT || !X86 depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && \ !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \ - (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) + (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \ + !ARM64 default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index cd8a8027f8ae..4e39291ac8b4 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3547,8 +3547,10 @@ static void fbcon_exit(void) "no")); for (j = first_fb_vc; j <= last_fb_vc; j++) { - if (con2fb_map[j] == i) + if (con2fb_map[j] == i) { mapped = 1; + break; + } } if (mapped) { @@ -3561,6 +3563,7 @@ static void fbcon_exit(void) fbcon_del_cursor_timer(info); kfree(ops->cursor_src); + kfree(ops->cursor_state.mask); kfree(info->fbcon_par); info->fbcon_par = NULL; } diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 35687fd56456..4ad24f2c6472 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -3,7 +3,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2001-2003 Helge Deller <deller@gmx.de> + * Copyright (C) 2001-2013 Helge Deller <deller@gmx.de> * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * * TODO: @@ -30,7 +30,7 @@ #include "../sticore.h" -#define STI_DRIVERVERSION "Version 0.9a" +#define STI_DRIVERVERSION "Version 0.9b" static struct sti_struct *default_sti __read_mostly; @@ -73,28 +73,34 @@ static const struct sti_init_flags default_init_flags = { static int sti_init_graph(struct sti_struct *sti) { - struct sti_init_inptr_ext inptr_ext = { 0, }; - struct sti_init_inptr inptr = { - .text_planes = 3, /* # of text planes (max 3 for STI) */ - .ext_ptr = STI_PTR(&inptr_ext) - }; - struct sti_init_outptr outptr = { 0, }; + struct sti_init_inptr *inptr = &sti->sti_data->init_inptr; + struct sti_init_inptr_ext *inptr_ext = &sti->sti_data->init_inptr_ext; + struct sti_init_outptr *outptr = &sti->sti_data->init_outptr; unsigned long flags; - int ret; + int ret, err; spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, - &outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + inptr->text_planes = 3; /* # of text planes (max 3 for STI) */ + memset(inptr_ext, 0, sizeof(*inptr_ext)); + inptr->ext_ptr = STI_PTR(inptr_ext); + outptr->errno = 0; + + ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr, + outptr, sti->glob_cfg); + + if (ret >= 0) + sti->text_planes = outptr->text_planes; + err = outptr->errno; spin_unlock_irqrestore(&sti->lock, flags); if (ret < 0) { - printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno); + pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err); return -1; } - sti->text_planes = outptr.text_planes; return 0; } @@ -104,16 +110,18 @@ static const struct sti_conf_flags default_conf_flags = { static void sti_inq_conf(struct sti_struct *sti) { - struct sti_conf_inptr inptr = { 0, }; + struct sti_conf_inptr *inptr = &sti->sti_data->inq_inptr; + struct sti_conf_outptr *outptr = &sti->sti_data->inq_outptr; unsigned long flags; s32 ret; - sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext); + outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext); do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->inq_conf, &default_conf_flags, - &inptr, &sti->outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + ret = sti_call(sti, sti->inq_conf, &default_conf_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -126,7 +134,8 @@ static const struct sti_font_flags default_font_flags = { void sti_putc(struct sti_struct *sti, int c, int y, int x) { - struct sti_font_inptr inptr = { + struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; + struct sti_font_inptr inptr_default = { .font_start_addr= STI_PTR(sti->font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), @@ -134,14 +143,15 @@ sti_putc(struct sti_struct *sti, int c, int y, int x) .dest_x = x * sti->font_width, .dest_y = y * sti->font_height, }; - struct sti_font_outptr outptr = { 0, }; + struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->font_unpmv, &default_font_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->font_unpmv, &default_font_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -156,7 +166,8 @@ void sti_set(struct sti_struct *sti, int src_y, int src_x, int height, int width, u8 color) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = color, .bg_color = color, .src_x = src_x, @@ -166,14 +177,15 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, .width = width, .height = height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -182,7 +194,8 @@ void sti_clear(struct sti_struct *sti, int src_y, int src_x, int height, int width, int c) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), .src_x = src_x * sti->font_width, @@ -192,14 +205,15 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -212,7 +226,8 @@ void sti_bmove(struct sti_struct *sti, int src_y, int src_x, int dst_y, int dst_x, int height, int width) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .src_x = src_x * sti->font_width, .src_y = src_y * sti->font_height, .dest_x = dst_x * sti->font_width, @@ -220,14 +235,15 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &default_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &default_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -284,7 +300,7 @@ __setup("sti=", sti_setup); -static char *font_name[MAX_STI_ROMS] = { "VGA8x16", }; +static char *font_name[MAX_STI_ROMS]; static int font_index[MAX_STI_ROMS], font_height[MAX_STI_ROMS], font_width[MAX_STI_ROMS]; @@ -389,10 +405,10 @@ static void sti_dump_outptr(struct sti_struct *sti) "%d used bits\n" "%d planes\n" "attributes %08x\n", - sti->outptr.bits_per_pixel, - sti->outptr.bits_used, - sti->outptr.planes, - sti->outptr.attributes)); + sti->sti_data->inq_outptr.bits_per_pixel, + sti->sti_data->inq_outptr.bits_used, + sti->sti_data->inq_outptr.planes, + sti->sti_data->inq_outptr.attributes)); } static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, @@ -402,24 +418,21 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, struct sti_glob_cfg_ext *glob_cfg_ext; void *save_addr; void *sti_mem_addr; - const int save_addr_size = 1024; /* XXX */ - int i; + int i, size; - if (!sti->sti_mem_request) + if (sti->sti_mem_request < 256) sti->sti_mem_request = 256; /* STI default */ - glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); - glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); - save_addr = kzalloc(save_addr_size, GFP_KERNEL); - sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); + size = sizeof(struct sti_all_data) + sti->sti_mem_request - 256; - if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { - kfree(glob_cfg); - kfree(glob_cfg_ext); - kfree(save_addr); - kfree(sti_mem_addr); + sti->sti_data = kzalloc(size, STI_LOWMEM); + if (!sti->sti_data) return -ENOMEM; - } + + glob_cfg = &sti->sti_data->glob_cfg; + glob_cfg_ext = &sti->sti_data->glob_cfg_ext; + save_addr = &sti->sti_data->save_addr; + sti_mem_addr = &sti->sti_data->sti_mem_addr; glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); glob_cfg->save_addr = STI_PTR(save_addr); @@ -475,32 +488,31 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, return 0; } -#ifdef CONFIG_FB +#ifdef CONFIG_FONTS static struct sti_cooked_font * sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { - const struct font_desc *fbfont; + const struct font_desc *fbfont = NULL; unsigned int size, bpc; void *dest; struct sti_rom_font *nf; struct sti_cooked_font *cooked_font; - if (!fbfont_name || !strlen(fbfont_name)) - return NULL; - fbfont = find_font(fbfont_name); + if (fbfont_name && strlen(fbfont_name)) + fbfont = find_font(fbfont_name); if (!fbfont) fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); if (!fbfont) return NULL; - DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n", - fbfont->width, fbfont->height, fbfont->name)); + pr_info("STI selected %dx%d framebuffer font %s for sticon\n", + fbfont->width, fbfont->height, fbfont->name); bpc = ((fbfont->width+7)/8) * fbfont->height; size = bpc * 256; size += sizeof(struct sti_rom_font); - nf = kzalloc(size, GFP_KERNEL); + nf = kzalloc(size, STI_LOWMEM); if (!nf) return NULL; @@ -637,7 +649,7 @@ static void *sti_bmode_font_raw(struct sti_cooked_font *f) unsigned char *n, *p, *q; int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - n = kzalloc (4*size, GFP_KERNEL); + n = kzalloc(4*size, STI_LOWMEM); if (!n) return NULL; p = n + 3; @@ -673,7 +685,7 @@ static struct sti_rom *sti_get_bmode_rom (unsigned long address) sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); size = (size+3) / 4; - raw = kmalloc(size, GFP_KERNEL); + raw = kmalloc(size, STI_LOWMEM); if (raw) { sti_bmode_rom_copy(address, size, raw); memmove (&raw->res004, &raw->type[0], 0x3c); @@ -707,7 +719,7 @@ static struct sti_rom *sti_get_wmode_rom(unsigned long address) /* read the ROM size directly from the struct in ROM */ size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); - raw = kmalloc(size, GFP_KERNEL); + raw = kmalloc(size, STI_LOWMEM); if (raw) sti_rom_copy(address, size, raw); @@ -743,6 +755,10 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, address = (unsigned long) STI_PTR(raw); + pr_info("STI ROM supports 32 %sbit firmware functions.\n", + raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 + ? "and 64 " : ""); + sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); sti->block_move = address + (raw->block_move & 0x03ffffff); sti->init_graph = address + (raw->init_graph & 0x03ffffff); @@ -901,7 +917,8 @@ test_rom: sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); sti_dump_outptr(sti); - printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name ); + pr_info(" graphics card name: %s\n", + sti->sti_data->inq_outptr.dev_name); sti_roms[num_sti_roms] = sti; num_sti_roms++; @@ -1073,6 +1090,29 @@ struct sti_struct * sti_get_rom(unsigned int index) } EXPORT_SYMBOL(sti_get_rom); + +int sti_call(const struct sti_struct *sti, unsigned long func, + const void *flags, void *inptr, void *outptr, + struct sti_glob_cfg *glob_cfg) +{ + unsigned long _flags = STI_PTR(flags); + unsigned long _inptr = STI_PTR(inptr); + unsigned long _outptr = STI_PTR(outptr); + unsigned long _glob_cfg = STI_PTR(glob_cfg); + int ret; + +#ifdef CONFIG_64BIT + /* Check for overflow when using 32bit STI on 64bit kernel. */ + if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32, + "Out of 32bit-range pointers!")) + return -1; +#endif + + ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg); + + return ret; +} + 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/controlfb.c b/drivers/video/controlfb.c index 67b77b40aa7f..fdadef979238 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -471,8 +471,8 @@ try_again: /* Register with fbdev layer */ if (register_framebuffer(&p->info) < 0) return -ENXIO; - - printk(KERN_INFO "fb%d: control display adapter\n", p->info.node); + + fb_info(&p->info, "control display adapter\n"); return 0; } diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 57886787ead0..b0a950f36970 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1641,67 +1641,6 @@ static void cyberpro_common_resume(struct cfb_info *cfb) cyber2000fb_set_par(&cfb->fb); } -#ifdef CONFIG_ARCH_SHARK - -#include <mach/framebuffer.h> - -static int cyberpro_vl_probe(void) -{ - struct cfb_info *cfb; - int err = -ENOMEM; - - if (!request_mem_region(FB_START, FB_SIZE, "CyberPro2010")) - return err; - - cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010"); - if (!cfb) - goto failed_release; - - cfb->irq = -1; - cfb->region = ioremap(FB_START, FB_SIZE); - if (!cfb->region) - goto failed_ioremap; - - cfb->regs = cfb->region + MMIO_OFFSET; - cfb->fb.device = NULL; - cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET; - cfb->fb.fix.smem_start = FB_START; - - /* - * Bring up the hardware. This is expected to enable access - * to the linear memory region, and allow access to the memory - * mapped registers. Also, mem_ctl1 and mem_ctl2 must be - * initialised. - */ - cyber2000fb_writeb(0x18, 0x46e8, cfb); - cyber2000fb_writeb(0x01, 0x102, cfb); - cyber2000fb_writeb(0x08, 0x46e8, cfb); - cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb); - cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb); - - cfb->mclk_mult = 0xdb; - cfb->mclk_div = 0x54; - - err = cyberpro_common_probe(cfb); - if (err) - goto failed; - - if (int_cfb_info == NULL) - int_cfb_info = cfb; - - return 0; - -failed: - iounmap(cfb->region); -failed_ioremap: - cyberpro_free_fb_info(cfb); -failed_release: - release_mem_region(FB_START, FB_SIZE); - - return err; -} -#endif /* CONFIG_ARCH_SHARK */ - /* * PCI specific support. */ @@ -1871,11 +1810,6 @@ static void cyberpro_pci_remove(struct pci_dev *dev) iounmap(cfb->region); cyberpro_free_fb_info(cfb); - /* - * Ensure that the driver data is no longer - * valid. - */ - pci_set_drvdata(dev, NULL); if (cfb == int_cfb_info) int_cfb_info = NULL; @@ -1948,28 +1882,19 @@ static int __init cyber2000fb_init(void) cyber2000fb_setup(option); #endif -#ifdef CONFIG_ARCH_SHARK - err = cyberpro_vl_probe(); - if (!err) - ret = 0; -#endif -#ifdef CONFIG_PCI err = pci_register_driver(&cyberpro_driver); if (!err) ret = 0; -#endif return ret ? err : 0; } module_init(cyber2000fb_init); -#ifndef CONFIG_ARCH_SHARK static void __exit cyberpro_exit(void) { pci_unregister_driver(&cyberpro_driver); } module_exit(cyberpro_exit); -#endif MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index e030e17a83f2..a1d74dd11988 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -129,7 +129,6 @@ #define LCD_NUM_BUFFERS 2 -#define WSI_TIMEOUT 50 #define PALETTE_SIZE 256 #define CLK_MIN_DIV 2 @@ -1314,7 +1313,7 @@ static struct fb_ops da8xx_fb_ops = { static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) { - struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data; + struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev); struct fb_videomode *lcdc_info; int i; @@ -1336,7 +1335,7 @@ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = - device->dev.platform_data; + dev_get_platdata(&device->dev); static struct resource *lcdc_regs; struct lcd_ctrl_config *lcd_cfg; struct fb_videomode *lcdc_info; @@ -1548,7 +1547,7 @@ err_pm_runtime_disable: } #ifdef CONFIG_PM -struct lcdc_context { +static struct lcdc_context { u32 clk_enable; u32 ctrl; u32 dma_ctrl; @@ -1663,19 +1662,7 @@ static struct platform_driver da8xx_fb_driver = { .owner = THIS_MODULE, }, }; - -static int __init da8xx_fb_init(void) -{ - return platform_driver_register(&da8xx_fb_driver); -} - -static void __exit da8xx_fb_cleanup(void) -{ - platform_driver_unregister(&da8xx_fb_driver); -} - -module_init(da8xx_fb_init); -module_exit(da8xx_fb_cleanup); +module_platform_driver(da8xx_fb_driver); MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); MODULE_AUTHOR("Texas Instruments"); diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 7f9ff75d0db2..cd7c0df9f24b 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -108,8 +108,8 @@ static int efifb_setup(char *options) if (!*this_opt) continue; for (i = 0; i < M_UNKNOWN; i++) { - if (!strcmp(this_opt, efifb_dmi_list[i].optname) && - efifb_dmi_list[i].base != 0) { + if (efifb_dmi_list[i].base != 0 && + !strcmp(this_opt, efifb_dmi_list[i].optname)) { screen_info.lfb_base = efifb_dmi_list[i].base; screen_info.lfb_linelength = efifb_dmi_list[i].stride; screen_info.lfb_width = efifb_dmi_list[i].width; @@ -322,8 +322,7 @@ static int efifb_probe(struct platform_device *dev) printk(KERN_ERR "efifb: cannot register framebuffer\n"); goto err_fb_dealoc; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; err_fb_dealoc: diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index 28a837dfddd1..35a0f533f1a2 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c @@ -487,7 +487,7 @@ static void ep93xxfb_dealloc_videomem(struct fb_info *info) static int ep93xxfb_probe(struct platform_device *pdev) { - struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data; + struct ep93xxfb_mach_info *mach_info = dev_get_platdata(&pdev->dev); struct fb_info *info; struct ep93xx_fbi *fbi; struct resource *res; diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig index 1b035b2eb6b6..1129d0e9e640 100644 --- a/drivers/video/exynos/Kconfig +++ b/drivers/video/exynos/Kconfig @@ -16,6 +16,7 @@ if EXYNOS_VIDEO config EXYNOS_MIPI_DSI bool "EXYNOS MIPI DSI driver support." depends on ARCH_S5PV210 || ARCH_EXYNOS + select GENERIC_PHY help This enables support for MIPI-DSI device. @@ -29,7 +30,7 @@ config EXYNOS_LCD_S6E8AX0 config EXYNOS_DP bool "EXYNOS DP driver support" - depends on ARCH_EXYNOS + depends on OF && ARCH_EXYNOS default n help This enables support for DP device. diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 12bbede3b091..5e1a71580051 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -19,8 +19,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/of.h> - -#include <video/exynos_dp.h> +#include <linux/phy/phy.h> #include "exynos_dp_core.h" @@ -894,26 +893,17 @@ static void exynos_dp_hotplug(struct work_struct *work) dev_err(dp->dev, "unable to config video\n"); } -#ifdef CONFIG_OF -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) +static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) { struct device_node *dp_node = dev->of_node; - struct exynos_dp_platdata *pd; struct video_info *dp_video_config; - pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); - if (!pd) { - dev_err(dev, "memory allocation for pdata failed\n"); - return ERR_PTR(-ENOMEM); - } dp_video_config = devm_kzalloc(dev, sizeof(*dp_video_config), GFP_KERNEL); - if (!dp_video_config) { dev_err(dev, "memory allocation for video config failed\n"); return ERR_PTR(-ENOMEM); } - pd->video_info = dp_video_config; dp_video_config->h_sync_polarity = of_property_read_bool(dp_node, "hsync-active-high"); @@ -960,7 +950,7 @@ static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) return ERR_PTR(-EINVAL); } - return pd; + return dp_video_config; } static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) @@ -971,8 +961,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy"); if (!dp_phy_node) { - dev_err(dp->dev, "could not find dptx-phy node\n"); - return -ENODEV; + dp->phy = devm_phy_get(dp->dev, "dp"); + if (IS_ERR(dp->phy)) + return PTR_ERR(dp->phy); + else + return 0; } if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) { @@ -1003,48 +996,34 @@ err: static void exynos_dp_phy_init(struct exynos_dp_device *dp) { - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg |= dp->enable_mask; - __raw_writel(reg, dp->phy_addr); -} - -static void exynos_dp_phy_exit(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = __raw_readl(dp->phy_addr); - reg &= ~(dp->enable_mask); - __raw_writel(reg, dp->phy_addr); -} -#else -static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev) -{ - return NULL; -} - -static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp) -{ - return -EINVAL; -} - -static void exynos_dp_phy_init(struct exynos_dp_device *dp) -{ - return; + if (dp->phy) { + phy_power_on(dp->phy); + } else if (dp->phy_addr) { + u32 reg; + + reg = __raw_readl(dp->phy_addr); + reg |= dp->enable_mask; + __raw_writel(reg, dp->phy_addr); + } } static void exynos_dp_phy_exit(struct exynos_dp_device *dp) { - return; + if (dp->phy) { + phy_power_off(dp->phy); + } else if (dp->phy_addr) { + u32 reg; + + reg = __raw_readl(dp->phy_addr); + reg &= ~(dp->enable_mask); + __raw_writel(reg, dp->phy_addr); + } } -#endif /* CONFIG_OF */ static int exynos_dp_probe(struct platform_device *pdev) { struct resource *res; struct exynos_dp_device *dp; - struct exynos_dp_platdata *pdata; int ret = 0; @@ -1057,21 +1036,13 @@ static int exynos_dp_probe(struct platform_device *pdev) dp->dev = &pdev->dev; - if (pdev->dev.of_node) { - pdata = exynos_dp_dt_parse_pdata(&pdev->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); + dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); + if (IS_ERR(dp->video_info)) + return PTR_ERR(dp->video_info); - ret = exynos_dp_dt_parse_phydata(dp); - if (ret) - return ret; - } else { - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - } + ret = exynos_dp_dt_parse_phydata(dp); + if (ret) + return ret; dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { @@ -1095,15 +1066,7 @@ static int exynos_dp_probe(struct platform_device *pdev) INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); - dp->video_info = pdata->video_info; - - if (pdev->dev.of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } + exynos_dp_phy_init(dp); exynos_dp_init_dp(dp); @@ -1121,18 +1084,11 @@ static int exynos_dp_probe(struct platform_device *pdev) static int exynos_dp_remove(struct platform_device *pdev) { - struct exynos_dp_platdata *pdata = pdev->dev.platform_data; struct exynos_dp_device *dp = platform_get_drvdata(pdev); flush_work(&dp->hotplug_work); - if (pdev->dev.of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } + exynos_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); @@ -1143,20 +1099,13 @@ static int exynos_dp_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int exynos_dp_suspend(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); disable_irq(dp->irq); flush_work(&dp->hotplug_work); - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_exit(dp); - } else { - if (pdata->phy_exit) - pdata->phy_exit(); - } + exynos_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); @@ -1165,16 +1114,9 @@ static int exynos_dp_suspend(struct device *dev) static int exynos_dp_resume(struct device *dev) { - struct exynos_dp_platdata *pdata = dev->platform_data; struct exynos_dp_device *dp = dev_get_drvdata(dev); - if (dev->of_node) { - if (dp->phy_addr) - exynos_dp_phy_init(dp); - } else { - if (pdata->phy_init) - pdata->phy_init(); - } + exynos_dp_phy_init(dp); clk_prepare_enable(dp->clock); @@ -1203,7 +1145,7 @@ static struct platform_driver exynos_dp_driver = { .name = "exynos-dp", .owner = THIS_MODULE, .pm = &exynos_dp_pm_ops, - .of_match_table = of_match_ptr(exynos_dp_match), + .of_match_table = exynos_dp_match, }, }; diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 6c567bbf2fb8..607e36d0c147 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h @@ -13,6 +13,99 @@ #ifndef _EXYNOS_DP_CORE_H #define _EXYNOS_DP_CORE_H +#define DP_TIMEOUT_LOOP_COUNT 100 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum link_training_state { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + PLL_UNLOCKED, + PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + enum dp_irq_type { DP_IRQ_TYPE_HP_CABLE_IN, DP_IRQ_TYPE_HP_CABLE_OUT, @@ -20,6 +113,22 @@ enum dp_irq_type { DP_IRQ_TYPE_UNKNOWN, }; +struct video_info { + char *name; + + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; + + enum color_space color_space; + enum dynamic_range dynamic_range; + enum color_coefficient ycbcr_coeff; + enum color_depth color_depth; + + enum link_rate_type link_rate; + enum link_lane_count_type lane_count; +}; + struct link_train { int eq_loop; int cr_loop[4]; @@ -42,6 +151,7 @@ struct exynos_dp_device { struct video_info *video_info; struct link_train link_train; struct work_struct hotplug_work; + struct phy *phy; }; /* exynos_dp_reg.c */ diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 29d9d035c73a..b70da5052ff0 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c @@ -14,8 +14,6 @@ #include <linux/io.h> #include <linux/delay.h> -#include <video/exynos_dp.h> - #include "exynos_dp_core.h" #include "exynos_dp_reg.h" diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 32e540600f99..cee9602f9a7b 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -30,6 +30,7 @@ #include <linux/interrupt.h> #include <linux/kthread.h> #include <linux/notifier.h> +#include <linux/phy/phy.h> #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/err.h> @@ -140,7 +141,6 @@ static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim, static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) { - struct platform_device *pdev = to_platform_device(dsim->dev); struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv; struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev; @@ -156,8 +156,7 @@ static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); clk_enable(dsim->clock); @@ -373,6 +372,10 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) return ret; } + dsim->phy = devm_phy_get(&pdev->dev, "dsim"); + if (IS_ERR(dsim->phy)) + return PTR_ERR(dsim->phy); + dsim->clock = devm_clk_get(&pdev->dev, "dsim0"); if (IS_ERR(dsim->clock)) { dev_err(&pdev->dev, "failed to get dsim clock source\n"); @@ -439,8 +442,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); exynos_mipi_update_cfg(dsim); @@ -504,9 +506,8 @@ static int exynos_mipi_dsi_suspend(struct device *dev) if (client_drv && client_drv->suspend) client_drv->suspend(client_dev); - /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, false); + /* disable MIPI-DSI PHY. */ + phy_power_off(dsim->phy); clk_disable(dsim->clock); @@ -536,8 +537,7 @@ static int exynos_mipi_dsi_resume(struct device *dev) exynos_mipi_regulator_enable(dsim); /* enable MIPI-DSI PHY. */ - if (dsim->pd->phy_enable) - dsim->pd->phy_enable(pdev, true); + phy_power_on(dsim->phy); clk_enable(dsim->clock); diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 520fc9bd887b..85edabfdef5a 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -220,7 +220,7 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, case MIPI_DSI_DCS_LONG_WRITE: { unsigned int size, payload = 0; - INIT_COMPLETION(dsim_wr_comp); + reinit_completion(&dsim_wr_comp); size = data_size * 4; @@ -356,7 +356,7 @@ int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id, msleep(20); mutex_lock(&dsim->lock); - INIT_COMPLETION(dsim_rd_comp); + reinit_completion(&dsim_rd_comp); exynos_mipi_dsi_rd_tx_header(dsim, MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size); @@ -376,6 +376,7 @@ int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id, "data id %x is not supported current DSI spec.\n", data_id); + mutex_unlock(&dsim->lock); return -EINVAL; } @@ -667,7 +668,7 @@ int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim) default: dev_info(dsim->dev, "data lane is invalid.\n"); return -EINVAL; - }; + } exynos_mipi_dsi_sw_reset(dsim); exynos_mipi_dsi_func_reset(dsim); diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c index 27fc956166fa..6db9ebd042a3 100644 --- a/drivers/video/fb-puv3.c +++ b/drivers/video/fb-puv3.c @@ -713,9 +713,8 @@ static int unifb_probe(struct platform_device *dev) platform_set_drvdata(dev, info); platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM); - printk(KERN_INFO - "fb%d: Virtual frame buffer device, using %dM of video memory\n", - info->node, UNIFB_MEMSIZE >> 20); + fb_info(info, "Virtual frame buffer device, using %dM of video memory\n", + UNIFB_MEMSIZE >> 20); return 0; err2: fb_dealloc_cmap(&info->cmap); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index dacaf74256a3..cde461932760 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1108,14 +1108,16 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, case FBIOPUT_VSCREENINFO: if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; - if (!lock_fb_info(info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(info)) { + console_unlock(); + return -ENODEV; + } info->flags |= FBINFO_MISC_USEREVENT; ret = fb_set_var(info, &var); info->flags &= ~FBINFO_MISC_USEREVENT; - console_unlock(); unlock_fb_info(info); + console_unlock(); if (!ret && copy_to_user(argp, &var, sizeof(var))) ret = -EFAULT; break; @@ -1144,12 +1146,14 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, case FBIOPAN_DISPLAY: if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; - if (!lock_fb_info(info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(info)) { + console_unlock(); + return -ENODEV; + } ret = fb_pan_display(info, &var); - console_unlock(); unlock_fb_info(info); + console_unlock(); if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) return -EFAULT; break; @@ -1184,23 +1188,27 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, break; } event.data = &con2fb; - if (!lock_fb_info(info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(info)) { + console_unlock(); + return -ENODEV; + } event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); - console_unlock(); unlock_fb_info(info); + console_unlock(); break; case FBIOBLANK: - if (!lock_fb_info(info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(info)) { + console_unlock(); + return -ENODEV; + } info->flags |= FBINFO_MISC_USEREVENT; ret = fb_blank(info, arg); info->flags &= ~FBINFO_MISC_USEREVENT; - console_unlock(); unlock_fb_info(info); + console_unlock(); break; default: if (!lock_fb_info(info)) @@ -1660,12 +1668,15 @@ static int do_register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; - if (!lock_fb_info(fb_info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(fb_info)) { + console_unlock(); + return -ENODEV; + } + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); - console_unlock(); unlock_fb_info(fb_info); + console_unlock(); return 0; } @@ -1678,13 +1689,16 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) return -EINVAL; - if (!lock_fb_info(fb_info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(fb_info)) { + console_unlock(); + return -ENODEV; + } + event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); - console_unlock(); unlock_fb_info(fb_info); + console_unlock(); if (ret) return -EINVAL; @@ -1916,6 +1930,9 @@ int fb_get_options(const char *name, char **option) options = opt + name_len + 1; } } + /* No match, pass global option */ + if (!options && option && fb_mode_option) + options = kstrdup(fb_mode_option, GFP_KERNEL); if (options && !strncmp(options, "off", 3)) retval = 1; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index ef476b02fbe5..53444ac19fe0 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -177,9 +177,12 @@ static ssize_t store_modes(struct device *device, if (i * sizeof(struct fb_videomode) != count) return -EINVAL; - if (!lock_fb_info(fb_info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(fb_info)) { + console_unlock(); + return -ENODEV; + } + list_splice(&fb_info->modelist, &old_list); fb_videomode_to_modelist((const struct fb_videomode *)buf, i, &fb_info->modelist); @@ -189,8 +192,8 @@ static ssize_t store_modes(struct device *device, } else fb_destroy_modelist(&old_list); - console_unlock(); unlock_fb_info(fb_info); + console_unlock(); return 0; } @@ -404,12 +407,16 @@ static ssize_t store_fbstate(struct device *device, state = simple_strtoul(buf, &last, 0); - if (!lock_fb_info(fb_info)) - return -ENODEV; console_lock(); + if (!lock_fb_info(fb_info)) { + console_unlock(); + return -ENODEV; + } + fb_set_suspend(fb_info, (int)state); - console_unlock(); + unlock_fb_info(fb_info); + console_unlock(); return count; } diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 6d2744794dd1..4c4ffa61ae26 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -1035,8 +1035,6 @@ static int ffb_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index c99c9671302b..e69d47af9932 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -289,7 +289,7 @@ static int fm2fb_probe(struct zorro_dev *z, const struct zorro_device_id *id) zorro_release_device(z); return -EINVAL; } - printk("fb%d: %s frame buffer device\n", info->node, fb_fix.id); + fb_info(info, "%s frame buffer device\n", fb_fix.id); return 0; } diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 6dd72250111e..e8758b9c3bcc 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -31,6 +31,8 @@ #include <linux/uaccess.h> #include <linux/vmalloc.h> #include <linux/spinlock.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <sysdev/fsl_soc.h> #include <linux/fsl-diu-fb.h> @@ -1102,7 +1104,7 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor) fsl_diu_load_cursor_image(info, image, bg, fg, cursor->image.width, cursor->image.height); - }; + } /* * Show or hide the cursor. The cursor data is always stored in the diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index ceab37020fff..4c7cb368a9dc 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1236,9 +1236,9 @@ static int gbefb_probe(struct platform_device *p_dev) platform_set_drvdata(p_dev, info); gbefb_create_sysfs(&p_dev->dev); - printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n", - info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE, - gbe_mem_size >> 10); + fb_info(info, "%s rev %d @ 0x%08x using %dkB memory\n", + info->fix.id, gbe_revision, (unsigned)GBE_BASE, + gbe_mem_size >> 10); return 0; diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index ebbaada7b941..2794ba11f332 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -357,7 +357,7 @@ static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; } pci_set_drvdata(pdev, info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; err: @@ -399,7 +399,6 @@ static void gx1fb_remove(struct pci_dev *pdev) release_mem_region(gx1_gx_base() + 0x8300, 0x100); fb_dealloc_cmap(&info->cmap); - pci_set_drvdata(pdev, NULL); framebuffer_release(info); } diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 19f0c1add747..1790f14bab15 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -423,7 +423,7 @@ static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; } pci_set_drvdata(pdev, info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; err: @@ -471,7 +471,6 @@ static void gxfb_remove(struct pci_dev *pdev) pci_release_region(pdev, 1); fb_dealloc_cmap(&info->cmap); - pci_set_drvdata(pdev, NULL); framebuffer_release(info); } diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 4dd7b5566962..9e1d19d673a1 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c @@ -555,8 +555,7 @@ static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; } pci_set_drvdata(pdev, info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; @@ -606,7 +605,6 @@ static void lxfb_remove(struct pci_dev *pdev) pci_release_region(pdev, 3); fb_dealloc_cmap(&info->cmap); - pci_set_drvdata(pdev, NULL); framebuffer_release(info); } diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c index 861109e7de1b..c078701f15f6 100644 --- a/drivers/video/grvga.c +++ b/drivers/video/grvga.c @@ -496,7 +496,6 @@ static int grvga_probe(struct platform_device *dev) return 0; free_mem: - dev_set_drvdata(&dev->dev, NULL); if (grvga_fix_addr) iounmap((void *)virtual_start); else @@ -530,7 +529,6 @@ static int grvga_remove(struct platform_device *device) kfree((void *)info->screen_base); framebuffer_release(info); - dev_set_drvdata(&device->dev, NULL); } return 0; @@ -557,19 +555,7 @@ static struct platform_driver grvga_driver = { .remove = grvga_remove, }; - -static int __init grvga_init(void) -{ - return platform_driver_register(&grvga_driver); -} - -static void __exit grvga_exit(void) -{ - platform_driver_unregister(&grvga_driver); -} - -module_init(grvga_init); -module_exit(grvga_exit); +module_platform_driver(grvga_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Aeroflex Gaisler"); diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c index c35663f6a54a..135d78a02588 100644 --- a/drivers/video/gxt4500.c +++ b/drivers/video/gxt4500.c @@ -698,8 +698,7 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "gxt4500: cannot register framebuffer\n"); goto err_free_cmap; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c index 59d23181fdb0..f64120ec9192 100644 --- a/drivers/video/hecubafb.c +++ b/drivers/video/hecubafb.c @@ -261,9 +261,8 @@ static int hecubafb_probe(struct platform_device *dev) goto err_fbreg; platform_set_drvdata(dev, info); - printk(KERN_INFO - "fb%d: Hecuba frame buffer device, using %dK of video memory\n", - info->node, videomemorysize >> 10); + fb_info(info, "Hecuba frame buffer device, using %dK of video memory\n", + videomemorysize >> 10); /* this inits the dpy */ retval = par->board->init(par); @@ -305,19 +304,7 @@ static struct platform_driver hecubafb_driver = { .name = "hecubafb", }, }; - -static int __init hecubafb_init(void) -{ - return platform_driver_register(&hecubafb_driver); -} - -static void __exit hecubafb_exit(void) -{ - platform_driver_unregister(&hecubafb_driver); -} - -module_init(hecubafb_init); -module_exit(hecubafb_exit); +module_platform_driver(hecubafb_driver); MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller"); MODULE_AUTHOR("Jaya Kumar"); diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 1e9e2d819d1f..5ff9fe2116a4 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -586,8 +586,7 @@ static int hgafb_probe(struct platform_device *pdev) return -EINVAL; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); platform_set_drvdata(pdev, info); return 0; } diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index c2414d6ab646..a648d5186c6e 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -405,8 +405,7 @@ static int hitfb_probe(struct platform_device *dev) platform_set_drvdata(dev, info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index b802f93cef5d..a1b7e5fa9b09 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -298,8 +298,7 @@ static int hpfb_init_one(unsigned long phys_base, unsigned long virt_base) if (ret < 0) goto dealloc_cmap; - printk(KERN_INFO "fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id); return 0; diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c index 8ac99b87c07e..130708f96430 100644 --- a/drivers/video/hyperv_fb.c +++ b/drivers/video/hyperv_fb.c @@ -575,6 +575,10 @@ static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } +static int hvfb_blank(int blank, struct fb_info *info) +{ + return 1; /* get fb_blank to set the colormap to all black */ +} static struct fb_ops hvfb_ops = { .owner = THIS_MODULE, @@ -584,6 +588,7 @@ static struct fb_ops hvfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_blank = hvfb_blank, }; @@ -795,12 +800,21 @@ static int hvfb_remove(struct hv_device *hdev) } +static DEFINE_PCI_DEVICE_TABLE(pci_stub_id_table) = { + { + .vendor = PCI_VENDOR_ID_MICROSOFT, + .device = PCI_DEVICE_ID_HYPERV_VIDEO, + }, + { /* end of list */ } +}; + static const struct hv_vmbus_device_id id_table[] = { /* Synthetic Video Device GUID */ {HV_SYNTHVID_GUID}, {} }; +MODULE_DEVICE_TABLE(pci, pci_stub_id_table); MODULE_DEVICE_TABLE(vmbus, id_table); static struct hv_driver hvfb_drv = { @@ -810,14 +824,43 @@ static struct hv_driver hvfb_drv = { .remove = hvfb_remove, }; +static int hvfb_pci_stub_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + return 0; +} + +static void hvfb_pci_stub_remove(struct pci_dev *pdev) +{ +} + +static struct pci_driver hvfb_pci_stub_driver = { + .name = KBUILD_MODNAME, + .id_table = pci_stub_id_table, + .probe = hvfb_pci_stub_probe, + .remove = hvfb_pci_stub_remove, +}; static int __init hvfb_drv_init(void) { - return vmbus_driver_register(&hvfb_drv); + int ret; + + ret = vmbus_driver_register(&hvfb_drv); + if (ret != 0) + return ret; + + ret = pci_register_driver(&hvfb_pci_stub_driver); + if (ret != 0) { + vmbus_driver_unregister(&hvfb_drv); + return ret; + } + + return 0; } static void __exit hvfb_drv_exit(void) { + pci_unregister_driver(&hvfb_pci_stub_driver); vmbus_driver_unregister(&hvfb_drv); } diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c index 6c4838818950..ca7c9df193b0 100644 --- a/drivers/video/i740fb.c +++ b/drivers/video/i740fb.c @@ -203,8 +203,7 @@ static int i740fb_release(struct fb_info *info, int user) mutex_lock(&(par->open_lock)); if (par->ref_count == 0) { - printk(KERN_ERR "fb%d: release called with zero refcount\n", - info->node); + fb_err(info, "release called with zero refcount\n"); mutex_unlock(&(par->open_lock)); return -EINVAL; } @@ -1067,7 +1066,7 @@ static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) par->has_sgram = !((tmp & DRAM_RAS_TIMING) || (tmp & DRAM_RAS_PRECHARGE)); - printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node, + fb_info(info, "Intel740 on %s, %ld KB %s\n", pci_name(dev), info->screen_size >> 10, par->has_sgram ? "SGRAM" : "SDRAM"); @@ -1143,8 +1142,7 @@ static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) goto err_reg_framebuffer; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); pci_set_drvdata(dev, info); #ifdef CONFIG_MTRR if (mtrr) { @@ -1194,7 +1192,6 @@ static void i740fb_remove(struct pci_dev *dev) pci_iounmap(dev, info->screen_base); pci_release_regions(dev); /* pci_disable_device(dev); */ - pci_set_drvdata(dev, NULL); framebuffer_release(info); } } diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 4ce3438ade6f..bb674e431741 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -2011,9 +2011,7 @@ static int i810fb_init_pci(struct pci_dev *dev, struct fb_info *info; struct i810fb_par *par = NULL; struct fb_videomode mode; - int i, err = -1, vfreq, hfreq, pixclock; - - i = 0; + int err = -1, vfreq, hfreq, pixclock; info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev); if (!info) @@ -2129,7 +2127,6 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev) unregister_framebuffer(info); i810fb_release_resource(info, par); - pci_set_drvdata(dev, NULL); printk("cleanup_module: unloaded i810 framebuffer device\n"); } diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 79cbfa7d1a9b..486f18897414 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -360,9 +360,8 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par) if (register_framebuffer(info) < 0) return 0; - printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n", - info->node, info->fix.id, - par->frame_buffer_phys, info->fix.smem_len >> 20); + fb_info(info, "%s frame buffer device at 0x%08lx [%dMB VRAM]\n", + info->fix.id, par->frame_buffer_phys, info->fix.smem_len >> 20); iga_blank_border(par); return 1; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index d5220cc90e93..aae10ce74f14 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1461,8 +1461,8 @@ static void init_imstt(struct fb_info *info) } tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8; - printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n", - info->node, info->fix.id, info->fix.smem_len >> 20, tmp); + fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n", + info->fix.id, info->fix.smem_len >> 20, tmp); } static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 38733ac2b698..44ee678481d5 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -755,7 +755,7 @@ static int imxfb_resume(struct platform_device *dev) static int imxfb_init_fbinfo(struct platform_device *pdev) { - struct imx_fb_platform_data *pdata = pdev->dev.platform_data; + struct imx_fb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct fb_info *info = dev_get_drvdata(&pdev->dev); struct imxfb_info *fbi = info->par; struct device_node *np; @@ -877,7 +877,7 @@ static int imxfb_probe(struct platform_device *pdev) if (!res) return -ENODEV; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev); if (!info) @@ -1066,7 +1066,7 @@ static int imxfb_remove(struct platform_device *pdev) #endif unregister_framebuffer(info); - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (pdata && pdata->exit) pdata->exit(fbi->pdev); diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 8209e46c5d28..b847d530471a 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -931,8 +931,6 @@ static void intelfb_pci_unregister(struct pci_dev *pdev) return; cleanup(dinfo); - - pci_set_drvdata(pdev, NULL); } /*************************************************************** diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c index 2c49112fdd6c..87790e9644d0 100644 --- a/drivers/video/jz4740_fb.c +++ b/drivers/video/jz4740_fb.c @@ -99,9 +99,9 @@ #define JZ_LCD_CTRL_BPP_15_16 0x4 #define JZ_LCD_CTRL_BPP_18_24 0x5 -#define JZ_LCD_CMD_SOF_IRQ BIT(15) -#define JZ_LCD_CMD_EOF_IRQ BIT(16) -#define JZ_LCD_CMD_ENABLE_PAL BIT(12) +#define JZ_LCD_CMD_SOF_IRQ BIT(31) +#define JZ_LCD_CMD_EOF_IRQ BIT(30) +#define JZ_LCD_CMD_ENABLE_PAL BIT(28) #define JZ_LCD_SYNC_MASK 0x3ff @@ -471,7 +471,7 @@ static int jzfb_set_par(struct fb_info *info) writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); if (!jzfb->is_enabled) - clk_disable(jzfb->ldclk); + clk_disable_unprepare(jzfb->ldclk); mutex_unlock(&jzfb->lock); @@ -485,7 +485,7 @@ static void jzfb_enable(struct jzfb *jzfb) { uint32_t ctrl; - clk_enable(jzfb->ldclk); + clk_prepare_enable(jzfb->ldclk); jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); @@ -514,7 +514,7 @@ static void jzfb_disable(struct jzfb *jzfb) jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); - clk_disable(jzfb->ldclk); + clk_disable_unprepare(jzfb->ldclk); } static int jzfb_blank(int blank_mode, struct fb_info *info) @@ -693,7 +693,7 @@ static int jzfb_probe(struct platform_device *pdev) fb_alloc_cmap(&fb->cmap, 256, 0); - clk_enable(jzfb->ldclk); + clk_prepare_enable(jzfb->ldclk); jzfb->is_enabled = 1; writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); @@ -763,7 +763,7 @@ static int jzfb_suspend(struct device *dev) static int jzfb_resume(struct device *dev) { struct jzfb *jzfb = dev_get_drvdata(dev); - clk_enable(jzfb->ldclk); + clk_prepare_enable(jzfb->ldclk); mutex_lock(&jzfb->lock); if (jzfb->is_enabled) @@ -798,18 +798,7 @@ static struct platform_driver jzfb_driver = { .pm = JZFB_PM_OPS, }, }; - -static int __init jzfb_init(void) -{ - return platform_driver_register(&jzfb_driver); -} -module_init(jzfb_init); - -static void __exit jzfb_exit(void) -{ - platform_driver_unregister(&jzfb_driver); -} -module_exit(jzfb_exit); +module_platform_driver(jzfb_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index 6157f74ac600..65041e15fd59 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -623,17 +623,16 @@ static int kyrofb_ioctl(struct fb_info *info, "command instead.\n"); return -EINVAL; } - break; case KYRO_IOCTL_UVSTRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride))) return -EFAULT; break; case KYRO_IOCTL_STRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride))) return -EFAULT; break; case KYRO_IOCTL_OVERLAY_OFFSET: - if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset))) return -EFAULT; break; } @@ -736,10 +735,10 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (register_framebuffer(info) < 0) goto out_unmap; - printk("fb%d: %s frame buffer device, at %dx%d@%d using %ldk/%ldk of VRAM\n", - info->node, info->fix.id, info->var.xres, - info->var.yres, info->var.bits_per_pixel, size >> 10, - (unsigned long)info->fix.smem_len >> 10); + fb_info(info, "%s frame buffer device, at %dx%d@%d using %ldk/%ldk of VRAM\n", + info->fix.id, + info->var.xres, info->var.yres, info->var.bits_per_pixel, + size >> 10, (unsigned long)info->fix.smem_len >> 10); pci_set_drvdata(pdev, info); @@ -779,7 +778,6 @@ static void kyrofb_remove(struct pci_dev *pdev) #endif unregister_framebuffer(info); - pci_set_drvdata(pdev, NULL); framebuffer_release(info); } diff --git a/drivers/video/leo.c b/drivers/video/leo.c index b17f5009a436..2c7f7d479fe2 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -469,7 +469,7 @@ static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) default: continue; - }; + } sbus_writel(0x5800 + j, &lx_krn->krn_type); sbus_writel(wi->wi_values[0], &lx_krn->krn_value); } @@ -648,8 +648,6 @@ static int leo_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index 080c35b34bbb..b670cbda38e3 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -17,10 +17,6 @@ #include <asm/setup.h> #endif -#ifdef CONFIG_MIPS -#include <asm/bootinfo.h> -#endif - static bool nologo; module_param(nologo, bool, 0); MODULE_PARM_DESC(nologo, "Disables startup logo"); diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index fe01add3700e..5bd2eb8d4f39 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -913,8 +913,7 @@ static int __init macfb_init(void) if (err) goto fail_dealloc; - pr_info("fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); + fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id); return 0; diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 1717623aabc0..a01147fdf270 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -494,7 +494,7 @@ static int m1064_compute(void* out, struct my_timming* m) { if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); - }; + } CRITEND @@ -639,7 +639,7 @@ static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags, if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); - }; + } if (!clk) printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A'); selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK; diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 9a44cec394b5..195ad7cac1ba 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -473,7 +473,7 @@ static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout) if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40) break; udelay(10); - }; + } if (!tmout) printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n"); diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 245652911650..87c64ff4546c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1893,14 +1893,12 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b) if (register_framebuffer(&minfo->fbcon) < 0) { goto failVideoIO; } - printk("fb%d: %s frame buffer device\n", - minfo->fbcon.node, minfo->fbcon.fix.id); + fb_info(&minfo->fbcon, "%s frame buffer device\n", minfo->fbcon.fix.id); /* there is no console on this fb... but we have to initialize hardware * until someone tells me what is proper thing to do */ if (!minfo->initialized) { - printk(KERN_INFO "fb%d: initializing hardware\n", - minfo->fbcon.node); + fb_info(&minfo->fbcon, "initializing hardware\n"); /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var * already before, so register_framebuffer works correctly. */ vesafb_defined.activate |= FB_ACTIVATE_FORCE; diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index fd2897455696..ee41a0f276b2 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -1295,19 +1295,7 @@ static struct i2c_driver maven_driver={ .id_table = maven_id, }; -static int __init matroxfb_maven_init(void) -{ - return i2c_add_driver(&maven_driver); -} - -static void __exit matroxfb_maven_exit(void) -{ - i2c_del_driver(&maven_driver); -} - +module_i2c_driver(maven_driver); MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>"); MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver"); MODULE_LICENSE("GPL"); -module_init(matroxfb_maven_init); -module_exit(matroxfb_maven_exit); -/* we do not have __setup() yet */ diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index 91c59c9fb082..0cd4c3318511 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c @@ -781,7 +781,6 @@ rel_reg: irqdisp: irq_dispose_mapping(par->irq); fbrel: - dev_set_drvdata(dev, NULL); framebuffer_release(info); return ret; } @@ -814,7 +813,6 @@ static int of_platform_mb862xx_remove(struct platform_device *ofdev) iounmap(par->mmio_base); iounmap(par->fb_base); - dev_set_drvdata(&ofdev->dev, NULL); release_mem_region(par->res->start, res_size); framebuffer_release(fbi); return 0; @@ -1157,7 +1155,6 @@ static void mb862xx_pci_remove(struct pci_dev *pdev) device_remove_file(&pdev->dev, &dev_attr_dispregs); - pci_set_drvdata(pdev, NULL); unregister_framebuffer(fbi); fb_dealloc_cmap(&fbi->cmap); diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 0c1a874ffd2b..f0a5392f5fd3 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -890,7 +890,7 @@ static int mbxfb_probe(struct platform_device *dev) dev_dbg(&dev->dev, "mbxfb_probe\n"); - pdata = dev->dev.platform_data; + pdata = dev_get_platdata(&dev->dev); if (!pdata) { dev_err(&dev->dev, "platform data is required\n"); return -EINVAL; @@ -976,7 +976,7 @@ static int mbxfb_probe(struct platform_device *dev) platform_set_drvdata(dev, fbi); - printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node); + fb_info(fbi, "mbx frame buffer device\n"); if (mfbi->platform_probe) mfbi->platform_probe(fbi); diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c index f30150d71be9..195cc2db4c2c 100644 --- a/drivers/video/metronomefb.c +++ b/drivers/video/metronomefb.c @@ -690,7 +690,8 @@ static int metronomefb_probe(struct platform_device *dev) goto err_csum_table; } - if (board->setup_irq(info)) + retval = board->setup_irq(info); + if (retval) goto err_csum_table; retval = metronome_init_regs(par); @@ -769,23 +770,11 @@ static struct platform_driver metronomefb_driver = { .name = "metronomefb", }, }; - -static int __init metronomefb_init(void) -{ - return platform_driver_register(&metronomefb_driver); -} - -static void __exit metronomefb_exit(void) -{ - platform_driver_unregister(&metronomefb_driver); -} +module_platform_driver(metronomefb_driver); module_param(user_wfm_size, uint, 0); MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size"); -module_init(metronomefb_init); -module_exit(metronomefb_exit); - MODULE_DESCRIPTION("fbdev driver for Metronome controller"); MODULE_AUTHOR("Jaya Kumar"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c index 84de2632857a..b563b920f159 100644 --- a/drivers/video/mmp/core.c +++ b/drivers/video/mmp/core.c @@ -30,7 +30,7 @@ static struct mmp_overlay *path_get_overlay(struct mmp_path *path, { if (path && overlay_id < path->overlay_num) return &path->overlays[overlay_id]; - return 0; + return NULL; } static int path_check_status(struct mmp_path *path) @@ -173,7 +173,7 @@ struct mmp_path *mmp_register_path(struct mmp_path_info *info) + sizeof(struct mmp_overlay) * info->overlay_num; path = kzalloc(size, GFP_KERNEL); if (!path) - goto failed; + return NULL; /* path set */ mutex_init(&path->access_ok); @@ -219,11 +219,6 @@ struct mmp_path *mmp_register_path(struct mmp_path_info *info) mutex_unlock(&disp_lock); return path; - -failed: - kfree(path); - mutex_unlock(&disp_lock); - return NULL; } EXPORT_SYMBOL_GPL(mmp_register_path); diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c index 4ab95b8daed3..7ab31eb76a8c 100644 --- a/drivers/video/mmp/fb/mmpfb.c +++ b/drivers/video/mmp/fb/mmpfb.c @@ -392,12 +392,29 @@ static int var_update(struct fb_info *info) return 0; } +static void mmpfb_set_win(struct fb_info *info) +{ + struct mmpfb_info *fbi = info->par; + struct fb_var_screeninfo *var = &info->var; + struct mmp_win win; + u32 stride; + + memset(&win, 0, sizeof(win)); + win.xsrc = win.xdst = fbi->mode.xres; + win.ysrc = win.ydst = fbi->mode.yres; + win.pix_fmt = fbi->pix_fmt; + stride = pixfmt_to_stride(win.pix_fmt); + win.pitch[0] = var->xres_virtual * stride; + win.pitch[1] = win.pitch[2] = + (stride == 1) ? (var->xres_virtual >> 1) : 0; + mmp_overlay_set_win(fbi->overlay, &win); +} + static int mmpfb_set_par(struct fb_info *info) { struct mmpfb_info *fbi = info->par; struct fb_var_screeninfo *var = &info->var; struct mmp_addr addr; - struct mmp_win win; struct mmp_mode mode; int ret; @@ -409,11 +426,8 @@ static int mmpfb_set_par(struct fb_info *info) fbmode_to_mmpmode(&mode, &fbi->mode, fbi->output_fmt); mmp_path_set_mode(fbi->path, &mode); - memset(&win, 0, sizeof(win)); - win.xsrc = win.xdst = fbi->mode.xres; - win.ysrc = win.ydst = fbi->mode.yres; - win.pix_fmt = fbi->pix_fmt; - mmp_overlay_set_win(fbi->overlay, &win); + /* set window related info */ + mmpfb_set_win(info); /* set address always */ memset(&addr, 0, sizeof(addr)); @@ -427,16 +441,12 @@ static int mmpfb_set_par(struct fb_info *info) static void mmpfb_power(struct mmpfb_info *fbi, int power) { struct mmp_addr addr; - struct mmp_win win; struct fb_var_screeninfo *var = &fbi->fb_info->var; /* for power on, always set address/window again */ if (power) { - memset(&win, 0, sizeof(win)); - win.xsrc = win.xdst = fbi->mode.xres; - win.ysrc = win.ydst = fbi->mode.yres; - win.pix_fmt = fbi->pix_fmt; - mmp_overlay_set_win(fbi->overlay, &win); + /* set window related info */ + mmpfb_set_win(fbi->fb_info); /* set address always */ memset(&addr, 0, sizeof(addr)); diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c index 6ac755270ab4..8621a9f2bdcc 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.c +++ b/drivers/video/mmp/hw/mmp_ctrl.c @@ -53,15 +53,14 @@ static irqreturn_t ctrl_handle_irq(int irq, void *dev_id) tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR); if (tmp & isr) writel_relaxed(~isr, ctrl->reg_base + SPU_IRQ_ISR); - } while ((isr = readl(ctrl->reg_base + SPU_IRQ_ISR)) & imask); + } while ((isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR)) & imask); return IRQ_HANDLED; } static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt) { - u32 link_config = path_to_path_plat(overlay->path)->link_config; - u32 rbswap, uvswap = 0, yuvswap = 0, + u32 rbswap = 0, uvswap = 0, yuvswap = 0, csc_en = 0, val = 0, vid = overlay_is_vid(overlay); @@ -71,27 +70,23 @@ static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt) case PIXFMT_RGB888PACK: case PIXFMT_RGB888UNPACK: case PIXFMT_RGBA888: - rbswap = !(link_config & 0x1); + rbswap = 1; break; case PIXFMT_VYUY: case PIXFMT_YVU422P: case PIXFMT_YVU420P: - rbswap = link_config & 0x1; uvswap = 1; break; case PIXFMT_YUYV: - rbswap = link_config & 0x1; yuvswap = 1; break; default: - rbswap = link_config & 0x1; break; } switch (pix_fmt) { case PIXFMT_RGB565: case PIXFMT_BGR565: - val = 0; break; case PIXFMT_RGB1555: case PIXFMT_BGR1555: @@ -147,17 +142,27 @@ static void dmafetch_set_fmt(struct mmp_overlay *overlay) static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win) { struct lcd_regs *regs = path_regs(overlay->path); - u32 pitch; /* assert win supported */ memcpy(&overlay->win, win, sizeof(struct mmp_win)); mutex_lock(&overlay->access_ok); - pitch = win->xsrc * pixfmt_to_stride(win->pix_fmt); - writel_relaxed(pitch, ®s->g_pitch); - writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->g_size); - writel_relaxed((win->ydst << 16) | win->xdst, ®s->g_size_z); - writel_relaxed(0, ®s->g_start); + + if (overlay_is_vid(overlay)) { + writel_relaxed(win->pitch[0], ®s->v_pitch_yc); + writel_relaxed(win->pitch[2] << 16 | + win->pitch[1], ®s->v_pitch_uv); + + writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->v_size); + writel_relaxed((win->ydst << 16) | win->xdst, ®s->v_size_z); + writel_relaxed(win->ypos << 16 | win->xpos, ®s->v_start); + } else { + writel_relaxed(win->pitch[0], ®s->g_pitch); + + writel_relaxed((win->ysrc << 16) | win->xsrc, ®s->g_size); + writel_relaxed((win->ydst << 16) | win->xdst, ®s->g_size_z); + writel_relaxed(win->ypos << 16 | win->xpos, ®s->g_start); + } dmafetch_set_fmt(overlay); mutex_unlock(&overlay->access_ok); @@ -239,7 +244,13 @@ static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr) /* FIXME: assert addr supported */ memcpy(&overlay->addr, addr, sizeof(struct mmp_addr)); - writel(addr->phys[0], ®s->g_0); + + if (overlay_is_vid(overlay)) { + writel_relaxed(addr->phys[0], ®s->v_y0); + writel_relaxed(addr->phys[1], ®s->v_u0); + writel_relaxed(addr->phys[2], ®s->v_v0); + } else + writel_relaxed(addr->phys[0], ®s->g_0); return overlay->addr.phys[0]; } @@ -248,7 +259,8 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) { struct lcd_regs *regs = path_regs(path); u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div, - link_config = path_to_path_plat(path)->link_config; + link_config = path_to_path_plat(path)->link_config, + dsi_rbswap = path_to_path_plat(path)->link_config; /* FIXME: assert videomode supported */ memcpy(&path->mode, mode, sizeof(struct mmp_mode)); @@ -263,6 +275,12 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) tmp |= CFG_DUMB_ENA(1); writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id)); + /* interface rb_swap setting */ + tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) & + (~(CFG_INTFRBSWAP_MASK)); + tmp |= dsi_rbswap & CFG_INTFRBSWAP_MASK; + writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id)); + writel_relaxed((mode->yres << 16) | mode->xres, ®s->screen_active); writel_relaxed((mode->left_margin << 16) | mode->right_margin, ®s->screen_h_porch); @@ -370,20 +388,12 @@ static void path_set_default(struct mmp_path *path) * bus arbiter for faster read if not tv path; * 2.enable horizontal smooth filter; */ - if (PATH_PN == path->id) { - mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK - | CFG_ARBFAST_ENA(1); - tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); - tmp |= mask; - writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); - } else if (PATH_TV == path->id) { - mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK - | CFG_ARBFAST_ENA(1); - tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); - tmp &= ~mask; - tmp |= CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK; - writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); - } + mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | CFG_ARBFAST_ENA(1); + tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id)); + tmp |= mask; + if (PATH_TV == path->id) + tmp &= ~CFG_ARBFAST_ENA(1); + writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id)); } static int path_init(struct mmphw_path_plat *path_plat, @@ -419,6 +429,7 @@ static int path_init(struct mmphw_path_plat *path_plat, path_plat->path = path; path_plat->path_config = config->path_config; path_plat->link_config = config->link_config; + path_plat->dsi_rbswap = config->dsi_rbswap; path_set_default(path); kfree(path_info); diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h index edd2002b0e99..53301cfdb1ae 100644 --- a/drivers/video/mmp/hw/mmp_ctrl.h +++ b/drivers/video/mmp/hw/mmp_ctrl.h @@ -163,6 +163,8 @@ struct lcd_regs { #define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\ ((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV)) +#define intf_rbswap_ctrl(id) ((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \ + PN2_IOPAD_CONTROL) : LCD_TOP_CTRL) /* dither configure */ #ifdef CONFIG_CPU_PXA988 @@ -615,6 +617,8 @@ struct lcd_regs { #define LCD_SPU_DUMB_CTRL 0x01B8 #define CFG_DUMBMODE(mode) ((mode)<<28) #define CFG_DUMBMODE_MASK 0xF0000000 +#define CFG_INTFRBSWAP(mode) ((mode)<<24) +#define CFG_INTFRBSWAP_MASK 0x0F000000 #define CFG_LCDGPIO_O(data) ((data)<<20) #define CFG_LCDGPIO_O_MASK 0x0FF00000 #define CFG_LCDGPIO_ENA(gpio) ((gpio)<<12) @@ -1427,6 +1431,7 @@ struct mmphw_path_plat { struct mmp_path *path; u32 path_config; u32 link_config; + u32 dsi_rbswap; }; /* mmp ctrl describes mmp controller related info */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index cfdb380ec81e..142e860fb527 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1263,7 +1263,7 @@ static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len, fbi->screen_base = dma_alloc_writecombine(fbi->device, mem_len, - &addr, GFP_DMA); + &addr, GFP_DMA | GFP_KERNEL); if (!fbi->screen_base) { dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", @@ -1354,7 +1354,7 @@ static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops) static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) { struct device *dev = mx3fb->dev; - struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data; + struct mx3fb_platform_data *mx3fb_pdata = dev_get_platdata(dev); const char *name = mx3fb_pdata->name; unsigned int irq; struct fb_info *fbi; @@ -1462,7 +1462,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg) return false; dev = rq->mx3fb->dev; - mx3fb_pdata = dev->platform_data; + mx3fb_pdata = dev_get_platdata(dev); return rq->id == chan->chan_id && mx3fb_pdata->dma_dev == chan->device->dev; diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 27197a8048c0..accf48a2cce4 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -49,6 +49,7 @@ #include <linux/fb.h> #include <linux/regulator/consumer.h> #include <video/of_display_timing.h> +#include <video/of_videomode.h> #include <video/videomode.h> #define REG_SET 4 @@ -297,7 +298,7 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var, } break; default: - pr_debug("Unsupported colour depth: %u\n", var->bits_per_pixel); + pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel); return -EINVAL; } @@ -426,7 +427,7 @@ static int mxsfb_set_par(struct fb_info *fb_info) ctrl |= CTRL_SET_WORD_LENGTH(3); switch (host->ld_intf_width) { case STMLCDIF_8BIT: - dev_dbg(&host->pdev->dev, + dev_err(&host->pdev->dev, "Unsupported LCD bus width mapping\n"); return -EINVAL; case STMLCDIF_16BIT: @@ -439,7 +440,7 @@ static int mxsfb_set_par(struct fb_info *fb_info) writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1); break; default: - dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n", + dev_err(&host->pdev->dev, "Unhandled color depth of %u\n", fb_info->var.bits_per_pixel); return -EINVAL; } @@ -589,7 +590,8 @@ static struct fb_ops mxsfb_ops = { .fb_imageblit = cfb_imageblit, }; -static int mxsfb_restore_mode(struct mxsfb_info *host) +static int mxsfb_restore_mode(struct mxsfb_info *host, + struct fb_videomode *vmode) { struct fb_info *fb_info = &host->fb_info; unsigned line_count; @@ -597,7 +599,6 @@ static int mxsfb_restore_mode(struct mxsfb_info *host) unsigned long pa, fbsize; int bits_per_pixel, ofs; u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl; - struct fb_videomode vmode; /* Only restore the mode when the controller is running */ ctrl = readl(host->base + LCDC_CTRL); @@ -611,8 +612,8 @@ static int mxsfb_restore_mode(struct mxsfb_info *host) transfer_count = readl(host->base + host->devdata->transfer_count); - vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count); - vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count); + vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count); + vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count); switch (CTRL_GET_WORD_LENGTH(ctrl)) { case 0: @@ -628,40 +629,39 @@ static int mxsfb_restore_mode(struct mxsfb_info *host) fb_info->var.bits_per_pixel = bits_per_pixel; - vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U); - vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2); - vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len; - vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len - - vmode.left_margin - vmode.xres; - vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0); + vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U); + vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2); + vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len; + vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - + vmode->hsync_len - vmode->left_margin - vmode->xres; + vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0); period = readl(host->base + LCDC_VDCTRL1); - vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len; - vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres; + vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len; + vmode->lower_margin = period - vmode->vsync_len - + vmode->upper_margin - vmode->yres; - vmode.vmode = FB_VMODE_NONINTERLACED; + vmode->vmode = FB_VMODE_NONINTERLACED; - vmode.sync = 0; + vmode->sync = 0; if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH) - vmode.sync |= FB_SYNC_HOR_HIGH_ACT; + vmode->sync |= FB_SYNC_HOR_HIGH_ACT; if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH) - vmode.sync |= FB_SYNC_VERT_HIGH_ACT; + vmode->sync |= FB_SYNC_VERT_HIGH_ACT; pr_debug("Reconstructed video mode:\n"); pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n", - vmode.xres, vmode.yres, - vmode.hsync_len, vmode.left_margin, vmode.right_margin, - vmode.vsync_len, vmode.upper_margin, vmode.lower_margin); - pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock)); - - fb_add_videomode(&vmode, &fb_info->modelist); + vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin, + vmode->right_margin, vmode->vsync_len, vmode->upper_margin, + vmode->lower_margin); + pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock)); host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl); host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4); - fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3); + fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3); pa = readl(host->base + host->devdata->cur_buf); - fbsize = fb_info->fix.line_length * vmode.yres; + fbsize = fb_info->fix.line_length * vmode->yres; if (pa < fb_info->fix.smem_start) return -EINVAL; if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) @@ -681,18 +681,17 @@ static int mxsfb_restore_mode(struct mxsfb_info *host) return 0; } -static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) +static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host, + struct fb_videomode *vmode) { struct fb_info *fb_info = &host->fb_info; struct fb_var_screeninfo *var = &fb_info->var; struct device *dev = &host->pdev->dev; struct device_node *np = host->pdev->dev.of_node; struct device_node *display_np; - struct device_node *timings_np; - struct display_timings *timings; + struct videomode vm; u32 width; - int i; - int ret = 0; + int ret; display_np = of_parse_phandle(np, "display", 0); if (!display_np) { @@ -732,54 +731,35 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) goto put_display_node; } - timings = of_get_display_timings(display_np); - if (!timings) { - dev_err(dev, "failed to get display timings\n"); - ret = -ENOENT; + ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE); + if (ret) { + dev_err(dev, "failed to get videomode from DT\n"); goto put_display_node; } - timings_np = of_find_node_by_name(display_np, - "display-timings"); - if (!timings_np) { - dev_err(dev, "failed to find display-timings node\n"); - ret = -ENOENT; + ret = fb_videomode_from_videomode(&vm, vmode); + if (ret < 0) goto put_display_node; - } - for (i = 0; i < of_get_child_count(timings_np); i++) { - struct videomode vm; - struct fb_videomode fb_vm; - - ret = videomode_from_timings(timings, &vm, i); - if (ret < 0) - goto put_timings_node; - ret = fb_videomode_from_videomode(&vm, &fb_vm); - if (ret < 0) - goto put_timings_node; - - if (vm.flags & DISPLAY_FLAGS_DE_HIGH) - host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; - if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) - host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT; - fb_add_videomode(&fb_vm, &fb_info->modelist); - } + if (vm.flags & DISPLAY_FLAGS_DE_HIGH) + host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; + if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT; -put_timings_node: - of_node_put(timings_np); put_display_node: of_node_put(display_np); return ret; } -static int mxsfb_init_fbinfo(struct mxsfb_info *host) +static int mxsfb_init_fbinfo(struct mxsfb_info *host, + struct fb_videomode *vmode) { + int ret; struct fb_info *fb_info = &host->fb_info; struct fb_var_screeninfo *var = &fb_info->var; dma_addr_t fb_phys; void *fb_virt; unsigned fb_size; - int ret; fb_info->fbops = &mxsfb_ops; fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; @@ -789,7 +769,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) fb_info->fix.visual = FB_VISUAL_TRUECOLOR, fb_info->fix.accel = FB_ACCEL_NONE; - ret = mxsfb_init_fbinfo_dt(host); + ret = mxsfb_init_fbinfo_dt(host, vmode); if (ret) return ret; @@ -810,7 +790,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) fb_info->screen_base = fb_virt; fb_info->screen_size = fb_info->fix.smem_len = fb_size; - if (mxsfb_restore_mode(host)) + if (mxsfb_restore_mode(host, vmode)) memset(fb_virt, 0, fb_size); return 0; @@ -850,7 +830,7 @@ static int mxsfb_probe(struct platform_device *pdev) struct resource *res; struct mxsfb_info *host; struct fb_info *fb_info; - struct fb_modelist *modelist; + struct fb_videomode *mode; int ret; if (of_id) @@ -862,6 +842,11 @@ static int mxsfb_probe(struct platform_device *pdev) return -ENOMEM; } + mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode), + GFP_KERNEL); + if (mode == NULL) + return -ENOMEM; + host = to_imxfb_host(fb_info); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -893,15 +878,11 @@ static int mxsfb_probe(struct platform_device *pdev) goto fb_release; } - INIT_LIST_HEAD(&fb_info->modelist); - - ret = mxsfb_init_fbinfo(host); + ret = mxsfb_init_fbinfo(host, mode); if (ret != 0) goto fb_release; - modelist = list_first_entry(&fb_info->modelist, - struct fb_modelist, list); - fb_videomode_to_var(&fb_info->var, &modelist->mode); + fb_videomode_to_var(&fb_info->var, mode); /* init the color fields */ mxsfb_check_var(&fb_info->var, fb_info); @@ -927,7 +908,6 @@ static int mxsfb_probe(struct platform_device *pdev) fb_destroy: if (host->enabled) clk_disable_unprepare(host->clk); - fb_destroy_modelist(&fb_info->modelist); fb_release: framebuffer_release(fb_info); diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index c172a5281f9e..44f99a60bb9b 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -2106,8 +2106,7 @@ static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err < 0) goto err_reg_fb; - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); /* * Our driver data @@ -2148,12 +2147,6 @@ static void neofb_remove(struct pci_dev *dev) fb_destroy_modedb(info->monspecs.modedb); neo_unmap_mmio(info); neo_free_fb_info(info); - - /* - * Ensure that the driver data is no longer - * valid. - */ - pci_set_drvdata(dev, NULL); } } diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index 796e5112ceee..478f9808dee4 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c @@ -91,7 +91,7 @@ static int nuc900fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct nuc900fb_info *fbi = info->par; - struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev); struct nuc900fb_display *display = NULL; struct nuc900fb_display *default_display = mach_info->displays + mach_info->default_display; @@ -358,7 +358,7 @@ static inline void modify_gpio(void __iomem *reg, static int nuc900fb_init_registers(struct fb_info *info) { struct nuc900fb_info *fbi = info->par; - struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev); void __iomem *regs = fbi->io; /*reset the display engine*/ @@ -512,7 +512,7 @@ static int nuc900fb_probe(struct platform_device *pdev) int size; dev_dbg(&pdev->dev, "devinit\n"); - mach_info = pdev->dev.platform_data; + mach_info = dev_get_platdata(&pdev->dev); if (mach_info == NULL) { dev_err(&pdev->dev, "no platform data for lcd, cannot attach\n"); @@ -647,8 +647,7 @@ static int nuc900fb_probe(struct platform_device *pdev) goto free_cpufreq; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - fbinfo->node, fbinfo->fix.id); + fb_info(fbinfo, "%s frame buffer device\n", fbinfo->fix.id); return 0; diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index ed20a9871b33..81c80ac3c76f 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -1300,7 +1300,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) break; default: break; - }; + } NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800); NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000); diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index ff228713425e..def041204676 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1461,7 +1461,6 @@ static void nvidiafb_remove(struct pci_dev *pd) pci_release_regions(pd); kfree(info->pixmap.addr); framebuffer_release(info); - pci_set_drvdata(pd, NULL); NVTRACE_LEAVE(); } diff --git a/drivers/video/ocfb.c b/drivers/video/ocfb.c new file mode 100644 index 000000000000..7f9dc9bec309 --- /dev/null +++ b/drivers/video/ocfb.c @@ -0,0 +1,440 @@ +/* + * OpenCores VGA/LCD 2.0 core frame buffer driver + * + * Copyright (C) 2013 Stefan Kristiansson, stefan.kristiansson@saunalahti.fi + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/string.h> +#include <linux/slab.h> + +/* OCFB register defines */ +#define OCFB_CTRL 0x000 +#define OCFB_STAT 0x004 +#define OCFB_HTIM 0x008 +#define OCFB_VTIM 0x00c +#define OCFB_HVLEN 0x010 +#define OCFB_VBARA 0x014 +#define OCFB_PALETTE 0x800 + +#define OCFB_CTRL_VEN 0x00000001 /* Video Enable */ +#define OCFB_CTRL_HIE 0x00000002 /* HSync Interrupt Enable */ +#define OCFB_CTRL_PC 0x00000800 /* 8-bit Pseudo Color Enable*/ +#define OCFB_CTRL_CD8 0x00000000 /* Color Depth 8 */ +#define OCFB_CTRL_CD16 0x00000200 /* Color Depth 16 */ +#define OCFB_CTRL_CD24 0x00000400 /* Color Depth 24 */ +#define OCFB_CTRL_CD32 0x00000600 /* Color Depth 32 */ +#define OCFB_CTRL_VBL1 0x00000000 /* Burst Length 1 */ +#define OCFB_CTRL_VBL2 0x00000080 /* Burst Length 2 */ +#define OCFB_CTRL_VBL4 0x00000100 /* Burst Length 4 */ +#define OCFB_CTRL_VBL8 0x00000180 /* Burst Length 8 */ + +#define PALETTE_SIZE 256 + +#define OCFB_NAME "OC VGA/LCD" + +static char *mode_option; + +static const struct fb_videomode default_mode = { + /* 640x480 @ 60 Hz, 31.5 kHz hsync */ + NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, + 0, FB_VMODE_NONINTERLACED +}; + +struct ocfb_dev { + struct fb_info info; + void __iomem *regs; + /* flag indicating whether the regs are little endian accessed */ + int little_endian; + /* Physical and virtual addresses of framebuffer */ + phys_addr_t fb_phys; + void __iomem *fb_virt; + u32 pseudo_palette[PALETTE_SIZE]; +}; + +#ifndef MODULE +static int __init ocfb_setup(char *options) +{ + char *curr_opt; + + if (!options || !*options) + return 0; + + while ((curr_opt = strsep(&options, ",")) != NULL) { + if (!*curr_opt) + continue; + mode_option = curr_opt; + } + + return 0; +} +#endif + +static inline u32 ocfb_readreg(struct ocfb_dev *fbdev, loff_t offset) +{ + if (fbdev->little_endian) + return ioread32(fbdev->regs + offset); + else + return ioread32be(fbdev->regs + offset); +} + +static void ocfb_writereg(struct ocfb_dev *fbdev, loff_t offset, u32 data) +{ + if (fbdev->little_endian) + iowrite32(data, fbdev->regs + offset); + else + iowrite32be(data, fbdev->regs + offset); +} + +static int ocfb_setupfb(struct ocfb_dev *fbdev) +{ + unsigned long bpp_config; + struct fb_var_screeninfo *var = &fbdev->info.var; + struct device *dev = fbdev->info.device; + u32 hlen; + u32 vlen; + + /* Disable display */ + ocfb_writereg(fbdev, OCFB_CTRL, 0); + + /* Register framebuffer address */ + fbdev->little_endian = 0; + ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys); + + /* Detect endianess */ + if (ocfb_readreg(fbdev, OCFB_VBARA) != fbdev->fb_phys) { + fbdev->little_endian = 1; + ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys); + } + + /* Horizontal timings */ + ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 | + (var->right_margin - 1) << 16 | (var->xres - 1)); + + /* Vertical timings */ + ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 | + (var->lower_margin - 1) << 16 | (var->yres - 1)); + + /* Total length of frame */ + hlen = var->left_margin + var->right_margin + var->hsync_len + + var->xres; + + vlen = var->upper_margin + var->lower_margin + var->vsync_len + + var->yres; + + ocfb_writereg(fbdev, OCFB_HVLEN, (hlen - 1) << 16 | (vlen - 1)); + + bpp_config = OCFB_CTRL_CD8; + switch (var->bits_per_pixel) { + case 8: + if (!var->grayscale) + bpp_config |= OCFB_CTRL_PC; /* enable palette */ + break; + + case 16: + bpp_config |= OCFB_CTRL_CD16; + break; + + case 24: + bpp_config |= OCFB_CTRL_CD24; + break; + + case 32: + bpp_config |= OCFB_CTRL_CD32; + break; + + default: + dev_err(dev, "no bpp specified\n"); + break; + } + + /* maximum (8) VBL (video memory burst length) */ + bpp_config |= OCFB_CTRL_VBL8; + + /* Enable output */ + ocfb_writereg(fbdev, OCFB_CTRL, (OCFB_CTRL_VEN | bpp_config)); + + return 0; +} + +static int ocfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct ocfb_dev *fbdev = (struct ocfb_dev *)info->par; + u32 color; + + if (regno >= info->cmap.len) { + dev_err(info->device, "regno >= cmap.len\n"); + return 1; + } + + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + red >>= (16 - info->var.red.length); + green >>= (16 - info->var.green.length); + blue >>= (16 - info->var.blue.length); + transp >>= (16 - info->var.transp.length); + + if (info->var.bits_per_pixel == 8 && !info->var.grayscale) { + regno <<= 2; + color = (red << 16) | (green << 8) | blue; + ocfb_writereg(fbdev, OCFB_PALETTE + regno, color); + } else { + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset) | + (transp << info->var.transp.offset); + } + + return 0; +} + +static int ocfb_init_fix(struct ocfb_dev *fbdev) +{ + struct fb_var_screeninfo *var = &fbdev->info.var; + struct fb_fix_screeninfo *fix = &fbdev->info.fix; + + strcpy(fix->id, OCFB_NAME); + + fix->line_length = var->xres * var->bits_per_pixel/8; + fix->smem_len = fix->line_length * var->yres; + fix->type = FB_TYPE_PACKED_PIXELS; + + if (var->bits_per_pixel == 8 && !var->grayscale) + fix->visual = FB_VISUAL_PSEUDOCOLOR; + else + fix->visual = FB_VISUAL_TRUECOLOR; + + return 0; +} + +static int ocfb_init_var(struct ocfb_dev *fbdev) +{ + struct fb_var_screeninfo *var = &fbdev->info.var; + + var->accel_flags = FB_ACCEL_NONE; + var->activate = FB_ACTIVATE_NOW; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + + switch (var->bits_per_pixel) { + case 8: + var->transp.offset = 0; + var->transp.length = 0; + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + break; + + case 16: + var->transp.offset = 0; + var->transp.length = 0; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + break; + + case 24: + var->transp.offset = 0; + var->transp.length = 0; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + break; + + case 32: + var->transp.offset = 24; + var->transp.length = 8; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + break; + } + + return 0; +} + +static struct fb_ops ocfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = ocfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int ocfb_probe(struct platform_device *pdev) +{ + int ret = 0; + struct ocfb_dev *fbdev; + struct resource *res; + int fbsize; + + fbdev = devm_kzalloc(&pdev->dev, sizeof(*fbdev), GFP_KERNEL); + if (!fbdev) + return -ENOMEM; + + platform_set_drvdata(pdev, fbdev); + + fbdev->info.fbops = &ocfb_ops; + fbdev->info.device = &pdev->dev; + fbdev->info.par = fbdev; + + /* Video mode setup */ + if (!fb_find_mode(&fbdev->info.var, &fbdev->info, mode_option, + NULL, 0, &default_mode, 16)) { + dev_err(&pdev->dev, "No valid video modes found\n"); + return -EINVAL; + } + ocfb_init_var(fbdev); + ocfb_init_fix(fbdev); + + /* Request I/O resource */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "I/O resource request failed\n"); + return -ENXIO; + } + res->flags &= ~IORESOURCE_CACHEABLE; + fbdev->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fbdev->regs)) + return PTR_ERR(fbdev->regs); + + /* Allocate framebuffer memory */ + fbsize = fbdev->info.fix.smem_len; + fbdev->fb_virt = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbsize), + &fbdev->fb_phys, GFP_KERNEL); + if (!fbdev->fb_virt) { + dev_err(&pdev->dev, + "Frame buffer memory allocation failed\n"); + return -ENOMEM; + } + fbdev->info.fix.smem_start = fbdev->fb_phys; + fbdev->info.screen_base = fbdev->fb_virt; + fbdev->info.pseudo_palette = fbdev->pseudo_palette; + + /* Clear framebuffer */ + memset_io(fbdev->fb_virt, 0, fbsize); + + /* Setup and enable the framebuffer */ + ocfb_setupfb(fbdev); + + if (fbdev->little_endian) + fbdev->info.flags |= FBINFO_FOREIGN_ENDIAN; + + /* Allocate color map */ + ret = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0); + if (ret) { + dev_err(&pdev->dev, "Color map allocation failed\n"); + goto err_dma_free; + } + + /* Register framebuffer */ + ret = register_framebuffer(&fbdev->info); + if (ret) { + dev_err(&pdev->dev, "Framebuffer registration failed\n"); + goto err_dealloc_cmap; + } + + return 0; + +err_dealloc_cmap: + fb_dealloc_cmap(&fbdev->info.cmap); + +err_dma_free: + dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbsize), fbdev->fb_virt, + fbdev->fb_phys); + + return ret; +} + +static int ocfb_remove(struct platform_device *pdev) +{ + struct ocfb_dev *fbdev = platform_get_drvdata(pdev); + + unregister_framebuffer(&fbdev->info); + fb_dealloc_cmap(&fbdev->info.cmap); + dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbdev->info.fix.smem_len), + fbdev->fb_virt, fbdev->fb_phys); + + /* Disable display */ + ocfb_writereg(fbdev, OCFB_CTRL, 0); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct of_device_id ocfb_match[] = { + { .compatible = "opencores,ocfb", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ocfb_match); + +static struct platform_driver ocfb_driver = { + .probe = ocfb_probe, + .remove = ocfb_remove, + .driver = { + .name = "ocfb_fb", + .of_match_table = ocfb_match, + } +}; + +/* + * Init and exit routines + */ +static int __init ocfb_init(void) +{ +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("ocfb", &option)) + return -ENODEV; + ocfb_setup(option); +#endif + return platform_driver_register(&ocfb_driver); +} + +static void __exit ocfb_exit(void) +{ + platform_driver_unregister(&ocfb_driver); +} + +module_init(ocfb_init); +module_exit(ocfb_exit); + +MODULE_AUTHOR("Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>"); +MODULE_DESCRIPTION("OpenCores VGA/LCD 2.0 frame buffer driver"); +MODULE_LICENSE("GPL v2"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "Video mode ('<xres>x<yres>[-<bpp>][@refresh]')"); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 0c4f34311eda..7d44d669d5b6 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos; #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8 +#define FB_RIGHT_POS(p, bpp) (fb_be_math(p) ? 0 : (32 - (bpp))) + +static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value) +{ + u32 bpp = info->var.bits_per_pixel; + + return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp); +} + /* * Set a single color register. The values supplied are already * rounded down to the hardware's capabilities (according to the @@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, mask <<= info->var.transp.offset; value |= mask; } - pal[regno] = value; + pal[regno] = offb_cmap_byteswap(info, value); return 0; } @@ -301,7 +310,7 @@ static struct fb_ops offb_ops = { static void __iomem *offb_map_reg(struct device_node *np, int index, unsigned long offset, unsigned long size) { - const u32 *addrp; + const __be32 *addrp; u64 asize, taddr; unsigned int flags; @@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp } of_node_put(pciparent); } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) { - const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#ifdef __BIG_ENDIAN + const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#else + const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 }; +#endif u64 io_addr = of_translate_address(dp, io_of_addr); if (io_addr != OF_BAD_ADDR) { par->cmap_adr = ioremap(io_addr + 0x3c8, 2); @@ -515,8 +528,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, if (register_framebuffer(info) < 0) goto out_err; - printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", - info->node, full_name); + fb_info(info, "Open Firmware frame buffer device on %s\n", full_name); return; out_err: @@ -536,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) unsigned int flags, rsize, addr_prop = 0; unsigned long max_size = 0; u64 rstart, address = OF_BAD_ADDR; - const u32 *pp, *addrp, *up; + const __be32 *pp, *addrp, *up; u64 asize; int foreign_endian = 0; @@ -552,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) if (pp == NULL) pp = of_get_property(dp, "depth", &len); if (pp && len == sizeof(u32)) - depth = *pp; + depth = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-width", &len); if (pp == NULL) pp = of_get_property(dp, "width", &len); if (pp && len == sizeof(u32)) - width = *pp; + width = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-height", &len); if (pp == NULL) pp = of_get_property(dp, "height", &len); if (pp && len == sizeof(u32)) - height = *pp; + height = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) pp = of_get_property(dp, "linebytes", &len); if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) - pitch = *pp; + pitch = be32_to_cpup(pp); else pitch = width * ((depth + 7) / 8); diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index f349ee6f0cea..a4ee65b8f918 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -947,7 +947,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, hwa742.extif = fbdev->ext_if; hwa742.int_ctrl = fbdev->int_ctrl; - omapfb_conf = fbdev->dev->platform_data; + omapfb_conf = dev_get_platdata(fbdev->dev); hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index d40612c31a98..e4fc6d9b5371 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -1602,7 +1602,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev) char name[17]; int i; - conf = fbdev->dev->platform_data; + conf = dev_get_platdata(fbdev->dev); fbdev->ctrl = NULL; @@ -1674,7 +1674,7 @@ static int omapfb_do_probe(struct platform_device *pdev, goto cleanup; } - if (pdev->dev.platform_data == NULL) { + if (dev_get_platdata(&pdev->dev) == NULL) { dev_err(&pdev->dev, "missing platform data\n"); r = -ENOENT; goto cleanup; diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/omap2/displays-new/Kconfig index 10b25e7cd878..e6cfc38160d3 100644 --- a/drivers/video/omap2/displays-new/Kconfig +++ b/drivers/video/omap2/displays-new/Kconfig @@ -57,6 +57,12 @@ config DISPLAY_PANEL_SHARP_LS037V7DW01 help LCD Panel used in TI's SDP3430 and EVM boards +config DISPLAY_PANEL_TPO_TD028TTEC1 + tristate "TPO TD028TTEC1 LCD Panel" + depends on SPI + help + LCD panel used in Openmoko. + config DISPLAY_PANEL_TPO_TD043MTEA1 tristate "TPO TD043MTEA1 LCD Panel" depends on SPI diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/omap2/displays-new/Makefile index 5aeb11b8fcd5..0323a8a1c682 100644 --- a/drivers/video/omap2/displays-new/Makefile +++ b/drivers/video/omap2/displays-new/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o +obj-$(CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/omap2/displays-new/connector-dvi.c index 63d88ee6dfe4..b6c50904038e 100644 --- a/drivers/video/omap2/displays-new/connector-dvi.c +++ b/drivers/video/omap2/displays-new/connector-dvi.c @@ -262,6 +262,9 @@ static int dvic_probe_pdata(struct platform_device *pdev) in = omap_dss_find_output(pdata->source); if (in == NULL) { + if (ddata->i2c_adapter) + i2c_put_adapter(ddata->i2c_adapter); + dev_err(&pdev->dev, "Failed to find video source\n"); return -EPROBE_DEFER; } @@ -313,6 +316,10 @@ static int dvic_probe(struct platform_device *pdev) err_reg: omap_dss_put_device(ddata->in); + + if (ddata->i2c_adapter) + i2c_put_adapter(ddata->i2c_adapter); + return r; } diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c index 798ef200b055..d5c936cb217f 100644 --- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c @@ -69,7 +69,7 @@ static int tpd_connect(struct omap_dss_device *dssdev, dst->src = dssdev; dssdev->dst = dst; - INIT_COMPLETION(ddata->hpd_completion); + reinit_completion(&ddata->hpd_completion); gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); /* DC-DC converter needs at max 300us to get to 90% of 5V */ diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/omap2/displays-new/panel-dsi-cm.c index aaaea6469cd9..b7baafe83aa3 100644 --- a/drivers/video/omap2/displays-new/panel-dsi-cm.c +++ b/drivers/video/omap2/displays-new/panel-dsi-cm.c @@ -599,7 +599,7 @@ static int dsicm_power_on(struct panel_drv_data *ddata) if (r) { dev_err(&ddata->pdev->dev, "failed to configure DSI pins\n"); goto err0; - }; + } r = in->ops.dsi->set_config(in, &dsi_config); if (r) { diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c index e6d56f714ae4..8e97d06921ff 100644 --- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c +++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c @@ -346,28 +346,22 @@ static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata) static int acx565akm_bl_update_status(struct backlight_device *dev) { struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); - int r; int level; dev_dbg(&ddata->spi->dev, "%s\n", __func__); - mutex_lock(&ddata->mutex); - if (dev->props.fb_blank == FB_BLANK_UNBLANK && dev->props.power == FB_BLANK_UNBLANK) level = dev->props.brightness; else level = 0; - r = 0; if (ddata->has_bc) acx565akm_set_brightness(ddata, level); else - r = -ENODEV; - - mutex_unlock(&ddata->mutex); + return -ENODEV; - return r; + return 0; } static int acx565akm_bl_get_intensity(struct backlight_device *dev) @@ -390,9 +384,33 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev) return 0; } +static int acx565akm_bl_update_status_locked(struct backlight_device *dev) +{ + struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); + int r; + + mutex_lock(&ddata->mutex); + r = acx565akm_bl_update_status(dev); + mutex_unlock(&ddata->mutex); + + return r; +} + +static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev) +{ + struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); + int r; + + mutex_lock(&ddata->mutex); + r = acx565akm_bl_get_intensity(dev); + mutex_unlock(&ddata->mutex); + + return r; +} + static const struct backlight_ops acx565akm_bl_ops = { - .get_brightness = acx565akm_bl_get_intensity, - .update_status = acx565akm_bl_update_status, + .get_brightness = acx565akm_bl_get_intensity_locked, + .update_status = acx565akm_bl_update_status_locked, }; /*--------------------Auto Brightness control via Sysfs---------------------*/ @@ -566,8 +584,6 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) set_display_state(ddata, 1); set_cabc_mode(ddata, ddata->cabc_mode); - mutex_unlock(&ddata->mutex); - return acx565akm_bl_update_status(ddata->bl_dev); } @@ -617,7 +633,6 @@ static int acx565akm_enable(struct omap_dss_device *dssdev) mutex_lock(&ddata->mutex); r = acx565akm_panel_power_on(dssdev); mutex_unlock(&ddata->mutex); - if (r) return r; diff --git a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c new file mode 100644 index 000000000000..9a08908fe998 --- /dev/null +++ b/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c @@ -0,0 +1,480 @@ +/* + * Toppoly TD028TTEC1 panel support + * + * Copyright (C) 2008 Nokia Corporation + * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> + * + * Neo 1973 code (jbt6k74.c): + * Copyright (C) 2006-2007 by OpenMoko, Inc. + * Author: Harald Welte <laforge@openmoko.org> + * + * Ported and adapted from Neo 1973 U-Boot by: + * H. Nikolaus Schaller <hns@goldelico.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <video/omapdss.h> +#include <video/omap-panel-data.h> + +struct panel_drv_data { + struct omap_dss_device dssdev; + struct omap_dss_device *in; + + int data_lines; + + struct omap_video_timings videomode; + + struct spi_device *spi_dev; +}; + +static struct omap_video_timings td028ttec1_panel_timings = { + .x_res = 480, + .y_res = 640, + .pixel_clock = 22153, + .hfp = 24, + .hsw = 8, + .hbp = 8, + .vfp = 4, + .vsw = 2, + .vbp = 2, + + .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, + .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, + + .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE, + .de_level = OMAPDSS_SIG_ACTIVE_HIGH, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, +}; + +#define JBT_COMMAND 0x000 +#define JBT_DATA 0x100 + +static int jbt_ret_write_0(struct panel_drv_data *ddata, u8 reg) +{ + int rc; + u16 tx_buf = JBT_COMMAND | reg; + + rc = spi_write(ddata->spi_dev, (u8 *)&tx_buf, + 1*sizeof(u16)); + if (rc != 0) + dev_err(&ddata->spi_dev->dev, + "jbt_ret_write_0 spi_write ret %d\n", rc); + + return rc; +} + +static int jbt_reg_write_1(struct panel_drv_data *ddata, u8 reg, u8 data) +{ + int rc; + u16 tx_buf[2]; + + tx_buf[0] = JBT_COMMAND | reg; + tx_buf[1] = JBT_DATA | data; + rc = spi_write(ddata->spi_dev, (u8 *)tx_buf, + 2*sizeof(u16)); + if (rc != 0) + dev_err(&ddata->spi_dev->dev, + "jbt_reg_write_1 spi_write ret %d\n", rc); + + return rc; +} + +static int jbt_reg_write_2(struct panel_drv_data *ddata, u8 reg, u16 data) +{ + int rc; + u16 tx_buf[3]; + + tx_buf[0] = JBT_COMMAND | reg; + tx_buf[1] = JBT_DATA | (data >> 8); + tx_buf[2] = JBT_DATA | (data & 0xff); + + rc = spi_write(ddata->spi_dev, (u8 *)tx_buf, + 3*sizeof(u16)); + + if (rc != 0) + dev_err(&ddata->spi_dev->dev, + "jbt_reg_write_2 spi_write ret %d\n", rc); + + return rc; +} + +enum jbt_register { + JBT_REG_SLEEP_IN = 0x10, + JBT_REG_SLEEP_OUT = 0x11, + + JBT_REG_DISPLAY_OFF = 0x28, + JBT_REG_DISPLAY_ON = 0x29, + + JBT_REG_RGB_FORMAT = 0x3a, + JBT_REG_QUAD_RATE = 0x3b, + + JBT_REG_POWER_ON_OFF = 0xb0, + JBT_REG_BOOSTER_OP = 0xb1, + JBT_REG_BOOSTER_MODE = 0xb2, + JBT_REG_BOOSTER_FREQ = 0xb3, + JBT_REG_OPAMP_SYSCLK = 0xb4, + JBT_REG_VSC_VOLTAGE = 0xb5, + JBT_REG_VCOM_VOLTAGE = 0xb6, + JBT_REG_EXT_DISPL = 0xb7, + JBT_REG_OUTPUT_CONTROL = 0xb8, + JBT_REG_DCCLK_DCEV = 0xb9, + JBT_REG_DISPLAY_MODE1 = 0xba, + JBT_REG_DISPLAY_MODE2 = 0xbb, + JBT_REG_DISPLAY_MODE = 0xbc, + JBT_REG_ASW_SLEW = 0xbd, + JBT_REG_DUMMY_DISPLAY = 0xbe, + JBT_REG_DRIVE_SYSTEM = 0xbf, + + JBT_REG_SLEEP_OUT_FR_A = 0xc0, + JBT_REG_SLEEP_OUT_FR_B = 0xc1, + JBT_REG_SLEEP_OUT_FR_C = 0xc2, + JBT_REG_SLEEP_IN_LCCNT_D = 0xc3, + JBT_REG_SLEEP_IN_LCCNT_E = 0xc4, + JBT_REG_SLEEP_IN_LCCNT_F = 0xc5, + JBT_REG_SLEEP_IN_LCCNT_G = 0xc6, + + JBT_REG_GAMMA1_FINE_1 = 0xc7, + JBT_REG_GAMMA1_FINE_2 = 0xc8, + JBT_REG_GAMMA1_INCLINATION = 0xc9, + JBT_REG_GAMMA1_BLUE_OFFSET = 0xca, + + JBT_REG_BLANK_CONTROL = 0xcf, + JBT_REG_BLANK_TH_TV = 0xd0, + JBT_REG_CKV_ON_OFF = 0xd1, + JBT_REG_CKV_1_2 = 0xd2, + JBT_REG_OEV_TIMING = 0xd3, + JBT_REG_ASW_TIMING_1 = 0xd4, + JBT_REG_ASW_TIMING_2 = 0xd5, + + JBT_REG_HCLOCK_VGA = 0xec, + JBT_REG_HCLOCK_QVGA = 0xed, +}; + +#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) + +static int td028ttec1_panel_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; +} + +static void td028ttec1_panel_disconnect(struct omap_dss_device *dssdev) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + + if (!omapdss_device_is_connected(dssdev)) + return; + + in->ops.dpi->disconnect(in, dssdev); +} + +static int td028ttec1_panel_enable(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 -ENODEV; + + if (omapdss_device_is_enabled(dssdev)) + return 0; + + in->ops.dpi->set_data_lines(in, ddata->data_lines); + in->ops.dpi->set_timings(in, &ddata->videomode); + + r = in->ops.dpi->enable(in); + if (r) + return r; + + dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n", + dssdev->state); + + /* three times command zero */ + r |= jbt_ret_write_0(ddata, 0x00); + usleep_range(1000, 2000); + r |= jbt_ret_write_0(ddata, 0x00); + usleep_range(1000, 2000); + r |= jbt_ret_write_0(ddata, 0x00); + usleep_range(1000, 2000); + + if (r) { + dev_warn(dssdev->dev, "transfer error\n"); + goto transfer_err; + } + + /* deep standby out */ + r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x17); + + /* RGB I/F on, RAM write off, QVGA through, SIGCON enable */ + r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE, 0x80); + + /* Quad mode off */ + r |= jbt_reg_write_1(ddata, JBT_REG_QUAD_RATE, 0x00); + + /* AVDD on, XVDD on */ + r |= jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x16); + + /* Output control */ + r |= jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0xfff9); + + /* Sleep mode off */ + r |= jbt_ret_write_0(ddata, JBT_REG_SLEEP_OUT); + + /* at this point we have like 50% grey */ + + /* initialize register set */ + r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE1, 0x01); + r |= jbt_reg_write_1(ddata, JBT_REG_DISPLAY_MODE2, 0x00); + r |= jbt_reg_write_1(ddata, JBT_REG_RGB_FORMAT, 0x60); + r |= jbt_reg_write_1(ddata, JBT_REG_DRIVE_SYSTEM, 0x10); + r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_OP, 0x56); + r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_MODE, 0x33); + r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11); + r |= jbt_reg_write_1(ddata, JBT_REG_BOOSTER_FREQ, 0x11); + r |= jbt_reg_write_1(ddata, JBT_REG_OPAMP_SYSCLK, 0x02); + r |= jbt_reg_write_1(ddata, JBT_REG_VSC_VOLTAGE, 0x2b); + r |= jbt_reg_write_1(ddata, JBT_REG_VCOM_VOLTAGE, 0x40); + r |= jbt_reg_write_1(ddata, JBT_REG_EXT_DISPL, 0x03); + r |= jbt_reg_write_1(ddata, JBT_REG_DCCLK_DCEV, 0x04); + /* + * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement + * to avoid red / blue flicker + */ + r |= jbt_reg_write_1(ddata, JBT_REG_ASW_SLEW, 0x04); + r |= jbt_reg_write_1(ddata, JBT_REG_DUMMY_DISPLAY, 0x00); + + r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_A, 0x11); + r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_B, 0x11); + r |= jbt_reg_write_1(ddata, JBT_REG_SLEEP_OUT_FR_C, 0x11); + r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040); + r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0); + r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020); + r |= jbt_reg_write_2(ddata, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0); + + r |= jbt_reg_write_2(ddata, JBT_REG_GAMMA1_FINE_1, 0x5533); + r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_FINE_2, 0x00); + r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_INCLINATION, 0x00); + r |= jbt_reg_write_1(ddata, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00); + + r |= jbt_reg_write_2(ddata, JBT_REG_HCLOCK_VGA, 0x1f0); + r |= jbt_reg_write_1(ddata, JBT_REG_BLANK_CONTROL, 0x02); + r |= jbt_reg_write_2(ddata, JBT_REG_BLANK_TH_TV, 0x0804); + + r |= jbt_reg_write_1(ddata, JBT_REG_CKV_ON_OFF, 0x01); + r |= jbt_reg_write_2(ddata, JBT_REG_CKV_1_2, 0x0000); + + r |= jbt_reg_write_2(ddata, JBT_REG_OEV_TIMING, 0x0d0e); + r |= jbt_reg_write_2(ddata, JBT_REG_ASW_TIMING_1, 0x11a4); + r |= jbt_reg_write_1(ddata, JBT_REG_ASW_TIMING_2, 0x0e); + + r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +transfer_err: + + return r ? -EIO : 0; +} + +static void td028ttec1_panel_disable(struct omap_dss_device *dssdev) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + + if (!omapdss_device_is_enabled(dssdev)) + return; + + dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n"); + + jbt_ret_write_0(ddata, JBT_REG_DISPLAY_OFF); + jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002); + jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN); + jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00); + + in->ops.dpi->disable(in); + + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +} + +static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + + ddata->videomode = *timings; + dssdev->panel.timings = *timings; + + in->ops.dpi->set_timings(in, timings); +} + +static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + + *timings = ddata->videomode; +} + +static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + + return in->ops.dpi->check_timings(in, timings); +} + +static struct omap_dss_driver td028ttec1_ops = { + .connect = td028ttec1_panel_connect, + .disconnect = td028ttec1_panel_disconnect, + + .enable = td028ttec1_panel_enable, + .disable = td028ttec1_panel_disable, + + .set_timings = td028ttec1_panel_set_timings, + .get_timings = td028ttec1_panel_get_timings, + .check_timings = td028ttec1_panel_check_timings, +}; + +static int td028ttec1_panel_probe_pdata(struct spi_device *spi) +{ + const struct panel_tpo_td028ttec1_platform_data *pdata; + struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); + struct omap_dss_device *dssdev, *in; + + pdata = dev_get_platdata(&spi->dev); + + in = omap_dss_find_output(pdata->source); + if (in == NULL) { + dev_err(&spi->dev, "failed to find video source '%s'\n", + pdata->source); + return -EPROBE_DEFER; + } + + ddata->in = in; + + ddata->data_lines = pdata->data_lines; + + dssdev = &ddata->dssdev; + dssdev->name = pdata->name; + + return 0; +} + +static int td028ttec1_panel_probe(struct spi_device *spi) +{ + struct panel_drv_data *ddata; + struct omap_dss_device *dssdev; + int r; + + dev_dbg(&spi->dev, "%s\n", __func__); + + spi->bits_per_word = 9; + spi->mode = SPI_MODE_3; + + r = spi_setup(spi); + if (r < 0) { + dev_err(&spi->dev, "spi_setup failed: %d\n", r); + return r; + } + + ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); + if (ddata == NULL) + return -ENOMEM; + + dev_set_drvdata(&spi->dev, ddata); + + ddata->spi_dev = spi; + + if (dev_get_platdata(&spi->dev)) { + r = td028ttec1_panel_probe_pdata(spi); + if (r) + return r; + } else { + return -ENODEV; + } + + ddata->videomode = td028ttec1_panel_timings; + + dssdev = &ddata->dssdev; + dssdev->dev = &spi->dev; + dssdev->driver = &td028ttec1_ops; + dssdev->type = OMAP_DISPLAY_TYPE_DPI; + dssdev->owner = THIS_MODULE; + dssdev->panel.timings = ddata->videomode; + dssdev->phy.dpi.data_lines = ddata->data_lines; + + r = omapdss_register_display(dssdev); + if (r) { + dev_err(&spi->dev, "Failed to register panel\n"); + goto err_reg; + } + + return 0; + +err_reg: + omap_dss_put_device(ddata->in); + return r; +} + +static int td028ttec1_panel_remove(struct spi_device *spi) +{ + struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); + struct omap_dss_device *dssdev = &ddata->dssdev; + struct omap_dss_device *in = ddata->in; + + dev_dbg(&ddata->spi_dev->dev, "%s\n", __func__); + + omapdss_unregister_display(dssdev); + + td028ttec1_panel_disable(dssdev); + td028ttec1_panel_disconnect(dssdev); + + omap_dss_put_device(in); + + return 0; +} + +static struct spi_driver td028ttec1_spi_driver = { + .probe = td028ttec1_panel_probe, + .remove = td028ttec1_panel_remove, + + .driver = { + .name = "panel-tpo-td028ttec1", + .owner = THIS_MODULE, + }, +}; + +module_spi_driver(td028ttec1_spi_driver); + +MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>"); +MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 94832eb06a3d..d3aa91bdd6a8 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -10,5 +10,6 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o -omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o ti_hdmi_4xxx_ip.o +omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \ + hdmi_phy.o hdmi4_core.o ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 60758dbefd79..0a0b084ce65d 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -149,6 +149,9 @@ static void apply_init_priv(void) op = &dss_data.ovl_priv_data_array[i]; + op->info.color_mode = OMAP_DSS_COLOR_RGB16; + op->info.rotation_type = OMAP_DSS_ROT_DMA; + op->info.global_alpha = 255; switch (i) { @@ -629,7 +632,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) struct mgr_priv_data *mp; int r; - DSSDBG("writing ovl %d regs", ovl->id); + DSSDBG("writing ovl %d regs\n", ovl->id); if (!op->enabled || !op->info_dirty) return; @@ -664,7 +667,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl) struct ovl_priv_data *op = get_ovl_priv(ovl); struct mgr_priv_data *mp; - DSSDBG("writing ovl %d regs extra", ovl->id); + DSSDBG("writing ovl %d regs extra\n", ovl->id); if (!op->extra_info_dirty) return; @@ -687,7 +690,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) struct mgr_priv_data *mp = get_mgr_priv(mgr); struct omap_overlay *ovl; - DSSDBG("writing mgr %d regs", mgr->id); + DSSDBG("writing mgr %d regs\n", mgr->id); if (!mp->enabled) return; @@ -713,7 +716,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); - DSSDBG("writing mgr %d regs extra", mgr->id); + DSSDBG("writing mgr %d regs extra\n", mgr->id); if (!mp->extra_info_dirty) return; diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 60d3958d04f7..ffa45c894cd4 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -266,7 +266,7 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = { venc_init_platform_driver, #endif #ifdef CONFIG_OMAP4_DSS_HDMI - hdmi_init_platform_driver, + hdmi4_init_platform_driver, #endif }; @@ -287,7 +287,7 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { venc_uninit_platform_driver, #endif #ifdef CONFIG_OMAP4_DSS_HDMI - hdmi_uninit_platform_driver, + hdmi4_uninit_platform_driver, #endif }; diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 477975009eee..f51646f15cf2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -90,6 +90,8 @@ struct dispc_features { /* revert to the OMAP4 mechanism of DISPC Smart Standby operation */ bool mstandby_workaround:1; + + bool set_max_preload:1; }; #define DISPC_MAX_NR_FIFOS 5 @@ -1200,7 +1202,17 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), FLD_VAL(high, hi_start, hi_end) | FLD_VAL(low, lo_start, lo_end)); + + /* + * configure the preload to the pipeline's high threhold, if HT it's too + * large for the preload field, set the threshold to the maximum value + * that can be held by the preload register + */ + if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && + plane != OMAP_DSS_WB) + dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); } +EXPORT_SYMBOL(dispc_ovl_set_fifo_threshold); void dispc_enable_fifomerge(bool enable) { @@ -1259,6 +1271,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, *fifo_high = total_fifo_size - buf_unit; } } +EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds); static void dispc_ovl_set_fir(enum omap_plane plane, int hinc, int vinc, @@ -1988,7 +2001,8 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, */ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, const struct omap_video_timings *t, u16 pos_x, - u16 width, u16 height, u16 out_width, u16 out_height) + u16 width, u16 height, u16 out_width, u16 out_height, + bool five_taps) { const int ds = DIV_ROUND_UP(height, out_height); unsigned long nonactive; @@ -2008,6 +2022,10 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, if (blank <= limits[i]) return -EINVAL; + /* FIXME add checks for 3-tap filter once the limitations are known */ + if (!five_taps) + return 0; + /* * Pixel data should be prepared before visible display point starts. * So, atleast DS-2 lines must have already been fetched by DISPC @@ -2183,22 +2201,30 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, do { in_height = DIV_ROUND_UP(height, *decim_y); in_width = DIV_ROUND_UP(width, *decim_x); - *core_clk = calc_core_clk_five_taps(pclk, mgr_timings, - in_width, in_height, out_width, out_height, color_mode); - - error = check_horiz_timing_omap3(pclk, lclk, mgr_timings, - pos_x, in_width, in_height, out_width, - out_height); + *five_taps = in_height > out_height; if (in_width > maxsinglelinewidth) if (in_height > out_height && in_height < out_height * 2) *five_taps = false; - if (!*five_taps) +again: + if (*five_taps) + *core_clk = calc_core_clk_five_taps(pclk, mgr_timings, + in_width, in_height, out_width, + out_height, color_mode); + else *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height, out_width, out_height, mem_to_mem); + error = check_horiz_timing_omap3(pclk, lclk, mgr_timings, + pos_x, in_width, in_height, out_width, + out_height, *five_taps); + if (error && *five_taps) { + *five_taps = false; + goto again; + } + error = (error || in_width > maxsinglelinewidth * 2 || (in_width > maxsinglelinewidth && *five_taps) || !*core_clk || *core_clk > dispc_core_clk_rate()); @@ -2215,7 +2241,7 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width, - height, out_width, out_height)){ + height, out_width, out_height, *five_taps)) { DSSERR("horizontal timing too tight\n"); return -EINVAL; } @@ -2352,7 +2378,7 @@ int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel, { enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); bool five_taps = true; - bool fieldmode = 0; + bool fieldmode = false; u16 in_height = oi->height; u16 in_width = oi->width; bool ilace = timings->interlace; @@ -2365,7 +2391,7 @@ int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel, out_height = oi->out_height == 0 ? oi->height : oi->out_height; if (ilace && oi->height == out_height) - fieldmode = 1; + fieldmode = true; if (ilace) { if (fieldmode) @@ -2396,7 +2422,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, bool mem_to_mem) { bool five_taps = true; - bool fieldmode = 0; + bool fieldmode = false; int r, cconv = 0; unsigned offset0, offset1; s32 row_inc; @@ -2417,7 +2443,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane, out_height = out_height == 0 ? height : out_height; if (ilace && height == out_height) - fieldmode = 1; + fieldmode = true; if (ilace) { if (fieldmode) @@ -2918,7 +2944,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, break; default: BUG(); - }; + } l = dispc_read_reg(DISPC_POL_FREQ(channel)); l |= FLD_VAL(onoff, 17, 17); @@ -3211,6 +3237,8 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_CONTROL3); DUMPREG(DISPC_CONFIG3); } + if (dss_has_feature(FEAT_MFLAG)) + DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE); #undef DUMPREG @@ -3285,6 +3313,8 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); if (dss_has_feature(FEAT_PRELOAD)) DUMPREG(i, DISPC_OVL_PRELOAD); + if (dss_has_feature(FEAT_MFLAG)) + DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); } #undef DISPC_REG @@ -3520,6 +3550,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = { .calc_core_clk = calc_core_clk_24xx, .num_fifos = 3, .no_framedone_tv = true, + .set_max_preload = false, }; static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { @@ -3539,6 +3570,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, .no_framedone_tv = true, + .set_max_preload = false, }; static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { @@ -3558,6 +3590,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, .no_framedone_tv = true, + .set_max_preload = false, }; static const struct dispc_features omap44xx_dispc_feats __initconst = { @@ -3577,6 +3610,7 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, .gfx_fifo_workaround = true, + .set_max_preload = true, }; static const struct dispc_features omap54xx_dispc_feats __initconst = { @@ -3597,6 +3631,7 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { .num_fifos = 5, .gfx_fifo_workaround = true, .mstandby_workaround = true, + .set_max_preload = true, }; static int __init dispc_init_features(struct platform_device *pdev) @@ -3734,6 +3769,8 @@ static int dispc_runtime_suspend(struct device *dev) static int dispc_runtime_resume(struct device *dev) { + _omap_dispc_initial_config(); + dispc_restore_context(); return 0; diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index de4863d21ab7..78edb449c763 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h @@ -40,6 +40,7 @@ #define DISPC_CONTROL3 0x0848 #define DISPC_CONFIG3 0x084C #define DISPC_MSTANDBY_CTRL 0x0858 +#define DISPC_GLOBAL_MFLAG_ATTRIBUTE 0x085C /* DISPC overlay registers */ #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ @@ -100,6 +101,8 @@ DISPC_FIR_COEF_V2_OFFSET(n, i)) #define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ DISPC_PRELOAD_OFFSET(n)) +#define DISPC_OVL_MFLAG_THRESHOLD(n) (DISPC_OVL_BASE(n) + \ + DISPC_MFLAG_THRESHOLD_OFFSET(n)) /* DISPC up/downsampling FIR filter coefficient structure */ struct dispc_coef { @@ -894,4 +897,21 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) return 0; } } + +static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane) +{ + switch (plane) { + case OMAP_DSS_GFX: + return 0x0860; + case OMAP_DSS_VIDEO1: + return 0x0864; + case OMAP_DSS_VIDEO2: + return 0x0868; + case OMAP_DSS_VIDEO3: + return 0x086c; + default: + BUG(); + return 0; + } +} #endif diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c index 21d7f77df702..f7b5f9561041 100644 --- a/drivers/video/omap2/dss/display-sysfs.c +++ b/drivers/video/omap2/dss/display-sysfs.c @@ -277,7 +277,7 @@ static ssize_t display_wss_store(struct device *dev, return size; } -static DEVICE_ATTR(name, S_IRUGO, display_name_show, NULL); +static DEVICE_ATTR(display_name, S_IRUGO, display_name_show, NULL); static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, display_enabled_show, display_enabled_store); static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, @@ -292,7 +292,7 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, display_wss_show, display_wss_store); static const struct attribute *display_sysfs_attrs[] = { - &dev_attr_name.attr, + &dev_attr_display_name.attr, &dev_attr_enabled.attr, &dev_attr_tear_elim.attr, &dev_attr_timings.attr, diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index fafe7c941a60..669a81fdf58e 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -266,7 +266,7 @@ void videomode_to_omap_video_timings(const struct videomode *vm, OMAPDSS_SIG_ACTIVE_LOW; ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ? OMAPDSS_SIG_ACTIVE_HIGH : - OMAPDSS_SIG_ACTIVE_HIGH; + OMAPDSS_SIG_ACTIVE_LOW; ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? OMAPDSS_DRIVE_SIG_RISING_EDGE : OMAPDSS_DRIVE_SIG_FALLING_EDGE; diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index ae1c8b9d39ca..7411f2674e16 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -550,7 +550,8 @@ static int dpi_init_regulator(void) vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi"); if (IS_ERR(vdds_dsi)) { - DSSERR("can't get VDDS_DSI regulator\n"); + if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) + DSSERR("can't get VDDS_DSI regulator\n"); return PTR_ERR(vdds_dsi); } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index a598b5812285..a820c37e323e 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -47,63 +47,73 @@ #define DSI_CATCH_MISSING_TE -struct dsi_reg { u16 idx; }; +struct dsi_reg { u16 module; u16 idx; }; -#define DSI_REG(idx) ((const struct dsi_reg) { idx }) +#define DSI_REG(mod, idx) ((const struct dsi_reg) { mod, idx }) -#define DSI_SZ_REGS SZ_1K /* DSI Protocol Engine */ -#define DSI_REVISION DSI_REG(0x0000) -#define DSI_SYSCONFIG DSI_REG(0x0010) -#define DSI_SYSSTATUS DSI_REG(0x0014) -#define DSI_IRQSTATUS DSI_REG(0x0018) -#define DSI_IRQENABLE DSI_REG(0x001C) -#define DSI_CTRL DSI_REG(0x0040) -#define DSI_GNQ DSI_REG(0x0044) -#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) -#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) -#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) -#define DSI_CLK_CTRL DSI_REG(0x0054) -#define DSI_TIMING1 DSI_REG(0x0058) -#define DSI_TIMING2 DSI_REG(0x005C) -#define DSI_VM_TIMING1 DSI_REG(0x0060) -#define DSI_VM_TIMING2 DSI_REG(0x0064) -#define DSI_VM_TIMING3 DSI_REG(0x0068) -#define DSI_CLK_TIMING DSI_REG(0x006C) -#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070) -#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074) -#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078) -#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C) -#define DSI_VM_TIMING4 DSI_REG(0x0080) -#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084) -#define DSI_VM_TIMING5 DSI_REG(0x0088) -#define DSI_VM_TIMING6 DSI_REG(0x008C) -#define DSI_VM_TIMING7 DSI_REG(0x0090) -#define DSI_STOPCLK_TIMING DSI_REG(0x0094) -#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20)) -#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20)) -#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20)) -#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20)) -#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20)) -#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20)) -#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20)) +#define DSI_PROTO 0 +#define DSI_PROTO_SZ 0x200 + +#define DSI_REVISION DSI_REG(DSI_PROTO, 0x0000) +#define DSI_SYSCONFIG DSI_REG(DSI_PROTO, 0x0010) +#define DSI_SYSSTATUS DSI_REG(DSI_PROTO, 0x0014) +#define DSI_IRQSTATUS DSI_REG(DSI_PROTO, 0x0018) +#define DSI_IRQENABLE DSI_REG(DSI_PROTO, 0x001C) +#define DSI_CTRL DSI_REG(DSI_PROTO, 0x0040) +#define DSI_GNQ DSI_REG(DSI_PROTO, 0x0044) +#define DSI_COMPLEXIO_CFG1 DSI_REG(DSI_PROTO, 0x0048) +#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(DSI_PROTO, 0x004C) +#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(DSI_PROTO, 0x0050) +#define DSI_CLK_CTRL DSI_REG(DSI_PROTO, 0x0054) +#define DSI_TIMING1 DSI_REG(DSI_PROTO, 0x0058) +#define DSI_TIMING2 DSI_REG(DSI_PROTO, 0x005C) +#define DSI_VM_TIMING1 DSI_REG(DSI_PROTO, 0x0060) +#define DSI_VM_TIMING2 DSI_REG(DSI_PROTO, 0x0064) +#define DSI_VM_TIMING3 DSI_REG(DSI_PROTO, 0x0068) +#define DSI_CLK_TIMING DSI_REG(DSI_PROTO, 0x006C) +#define DSI_TX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0070) +#define DSI_RX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0074) +#define DSI_COMPLEXIO_CFG2 DSI_REG(DSI_PROTO, 0x0078) +#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(DSI_PROTO, 0x007C) +#define DSI_VM_TIMING4 DSI_REG(DSI_PROTO, 0x0080) +#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(DSI_PROTO, 0x0084) +#define DSI_VM_TIMING5 DSI_REG(DSI_PROTO, 0x0088) +#define DSI_VM_TIMING6 DSI_REG(DSI_PROTO, 0x008C) +#define DSI_VM_TIMING7 DSI_REG(DSI_PROTO, 0x0090) +#define DSI_STOPCLK_TIMING DSI_REG(DSI_PROTO, 0x0094) +#define DSI_VC_CTRL(n) DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20)) +#define DSI_VC_TE(n) DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20)) +#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(DSI_PROTO, 0x010C + (n * 0x20)) +#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20)) +#define DSI_VC_IRQSTATUS(n) DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20)) +#define DSI_VC_IRQENABLE(n) DSI_REG(DSI_PROTO, 0x011C + (n * 0x20)) /* DSIPHY_SCP */ -#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) -#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) -#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) -#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) -#define DSI_DSIPHY_CFG10 DSI_REG(0x200 + 0x0028) +#define DSI_PHY 1 +#define DSI_PHY_OFFSET 0x200 +#define DSI_PHY_SZ 0x40 + +#define DSI_DSIPHY_CFG0 DSI_REG(DSI_PHY, 0x0000) +#define DSI_DSIPHY_CFG1 DSI_REG(DSI_PHY, 0x0004) +#define DSI_DSIPHY_CFG2 DSI_REG(DSI_PHY, 0x0008) +#define DSI_DSIPHY_CFG5 DSI_REG(DSI_PHY, 0x0014) +#define DSI_DSIPHY_CFG10 DSI_REG(DSI_PHY, 0x0028) /* DSI_PLL_CTRL_SCP */ -#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000) -#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004) -#define DSI_PLL_GO DSI_REG(0x300 + 0x0008) -#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) -#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) +#define DSI_PLL 2 +#define DSI_PLL_OFFSET 0x300 +#define DSI_PLL_SZ 0x20 + +#define DSI_PLL_CONTROL DSI_REG(DSI_PLL, 0x0000) +#define DSI_PLL_STATUS DSI_REG(DSI_PLL, 0x0004) +#define DSI_PLL_GO DSI_REG(DSI_PLL, 0x0008) +#define DSI_PLL_CONFIGURATION1 DSI_REG(DSI_PLL, 0x000C) +#define DSI_PLL_CONFIGURATION2 DSI_REG(DSI_PLL, 0x0010) #define REG_GET(dsidev, idx, start, end) \ FLD_GET(dsi_read_reg(dsidev, idx), start, end) @@ -277,7 +287,9 @@ struct dsi_clk_calc_ctx { struct dsi_data { struct platform_device *pdev; - void __iomem *base; + void __iomem *proto_base; + void __iomem *phy_base; + void __iomem *pll_base; int module_id; @@ -297,7 +309,8 @@ struct dsi_data { struct { enum dsi_vc_source source; struct omap_dss_device *dssdev; - enum fifo_size fifo_size; + enum fifo_size tx_fifo_size; + enum fifo_size rx_fifo_size; int vc_id; } vc[4]; @@ -312,7 +325,7 @@ struct dsi_data { struct dsi_isr_tables isr_tables_copy; int update_channel; -#ifdef DEBUG +#ifdef DSI_PERF_MEASURE unsigned update_bytes; #endif @@ -334,7 +347,7 @@ struct dsi_data { u32 errors; spinlock_t errors_lock; -#ifdef DEBUG +#ifdef DSI_PERF_MEASURE ktime_t perf_setup_time; ktime_t perf_start_time; #endif @@ -373,7 +386,7 @@ struct dsi_packet_sent_handler_data { struct completion *completion; }; -#ifdef DEBUG +#ifdef DSI_PERF_MEASURE static bool dsi_perf; module_param(dsi_perf, bool, 0644); #endif @@ -413,16 +426,32 @@ static inline void dsi_write_reg(struct platform_device *dsidev, const struct dsi_reg idx, u32 val) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + void __iomem *base; + + switch(idx.module) { + case DSI_PROTO: base = dsi->proto_base; break; + case DSI_PHY: base = dsi->phy_base; break; + case DSI_PLL: base = dsi->pll_base; break; + default: return; + } - __raw_writel(val, dsi->base + idx.idx); + __raw_writel(val, base + idx.idx); } static inline u32 dsi_read_reg(struct platform_device *dsidev, const struct dsi_reg idx) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + void __iomem *base; - return __raw_readl(dsi->base + idx.idx); + switch(idx.module) { + case DSI_PROTO: base = dsi->proto_base; break; + case DSI_PHY: base = dsi->phy_base; break; + case DSI_PLL: base = dsi->pll_base; break; + default: return 0; + } + + return __raw_readl(base + idx.idx); } static void dsi_bus_lock(struct omap_dss_device *dssdev) @@ -497,7 +526,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) } } -#ifdef DEBUG +#ifdef DSI_PERF_MEASURE static void dsi_perf_mark_setup(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); @@ -1129,7 +1158,8 @@ static int dsi_regulator_init(struct platform_device *dsidev) vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO"); if (IS_ERR(vdds_dsi)) { - DSSERR("can't get VDDS_DSI regulator\n"); + if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) + DSSERR("can't get VDDS_DSI regulator\n"); return PTR_ERR(vdds_dsi); } @@ -2427,14 +2457,14 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev, int add = 0; int i; - dsi->vc[0].fifo_size = size1; - dsi->vc[1].fifo_size = size2; - dsi->vc[2].fifo_size = size3; - dsi->vc[3].fifo_size = size4; + dsi->vc[0].tx_fifo_size = size1; + dsi->vc[1].tx_fifo_size = size2; + dsi->vc[2].tx_fifo_size = size3; + dsi->vc[3].tx_fifo_size = size4; for (i = 0; i < 4; i++) { u8 v; - int size = dsi->vc[i].fifo_size; + int size = dsi->vc[i].tx_fifo_size; if (add + size > 4) { DSSERR("Illegal FIFO configuration\n"); @@ -2460,14 +2490,14 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev, int add = 0; int i; - dsi->vc[0].fifo_size = size1; - dsi->vc[1].fifo_size = size2; - dsi->vc[2].fifo_size = size3; - dsi->vc[3].fifo_size = size4; + dsi->vc[0].rx_fifo_size = size1; + dsi->vc[1].rx_fifo_size = size2; + dsi->vc[2].rx_fifo_size = size3; + dsi->vc[3].rx_fifo_size = size4; for (i = 0; i < 4; i++) { u8 v; - int size = dsi->vc[i].fifo_size; + int size = dsi->vc[i].rx_fifo_size; if (add + size > 4) { DSSERR("Illegal FIFO configuration\n"); @@ -2920,7 +2950,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel, DSSDBG("dsi_vc_send_long, %d bytes\n", len); /* len + header */ - if (dsi->vc[channel].fifo_size * 32 * 4 < len + 4) { + if (dsi->vc[channel].tx_fifo_size * 32 * 4 < len + 4) { DSSERR("unable to send long packet: packet too long.\n"); return -EINVAL; } @@ -4066,7 +4096,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) default: r = -EINVAL; goto err_pix_fmt; - }; + } dsi_if_enable(dsidev, false); dsi_vc_enable(dsidev, channel, false); @@ -4277,7 +4307,7 @@ static int dsi_update(struct omap_dss_device *dssdev, int channel, dw = dsi->timings.x_res; dh = dsi->timings.y_res; -#ifdef DEBUG +#ifdef DSI_PERF_MEASURE dsi->update_bytes = dw * dh * dsi_get_pixel_size(dsi->pix_fmt) / 8; #endif @@ -5345,8 +5375,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev) { u32 rev; int r, i; - struct resource *dsi_mem; struct dsi_data *dsi; + struct resource *res; + struct resource temp_res; dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) @@ -5376,16 +5407,64 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dsi->te_timer.function = dsi_te_timeout; dsi->te_timer.data = 0; #endif - dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); - if (!dsi_mem) { - DSSERR("can't get IORESOURCE_MEM DSI\n"); - return -EINVAL; + + res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "proto"); + if (!res) { + res = platform_get_resource(dsidev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get IORESOURCE_MEM DSI\n"); + return -EINVAL; + } + + temp_res.start = res->start; + temp_res.end = temp_res.start + DSI_PROTO_SZ - 1; + res = &temp_res; + } + + dsi->proto_base = devm_ioremap(&dsidev->dev, res->start, + resource_size(res)); + if (!dsi->proto_base) { + DSSERR("can't ioremap DSI protocol engine\n"); + return -ENOMEM; + } + + res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "phy"); + if (!res) { + res = platform_get_resource(dsidev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get IORESOURCE_MEM DSI\n"); + return -EINVAL; + } + + temp_res.start = res->start + DSI_PHY_OFFSET; + temp_res.end = temp_res.start + DSI_PHY_SZ - 1; + res = &temp_res; + } + + dsi->phy_base = devm_ioremap(&dsidev->dev, res->start, + resource_size(res)); + if (!dsi->proto_base) { + DSSERR("can't ioremap DSI PHY\n"); + return -ENOMEM; + } + + res = platform_get_resource_byname(dsidev, IORESOURCE_MEM, "pll"); + if (!res) { + res = platform_get_resource(dsidev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get IORESOURCE_MEM DSI\n"); + return -EINVAL; + } + + temp_res.start = res->start + DSI_PLL_OFFSET; + temp_res.end = temp_res.start + DSI_PLL_SZ - 1; + res = &temp_res; } - dsi->base = devm_ioremap(&dsidev->dev, dsi_mem->start, - resource_size(dsi_mem)); - if (!dsi->base) { - DSSERR("can't ioremap DSI\n"); + dsi->pll_base = devm_ioremap(&dsidev->dev, res->start, + resource_size(res)); + if (!dsi->proto_base) { + DSSERR("can't ioremap DSI PLL\n"); return -ENOMEM; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 2acc6615b984..057f24c8a332 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -418,8 +418,8 @@ int venc_init_platform_driver(void) __init; void venc_uninit_platform_driver(void) __exit; /* HDMI */ -int hdmi_init_platform_driver(void) __init; -void hdmi_uninit_platform_driver(void) __exit; +int hdmi4_init_platform_driver(void) __init; +void hdmi4_uninit_platform_driver(void) __exit; /* RFBI */ int rfbi_init_platform_driver(void) __init; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b9cfebb378a2..7f8969191dc6 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -613,6 +613,7 @@ static const enum dss_feat_id omap5_dss_feat_list[] = { FEAT_DSI_PLL_SELFREQDCO, FEAT_DSI_PLL_REFSEL, FEAT_DSI_PHY_DCC, + FEAT_MFLAG, }; /* OMAP2 DSS Features */ @@ -789,50 +790,6 @@ static const struct omap_dss_features omap5_dss_features = { .burst_size_unit = 16, }; -#if defined(CONFIG_OMAP4_DSS_HDMI) -/* HDMI OMAP4 Functions*/ -static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { - - .video_configure = ti_hdmi_4xxx_basic_configure, - .phy_enable = ti_hdmi_4xxx_phy_enable, - .phy_disable = ti_hdmi_4xxx_phy_disable, - .read_edid = ti_hdmi_4xxx_read_edid, - .pll_enable = ti_hdmi_4xxx_pll_enable, - .pll_disable = ti_hdmi_4xxx_pll_disable, - .video_enable = ti_hdmi_4xxx_wp_video_start, - .video_disable = ti_hdmi_4xxx_wp_video_stop, - .dump_wrapper = ti_hdmi_4xxx_wp_dump, - .dump_core = ti_hdmi_4xxx_core_dump, - .dump_pll = ti_hdmi_4xxx_pll_dump, - .dump_phy = ti_hdmi_4xxx_phy_dump, -#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) - .audio_enable = ti_hdmi_4xxx_wp_audio_enable, - .audio_disable = ti_hdmi_4xxx_wp_audio_disable, - .audio_start = ti_hdmi_4xxx_audio_start, - .audio_stop = ti_hdmi_4xxx_audio_stop, - .audio_config = ti_hdmi_4xxx_audio_config, - .audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port, -#endif - -}; - -void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data, - enum omapdss_version version) -{ - switch (version) { - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - ip_data->ops = &omap4_hdmi_functions; - break; - default: - ip_data->ops = NULL; - } - - WARN_ON(ip_data->ops == NULL); -} -#endif - /* Functions returning values related to a DSS feature */ int dss_feat_get_num_mgrs(void) { diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 489b9bec4a6d..e3ef3b714896 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -20,10 +20,6 @@ #ifndef __OMAP2_DSS_FEATURES_H #define __OMAP2_DSS_FEATURES_H -#if defined(CONFIG_OMAP4_DSS_HDMI) -#include "ti_hdmi.h" -#endif - #define MAX_DSS_MANAGERS 4 #define MAX_DSS_OVERLAYS 4 #define MAX_DSS_LCD_MANAGERS 3 @@ -68,6 +64,7 @@ enum dss_feat_id { FEAT_DSI_PLL_SELFREQDCO, FEAT_DSI_PLL_REFSEL, FEAT_DSI_PHY_DCC, + FEAT_MFLAG, }; /* DSS register field id */ @@ -117,8 +114,4 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type); bool dss_has_feature(enum dss_feat_id id); void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); void dss_features_init(enum omapdss_version version); -#if defined(CONFIG_OMAP4_DSS_HDMI) -void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data, - enum omapdss_version version); -#endif #endif diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c deleted file mode 100644 index 82a964074993..000000000000 --- a/drivers/video/omap2/dss/hdmi.c +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * hdmi.c - * - * HDMI interface DSS driver setting for TI's OMAP4 family of processor. - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ - * Authors: Yong Zhi - * Mythri pk <mythripk@ti.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#define DSS_SUBSYS_NAME "HDMI" - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/delay.h> -#include <linux/string.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/clk.h> -#include <linux/gpio.h> -#include <linux/regulator/consumer.h> -#include <video/omapdss.h> - -#include "ti_hdmi.h" -#include "dss.h" -#include "dss_features.h" - -#define HDMI_WP 0x0 -#define HDMI_CORE_SYS 0x400 -#define HDMI_CORE_AV 0x900 -#define HDMI_PLLCTRL 0x200 -#define HDMI_PHY 0x300 - -/* HDMI EDID Length move this */ -#define HDMI_EDID_MAX_LENGTH 256 -#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 -#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 -#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 -#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 -#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 - -#define HDMI_DEFAULT_REGN 16 -#define HDMI_DEFAULT_REGM2 1 - -static struct { - struct mutex lock; - struct platform_device *pdev; - - struct hdmi_ip_data ip_data; - - struct clk *sys_clk; - struct regulator *vdda_hdmi_dac_reg; - - bool core_enabled; - - struct omap_dss_device output; -} hdmi; - -/* - * Logic for the below structure : - * user enters the CEA or VESA timings by specifying the HDMI/DVI code. - * There is a correspondence between CEA/VESA timing and code, please - * refer to section 6.3 in HDMI 1.3 specification for timing code. - * - * In the below structure, cea_vesa_timings corresponds to all OMAP4 - * supported CEA and VESA timing values.code_cea corresponds to the CEA - * code, It is used to get the timing from cea_vesa_timing array.Similarly - * with code_vesa. Code_index is used for back mapping, that is once EDID - * is read from the TV, EDID is parsed to find the timing values and then - * map it to corresponding CEA or VESA index. - */ - -static const struct hdmi_config cea_timings[] = { - { - { 640, 480, 25200, 96, 16, 48, 2, 10, 33, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 1, HDMI_HDMI }, - }, - { - { 720, 480, 27027, 62, 16, 60, 6, 9, 30, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 2, HDMI_HDMI }, - }, - { - { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 4, HDMI_HDMI }, - }, - { - { 1920, 540, 74250, 44, 88, 148, 5, 2, 15, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - true, }, - { 5, HDMI_HDMI }, - }, - { - { 1440, 240, 27027, 124, 38, 114, 3, 4, 15, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - true, }, - { 6, HDMI_HDMI }, - }, - { - { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 16, HDMI_HDMI }, - }, - { - { 720, 576, 27000, 64, 12, 68, 5, 5, 39, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 17, HDMI_HDMI }, - }, - { - { 1280, 720, 74250, 40, 440, 220, 5, 5, 20, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 19, HDMI_HDMI }, - }, - { - { 1920, 540, 74250, 44, 528, 148, 5, 2, 15, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - true, }, - { 20, HDMI_HDMI }, - }, - { - { 1440, 288, 27000, 126, 24, 138, 3, 2, 19, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - true, }, - { 21, HDMI_HDMI }, - }, - { - { 1440, 576, 54000, 128, 24, 136, 5, 5, 39, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 29, HDMI_HDMI }, - }, - { - { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 31, HDMI_HDMI }, - }, - { - { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 32, HDMI_HDMI }, - }, - { - { 2880, 480, 108108, 248, 64, 240, 6, 9, 30, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 35, HDMI_HDMI }, - }, - { - { 2880, 576, 108000, 256, 48, 272, 5, 5, 39, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 37, HDMI_HDMI }, - }, -}; - -static const struct hdmi_config vesa_timings[] = { -/* VESA From Here */ - { - { 640, 480, 25175, 96, 16, 48, 2, 11, 31, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 4, HDMI_DVI }, - }, - { - { 800, 600, 40000, 128, 40, 88, 4, 1, 23, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 9, HDMI_DVI }, - }, - { - { 848, 480, 33750, 112, 16, 112, 8, 6, 23, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0xE, HDMI_DVI }, - }, - { - { 1280, 768, 79500, 128, 64, 192, 7, 3, 20, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x17, HDMI_DVI }, - }, - { - { 1280, 800, 83500, 128, 72, 200, 6, 3, 22, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x1C, HDMI_DVI }, - }, - { - { 1360, 768, 85500, 112, 64, 256, 6, 3, 18, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x27, HDMI_DVI }, - }, - { - { 1280, 960, 108000, 112, 96, 312, 3, 1, 36, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x20, HDMI_DVI }, - }, - { - { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x23, HDMI_DVI }, - }, - { - { 1024, 768, 65000, 136, 24, 160, 6, 3, 29, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x10, HDMI_DVI }, - }, - { - { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x2A, HDMI_DVI }, - }, - { - { 1440, 900, 106500, 152, 80, 232, 6, 3, 25, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x2F, HDMI_DVI }, - }, - { - { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, - false, }, - { 0x3A, HDMI_DVI }, - }, - { - { 1366, 768, 85500, 143, 70, 213, 3, 3, 24, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x51, HDMI_DVI }, - }, - { - { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x52, HDMI_DVI }, - }, - { - { 1280, 768, 68250, 32, 48, 80, 7, 3, 12, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x16, HDMI_DVI }, - }, - { - { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x29, HDMI_DVI }, - }, - { - { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x39, HDMI_DVI }, - }, - { - { 1280, 800, 79500, 32, 48, 80, 6, 3, 14, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x1B, HDMI_DVI }, - }, - { - { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, - OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x55, HDMI_DVI }, - }, - { - { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26, - OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, - false, }, - { 0x44, HDMI_DVI }, - }, -}; - -static int hdmi_runtime_get(void) -{ - int r; - - DSSDBG("hdmi_runtime_get\n"); - - r = pm_runtime_get_sync(&hdmi.pdev->dev); - WARN_ON(r < 0); - if (r < 0) - return r; - - return 0; -} - -static void hdmi_runtime_put(void) -{ - int r; - - DSSDBG("hdmi_runtime_put\n"); - - r = pm_runtime_put_sync(&hdmi.pdev->dev); - WARN_ON(r < 0 && r != -ENOSYS); -} - -static int hdmi_init_regulator(void) -{ - struct regulator *reg; - - if (hdmi.vdda_hdmi_dac_reg != NULL) - return 0; - - reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); - - /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ - if (IS_ERR(reg)) - reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC"); - - if (IS_ERR(reg)) { - DSSERR("can't get VDDA_HDMI_DAC regulator\n"); - return PTR_ERR(reg); - } - - hdmi.vdda_hdmi_dac_reg = reg; - - return 0; -} - -static const struct hdmi_config *hdmi_find_timing( - const struct hdmi_config *timings_arr, - int len) -{ - int i; - - for (i = 0; i < len; i++) { - if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code) - return &timings_arr[i]; - } - return NULL; -} - -static const struct hdmi_config *hdmi_get_timings(void) -{ - const struct hdmi_config *arr; - int len; - - if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) { - arr = vesa_timings; - len = ARRAY_SIZE(vesa_timings); - } else { - arr = cea_timings; - len = ARRAY_SIZE(cea_timings); - } - - return hdmi_find_timing(arr, len); -} - -static bool hdmi_timings_compare(struct omap_video_timings *timing1, - const struct omap_video_timings *timing2) -{ - int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; - - if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == - DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && - (timing2->x_res == timing1->x_res) && - (timing2->y_res == timing1->y_res)) { - - timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; - timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; - timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; - timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; - - DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ - "timing2_hsync = %d timing2_vsync = %d\n", - timing1_hsync, timing1_vsync, - timing2_hsync, timing2_vsync); - - if ((timing1_hsync == timing2_hsync) && - (timing1_vsync == timing2_vsync)) { - return true; - } - } - return false; -} - -static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) -{ - int i; - struct hdmi_cm cm = {-1}; - DSSDBG("hdmi_get_code\n"); - - for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { - if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { - cm = cea_timings[i].cm; - goto end; - } - } - for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { - if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { - cm = vesa_timings[i].cm; - goto end; - } - } - -end: return cm; - -} - -static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, - struct hdmi_pll_info *pi) -{ - unsigned long clkin, refclk; - u32 mf; - - clkin = clk_get_rate(hdmi.sys_clk) / 10000; - /* - * Input clock is predivided by N + 1 - * out put of which is reference clk - */ - - pi->regn = HDMI_DEFAULT_REGN; - - refclk = clkin / pi->regn; - - pi->regm2 = HDMI_DEFAULT_REGM2; - - /* - * multiplier is pixel_clk/ref_clk - * Multiplying by 100 to avoid fractional part removal - */ - pi->regm = phy * pi->regm2 / refclk; - - /* - * fractional multiplier is remainder of the difference between - * multiplier and actual phy(required pixel clock thus should be - * multiplied by 2^18(262144) divided by the reference clock - */ - mf = (phy - pi->regm / pi->regm2 * refclk) * 262144; - pi->regmf = pi->regm2 * mf / refclk; - - /* - * Dcofreq should be set to 1 if required pixel clock - * is greater than 1000MHz - */ - pi->dcofreq = phy > 1000 * 100; - pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; - - /* Set the reference clock to sysclk reference */ - pi->refsel = HDMI_REFSEL_SYSCLK; - - DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); - DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); -} - -static int hdmi_power_on_core(struct omap_dss_device *dssdev) -{ - int r; - - r = regulator_enable(hdmi.vdda_hdmi_dac_reg); - if (r) - return r; - - r = hdmi_runtime_get(); - if (r) - goto err_runtime_get; - - /* Make selection of HDMI in DSS */ - dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); - - hdmi.core_enabled = true; - - return 0; - -err_runtime_get: - regulator_disable(hdmi.vdda_hdmi_dac_reg); - - return r; -} - -static void hdmi_power_off_core(struct omap_dss_device *dssdev) -{ - hdmi.core_enabled = false; - - hdmi_runtime_put(); - regulator_disable(hdmi.vdda_hdmi_dac_reg); -} - -static int hdmi_power_on_full(struct omap_dss_device *dssdev) -{ - int r; - struct omap_video_timings *p; - struct omap_overlay_manager *mgr = hdmi.output.manager; - unsigned long phy; - - r = hdmi_power_on_core(dssdev); - if (r) - return r; - - dss_mgr_disable(mgr); - - p = &hdmi.ip_data.cfg.timings; - - DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); - - phy = p->pixel_clock; - - hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); - - hdmi.ip_data.ops->video_disable(&hdmi.ip_data); - - /* config the PLL and PHY hdmi_set_pll_pwrfirst */ - r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); - if (r) { - DSSDBG("Failed to lock PLL\n"); - goto err_pll_enable; - } - - r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); - if (r) { - DSSDBG("Failed to start PHY\n"); - goto err_phy_enable; - } - - hdmi.ip_data.ops->video_configure(&hdmi.ip_data); - - /* bypass TV gamma table */ - dispc_enable_gamma_table(0); - - /* tv size */ - dss_mgr_set_timings(mgr, p); - - r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); - if (r) - goto err_vid_enable; - - r = dss_mgr_enable(mgr); - if (r) - goto err_mgr_enable; - - return 0; - -err_mgr_enable: - hdmi.ip_data.ops->video_disable(&hdmi.ip_data); -err_vid_enable: - hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); -err_phy_enable: - hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); -err_pll_enable: - hdmi_power_off_core(dssdev); - return -EIO; -} - -static void hdmi_power_off_full(struct omap_dss_device *dssdev) -{ - struct omap_overlay_manager *mgr = hdmi.output.manager; - - dss_mgr_disable(mgr); - - hdmi.ip_data.ops->video_disable(&hdmi.ip_data); - hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); - hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); - - hdmi_power_off_core(dssdev); -} - -static int hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - struct hdmi_cm cm; - - cm = hdmi_get_code(timings); - if (cm.code == -1) { - return -EINVAL; - } - - return 0; - -} - -static void hdmi_display_set_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - struct hdmi_cm cm; - const struct hdmi_config *t; - - mutex_lock(&hdmi.lock); - - cm = hdmi_get_code(timings); - hdmi.ip_data.cfg.cm = cm; - - t = hdmi_get_timings(); - if (t != NULL) { - hdmi.ip_data.cfg = *t; - - dispc_set_tv_pclk(t->timings.pixel_clock * 1000); - } - - mutex_unlock(&hdmi.lock); -} - -static void hdmi_display_get_timings(struct omap_dss_device *dssdev, - struct omap_video_timings *timings) -{ - const struct hdmi_config *cfg; - - cfg = hdmi_get_timings(); - if (cfg == NULL) - cfg = &vesa_timings[0]; - - memcpy(timings, &cfg->timings, sizeof(cfg->timings)); -} - -static void hdmi_dump_regs(struct seq_file *s) -{ - mutex_lock(&hdmi.lock); - - if (hdmi_runtime_get()) { - mutex_unlock(&hdmi.lock); - return; - } - - hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); - hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); - hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); - hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); - - hdmi_runtime_put(); - mutex_unlock(&hdmi.lock); -} - -static int read_edid(u8 *buf, int len) -{ - int r; - - mutex_lock(&hdmi.lock); - - r = hdmi_runtime_get(); - BUG_ON(r); - - r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); - - hdmi_runtime_put(); - mutex_unlock(&hdmi.lock); - - return r; -} - -static int hdmi_display_enable(struct omap_dss_device *dssdev) -{ - struct omap_dss_device *out = &hdmi.output; - int r = 0; - - DSSDBG("ENTER hdmi_display_enable\n"); - - mutex_lock(&hdmi.lock); - - if (out == NULL || out->manager == NULL) { - DSSERR("failed to enable display: no output/manager\n"); - r = -ENODEV; - goto err0; - } - - r = hdmi_power_on_full(dssdev); - if (r) { - DSSERR("failed to power on device\n"); - goto err0; - } - - mutex_unlock(&hdmi.lock); - return 0; - -err0: - mutex_unlock(&hdmi.lock); - return r; -} - -static void hdmi_display_disable(struct omap_dss_device *dssdev) -{ - DSSDBG("Enter hdmi_display_disable\n"); - - mutex_lock(&hdmi.lock); - - hdmi_power_off_full(dssdev); - - mutex_unlock(&hdmi.lock); -} - -static int hdmi_core_enable(struct omap_dss_device *dssdev) -{ - int r = 0; - - DSSDBG("ENTER omapdss_hdmi_core_enable\n"); - - mutex_lock(&hdmi.lock); - - r = hdmi_power_on_core(dssdev); - if (r) { - DSSERR("failed to power on device\n"); - goto err0; - } - - mutex_unlock(&hdmi.lock); - return 0; - -err0: - mutex_unlock(&hdmi.lock); - return r; -} - -static void hdmi_core_disable(struct omap_dss_device *dssdev) -{ - DSSDBG("Enter omapdss_hdmi_core_disable\n"); - - mutex_lock(&hdmi.lock); - - hdmi_power_off_core(dssdev); - - mutex_unlock(&hdmi.lock); -} - -static int hdmi_get_clocks(struct platform_device *pdev) -{ - struct clk *clk; - - clk = devm_clk_get(&pdev->dev, "sys_clk"); - if (IS_ERR(clk)) { - DSSERR("can't get sys_clk\n"); - return PTR_ERR(clk); - } - - hdmi.sys_clk = clk; - - return 0; -} - -#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) -int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) -{ - u32 deep_color; - bool deep_color_correct = false; - u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock; - - if (n == NULL || cts == NULL) - return -EINVAL; - - /* TODO: When implemented, query deep color mode here. */ - deep_color = 100; - - /* - * When using deep color, the default N value (as in the HDMI - * specification) yields to an non-integer CTS. Hence, we - * modify it while keeping the restrictions described in - * section 7.2.1 of the HDMI 1.4a specification. - */ - switch (sample_freq) { - case 32000: - case 48000: - case 96000: - case 192000: - if (deep_color == 125) - if (pclk == 27027 || pclk == 74250) - deep_color_correct = true; - if (deep_color == 150) - if (pclk == 27027) - deep_color_correct = true; - break; - case 44100: - case 88200: - case 176400: - if (deep_color == 125) - if (pclk == 27027) - deep_color_correct = true; - break; - default: - return -EINVAL; - } - - if (deep_color_correct) { - switch (sample_freq) { - case 32000: - *n = 8192; - break; - case 44100: - *n = 12544; - break; - case 48000: - *n = 8192; - break; - case 88200: - *n = 25088; - break; - case 96000: - *n = 16384; - break; - case 176400: - *n = 50176; - break; - case 192000: - *n = 32768; - break; - default: - return -EINVAL; - } - } else { - switch (sample_freq) { - case 32000: - *n = 4096; - break; - case 44100: - *n = 6272; - break; - case 48000: - *n = 6144; - break; - case 88200: - *n = 12544; - break; - case 96000: - *n = 12288; - break; - case 176400: - *n = 25088; - break; - case 192000: - *n = 24576; - break; - default: - return -EINVAL; - } - } - /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ - *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); - - return 0; -} - -static bool hdmi_mode_has_audio(void) -{ - if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI) - return true; - else - return false; -} - -#endif - -static int hdmi_connect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) -{ - struct omap_overlay_manager *mgr; - int r; - - dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version()); - - r = hdmi_init_regulator(); - if (r) - return r; - - mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); - if (!mgr) - return -ENODEV; - - r = dss_mgr_connect(mgr, dssdev); - if (r) - return r; - - r = omapdss_output_set_device(dssdev, dst); - if (r) { - DSSERR("failed to connect output to new device: %s\n", - dst->name); - dss_mgr_disconnect(mgr, dssdev); - return r; - } - - return 0; -} - -static void hdmi_disconnect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) -{ - WARN_ON(dst != dssdev->dst); - - if (dst != dssdev->dst) - return; - - omapdss_output_unset_device(dssdev); - - if (dssdev->manager) - dss_mgr_disconnect(dssdev->manager, dssdev); -} - -static int hdmi_read_edid(struct omap_dss_device *dssdev, - u8 *edid, int len) -{ - bool need_enable; - int r; - - need_enable = hdmi.core_enabled == false; - - if (need_enable) { - r = hdmi_core_enable(dssdev); - if (r) - return r; - } - - r = read_edid(edid, len); - - if (need_enable) - hdmi_core_disable(dssdev); - - return r; -} - -#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) -static int hdmi_audio_enable(struct omap_dss_device *dssdev) -{ - int r; - - mutex_lock(&hdmi.lock); - - if (!hdmi_mode_has_audio()) { - r = -EPERM; - goto err; - } - - - r = hdmi.ip_data.ops->audio_enable(&hdmi.ip_data); - if (r) - goto err; - - mutex_unlock(&hdmi.lock); - return 0; - -err: - mutex_unlock(&hdmi.lock); - return r; -} - -static void hdmi_audio_disable(struct omap_dss_device *dssdev) -{ - hdmi.ip_data.ops->audio_disable(&hdmi.ip_data); -} - -static int hdmi_audio_start(struct omap_dss_device *dssdev) -{ - return hdmi.ip_data.ops->audio_start(&hdmi.ip_data); -} - -static void hdmi_audio_stop(struct omap_dss_device *dssdev) -{ - hdmi.ip_data.ops->audio_stop(&hdmi.ip_data); -} - -static bool hdmi_audio_supported(struct omap_dss_device *dssdev) -{ - bool r; - - mutex_lock(&hdmi.lock); - - r = hdmi_mode_has_audio(); - - mutex_unlock(&hdmi.lock); - return r; -} - -static int hdmi_audio_config(struct omap_dss_device *dssdev, - struct omap_dss_audio *audio) -{ - int r; - - mutex_lock(&hdmi.lock); - - if (!hdmi_mode_has_audio()) { - r = -EPERM; - goto err; - } - - r = hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio); - if (r) - goto err; - - mutex_unlock(&hdmi.lock); - return 0; - -err: - mutex_unlock(&hdmi.lock); - return r; -} -#else -static int hdmi_audio_enable(struct omap_dss_device *dssdev) -{ - return -EPERM; -} - -static void hdmi_audio_disable(struct omap_dss_device *dssdev) -{ -} - -static int hdmi_audio_start(struct omap_dss_device *dssdev) -{ - return -EPERM; -} - -static void hdmi_audio_stop(struct omap_dss_device *dssdev) -{ -} - -static bool hdmi_audio_supported(struct omap_dss_device *dssdev) -{ - return false; -} - -static int hdmi_audio_config(struct omap_dss_device *dssdev, - struct omap_dss_audio *audio) -{ - return -EPERM; -} -#endif - -static const struct omapdss_hdmi_ops hdmi_ops = { - .connect = hdmi_connect, - .disconnect = hdmi_disconnect, - - .enable = hdmi_display_enable, - .disable = hdmi_display_disable, - - .check_timings = hdmi_display_check_timing, - .set_timings = hdmi_display_set_timing, - .get_timings = hdmi_display_get_timings, - - .read_edid = hdmi_read_edid, - - .audio_enable = hdmi_audio_enable, - .audio_disable = hdmi_audio_disable, - .audio_start = hdmi_audio_start, - .audio_stop = hdmi_audio_stop, - .audio_supported = hdmi_audio_supported, - .audio_config = hdmi_audio_config, -}; - -static void hdmi_init_output(struct platform_device *pdev) -{ - struct omap_dss_device *out = &hdmi.output; - - out->dev = &pdev->dev; - out->id = OMAP_DSS_OUTPUT_HDMI; - out->output_type = OMAP_DISPLAY_TYPE_HDMI; - out->name = "hdmi.0"; - out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; - out->ops.hdmi = &hdmi_ops; - out->owner = THIS_MODULE; - - omapdss_register_output(out); -} - -static void __exit hdmi_uninit_output(struct platform_device *pdev) -{ - struct omap_dss_device *out = &hdmi.output; - - omapdss_unregister_output(out); -} - -/* HDMI HW IP initialisation */ -static int omapdss_hdmihw_probe(struct platform_device *pdev) -{ - struct resource *res; - int r; - - hdmi.pdev = pdev; - - mutex_init(&hdmi.lock); - mutex_init(&hdmi.ip_data.lock); - - res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); - - /* Base address taken from platform */ - hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hdmi.ip_data.base_wp)) - return PTR_ERR(hdmi.ip_data.base_wp); - - hdmi.ip_data.irq = platform_get_irq(pdev, 0); - if (hdmi.ip_data.irq < 0) { - DSSERR("platform_get_irq failed\n"); - return -ENODEV; - } - - r = hdmi_get_clocks(pdev); - if (r) { - DSSERR("can't get clocks\n"); - return r; - } - - pm_runtime_enable(&pdev->dev); - - hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; - hdmi.ip_data.core_av_offset = HDMI_CORE_AV; - hdmi.ip_data.pll_offset = HDMI_PLLCTRL; - hdmi.ip_data.phy_offset = HDMI_PHY; - - hdmi_init_output(pdev); - - dss_debugfs_create_file("hdmi", hdmi_dump_regs); - - return 0; -} - -static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) -{ - hdmi_uninit_output(pdev); - - pm_runtime_disable(&pdev->dev); - - return 0; -} - -static int hdmi_runtime_suspend(struct device *dev) -{ - clk_disable_unprepare(hdmi.sys_clk); - - dispc_runtime_put(); - - return 0; -} - -static int hdmi_runtime_resume(struct device *dev) -{ - int r; - - r = dispc_runtime_get(); - if (r < 0) - return r; - - clk_prepare_enable(hdmi.sys_clk); - - return 0; -} - -static const struct dev_pm_ops hdmi_pm_ops = { - .runtime_suspend = hdmi_runtime_suspend, - .runtime_resume = hdmi_runtime_resume, -}; - -static struct platform_driver omapdss_hdmihw_driver = { - .probe = omapdss_hdmihw_probe, - .remove = __exit_p(omapdss_hdmihw_remove), - .driver = { - .name = "omapdss_hdmi", - .owner = THIS_MODULE, - .pm = &hdmi_pm_ops, - }, -}; - -int __init hdmi_init_platform_driver(void) -{ - return platform_driver_register(&omapdss_hdmihw_driver); -} - -void __exit hdmi_uninit_platform_driver(void) -{ - platform_driver_unregister(&omapdss_hdmihw_driver); -} diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h new file mode 100644 index 000000000000..e25681ff5a70 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.h @@ -0,0 +1,444 @@ +/* + * HDMI driver definition for TI OMAP4 Processor. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _HDMI_H +#define _HDMI_H + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <video/omapdss.h> + +#include "dss.h" + +/* HDMI Wrapper */ + +#define HDMI_WP_REVISION 0x0 +#define HDMI_WP_SYSCONFIG 0x10 +#define HDMI_WP_IRQSTATUS_RAW 0x24 +#define HDMI_WP_IRQSTATUS 0x28 +#define HDMI_WP_IRQENABLE_SET 0x2C +#define HDMI_WP_IRQENABLE_CLR 0x30 +#define HDMI_WP_IRQWAKEEN 0x34 +#define HDMI_WP_PWR_CTRL 0x40 +#define HDMI_WP_DEBOUNCE 0x44 +#define HDMI_WP_VIDEO_CFG 0x50 +#define HDMI_WP_VIDEO_SIZE 0x60 +#define HDMI_WP_VIDEO_TIMING_H 0x68 +#define HDMI_WP_VIDEO_TIMING_V 0x6C +#define HDMI_WP_CLK 0x70 +#define HDMI_WP_AUDIO_CFG 0x80 +#define HDMI_WP_AUDIO_CFG2 0x84 +#define HDMI_WP_AUDIO_CTRL 0x88 +#define HDMI_WP_AUDIO_DATA 0x8C + +/* HDMI WP IRQ flags */ +#define HDMI_IRQ_CORE (1 << 0) +#define HDMI_IRQ_OCP_TIMEOUT (1 << 4) +#define HDMI_IRQ_AUDIO_FIFO_UNDERFLOW (1 << 8) +#define HDMI_IRQ_AUDIO_FIFO_OVERFLOW (1 << 9) +#define HDMI_IRQ_AUDIO_FIFO_SAMPLE_REQ (1 << 10) +#define HDMI_IRQ_VIDEO_VSYNC (1 << 16) +#define HDMI_IRQ_VIDEO_FRAME_DONE (1 << 17) +#define HDMI_IRQ_PHY_LINE5V_ASSERT (1 << 24) +#define HDMI_IRQ_LINK_CONNECT (1 << 25) +#define HDMI_IRQ_LINK_DISCONNECT (1 << 26) +#define HDMI_IRQ_PLL_LOCK (1 << 29) +#define HDMI_IRQ_PLL_UNLOCK (1 << 30) +#define HDMI_IRQ_PLL_RECAL (1 << 31) + +/* HDMI PLL */ + +#define PLLCTRL_PLL_CONTROL 0x0 +#define PLLCTRL_PLL_STATUS 0x4 +#define PLLCTRL_PLL_GO 0x8 +#define PLLCTRL_CFG1 0xC +#define PLLCTRL_CFG2 0x10 +#define PLLCTRL_CFG3 0x14 +#define PLLCTRL_SSC_CFG1 0x18 +#define PLLCTRL_SSC_CFG2 0x1C +#define PLLCTRL_CFG4 0x20 + +/* HDMI PHY */ + +#define HDMI_TXPHY_TX_CTRL 0x0 +#define HDMI_TXPHY_DIGITAL_CTRL 0x4 +#define HDMI_TXPHY_POWER_CTRL 0x8 +#define HDMI_TXPHY_PAD_CFG_CTRL 0xC + +enum hdmi_pll_pwr { + HDMI_PLLPWRCMD_ALLOFF = 0, + HDMI_PLLPWRCMD_PLLONLY = 1, + HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, + HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 +}; + +enum hdmi_phy_pwr { + HDMI_PHYPWRCMD_OFF = 0, + HDMI_PHYPWRCMD_LDOON = 1, + HDMI_PHYPWRCMD_TXON = 2 +}; + +enum hdmi_core_hdmi_dvi { + HDMI_DVI = 0, + HDMI_HDMI = 1 +}; + +enum hdmi_clk_refsel { + HDMI_REFSEL_PCLK = 0, + HDMI_REFSEL_REF1 = 1, + HDMI_REFSEL_REF2 = 2, + HDMI_REFSEL_SYSCLK = 3 +}; + +enum hdmi_packing_mode { + HDMI_PACK_10b_RGB_YUV444 = 0, + HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, + HDMI_PACK_20b_YUV422 = 2, + HDMI_PACK_ALREADYPACKED = 7 +}; + +enum hdmi_stereo_channels { + HDMI_AUDIO_STEREO_NOCHANNELS = 0, + HDMI_AUDIO_STEREO_ONECHANNEL = 1, + HDMI_AUDIO_STEREO_TWOCHANNELS = 2, + HDMI_AUDIO_STEREO_THREECHANNELS = 3, + HDMI_AUDIO_STEREO_FOURCHANNELS = 4 +}; + +enum hdmi_audio_type { + HDMI_AUDIO_TYPE_LPCM = 0, + HDMI_AUDIO_TYPE_IEC = 1 +}; + +enum hdmi_audio_justify { + HDMI_AUDIO_JUSTIFY_LEFT = 0, + HDMI_AUDIO_JUSTIFY_RIGHT = 1 +}; + +enum hdmi_audio_sample_order { + HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, + HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 +}; + +enum hdmi_audio_samples_perword { + HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, + HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 +}; + +enum hdmi_audio_sample_size { + HDMI_AUDIO_SAMPLE_16BITS = 0, + HDMI_AUDIO_SAMPLE_24BITS = 1 +}; + +enum hdmi_audio_transf_mode { + HDMI_AUDIO_TRANSF_DMA = 0, + HDMI_AUDIO_TRANSF_IRQ = 1 +}; + +enum hdmi_audio_blk_strt_end_sig { + HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, + HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 +}; + +enum hdmi_core_audio_layout { + HDMI_AUDIO_LAYOUT_2CH = 0, + HDMI_AUDIO_LAYOUT_8CH = 1 +}; + +enum hdmi_core_cts_mode { + HDMI_AUDIO_CTS_MODE_HW = 0, + HDMI_AUDIO_CTS_MODE_SW = 1 +}; + +enum hdmi_audio_mclk_mode { + HDMI_AUDIO_MCLK_128FS = 0, + HDMI_AUDIO_MCLK_256FS = 1, + HDMI_AUDIO_MCLK_384FS = 2, + HDMI_AUDIO_MCLK_512FS = 3, + HDMI_AUDIO_MCLK_768FS = 4, + HDMI_AUDIO_MCLK_1024FS = 5, + HDMI_AUDIO_MCLK_1152FS = 6, + HDMI_AUDIO_MCLK_192FS = 7 +}; + +/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ +enum hdmi_core_infoframe { + HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, + HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, + HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, + HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, + HDMI_INFOFRAME_AVI_DB1B_NO = 0, + HDMI_INFOFRAME_AVI_DB1B_VERT = 1, + HDMI_INFOFRAME_AVI_DB1B_HORI = 2, + HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, + HDMI_INFOFRAME_AVI_DB1S_0 = 0, + HDMI_INFOFRAME_AVI_DB1S_1 = 1, + HDMI_INFOFRAME_AVI_DB1S_2 = 2, + HDMI_INFOFRAME_AVI_DB2C_NO = 0, + HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, + HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, + HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, + HDMI_INFOFRAME_AVI_DB2M_NO = 0, + HDMI_INFOFRAME_AVI_DB2M_43 = 1, + HDMI_INFOFRAME_AVI_DB2M_169 = 2, + HDMI_INFOFRAME_AVI_DB2R_SAME = 8, + HDMI_INFOFRAME_AVI_DB2R_43 = 9, + HDMI_INFOFRAME_AVI_DB2R_169 = 10, + HDMI_INFOFRAME_AVI_DB2R_149 = 11, + HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, + HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, + HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, + HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, + HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, + HDMI_INFOFRAME_AVI_DB3Q_LR = 1, + HDMI_INFOFRAME_AVI_DB3Q_FR = 2, + HDMI_INFOFRAME_AVI_DB3SC_NO = 0, + HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, + HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, + HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, + HDMI_INFOFRAME_AVI_DB5PR_NO = 0, + HDMI_INFOFRAME_AVI_DB5PR_2 = 1, + HDMI_INFOFRAME_AVI_DB5PR_3 = 2, + HDMI_INFOFRAME_AVI_DB5PR_4 = 3, + HDMI_INFOFRAME_AVI_DB5PR_5 = 4, + HDMI_INFOFRAME_AVI_DB5PR_6 = 5, + HDMI_INFOFRAME_AVI_DB5PR_7 = 6, + HDMI_INFOFRAME_AVI_DB5PR_8 = 7, + HDMI_INFOFRAME_AVI_DB5PR_9 = 8, + HDMI_INFOFRAME_AVI_DB5PR_10 = 9, +}; + +struct hdmi_cm { + int code; + int mode; +}; + +struct hdmi_video_format { + enum hdmi_packing_mode packing_mode; + u32 y_res; /* Line per panel */ + u32 x_res; /* pixel per line */ +}; + +struct hdmi_config { + struct omap_video_timings timings; + struct hdmi_cm cm; +}; + +/* HDMI PLL structure */ +struct hdmi_pll_info { + u16 regn; + u16 regm; + u32 regmf; + u16 regm2; + u16 regsd; + u16 dcofreq; + enum hdmi_clk_refsel refsel; +}; + +struct hdmi_audio_format { + enum hdmi_stereo_channels stereo_channels; + u8 active_chnnls_msk; + enum hdmi_audio_type type; + enum hdmi_audio_justify justification; + enum hdmi_audio_sample_order sample_order; + enum hdmi_audio_samples_perword samples_per_word; + enum hdmi_audio_sample_size sample_size; + enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; +}; + +struct hdmi_audio_dma { + u8 transfer_size; + u8 block_size; + enum hdmi_audio_transf_mode mode; + u16 fifo_threshold; +}; + +struct hdmi_core_audio_i2s_config { + u8 in_length_bits; + u8 justification; + u8 sck_edge_mode; + u8 vbit; + u8 direction; + u8 shift; + u8 active_sds; +}; + +struct hdmi_core_audio_config { + struct hdmi_core_audio_i2s_config i2s_cfg; + struct snd_aes_iec958 *iec60958_cfg; + bool fs_override; + u32 n; + u32 cts; + u32 aud_par_busclk; + enum hdmi_core_audio_layout layout; + enum hdmi_core_cts_mode cts_mode; + bool use_mclk; + enum hdmi_audio_mclk_mode mclk_mode; + bool en_acr_pkt; + bool en_dsd_audio; + bool en_parallel_aud_input; + bool en_spdif; +}; + +/* + * Refer to section 8.2 in HDMI 1.3 specification for + * details about infoframe databytes + */ +struct hdmi_core_infoframe_avi { + /* Y0, Y1 rgb,yCbCr */ + u8 db1_format; + /* A0 Active information Present */ + u8 db1_active_info; + /* B0, B1 Bar info data valid */ + u8 db1_bar_info_dv; + /* S0, S1 scan information */ + u8 db1_scan_info; + /* C0, C1 colorimetry */ + u8 db2_colorimetry; + /* M0, M1 Aspect ratio (4:3, 16:9) */ + u8 db2_aspect_ratio; + /* R0...R3 Active format aspect ratio */ + u8 db2_active_fmt_ar; + /* ITC IT content. */ + u8 db3_itc; + /* EC0, EC1, EC2 Extended colorimetry */ + u8 db3_ec; + /* Q1, Q0 Quantization range */ + u8 db3_q_range; + /* SC1, SC0 Non-uniform picture scaling */ + u8 db3_nup_scaling; + /* VIC0..6 Video format identification */ + u8 db4_videocode; + /* PR0..PR3 Pixel repetition factor */ + u8 db5_pixel_repeat; + /* Line number end of top bar */ + u16 db6_7_line_eoftop; + /* Line number start of bottom bar */ + u16 db8_9_line_sofbottom; + /* Pixel number end of left bar */ + u16 db10_11_pixel_eofleft; + /* Pixel number start of right bar */ + u16 db12_13_pixel_sofright; +}; + +struct hdmi_wp_data { + void __iomem *base; +}; + +struct hdmi_pll_data { + void __iomem *base; + + struct hdmi_pll_info info; +}; + +struct hdmi_phy_data { + void __iomem *base; + + int irq; +}; + +struct hdmi_core_data { + void __iomem *base; + + struct hdmi_core_infoframe_avi avi_cfg; +}; + +static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx, + u32 val) +{ + __raw_writel(val, base_addr + idx); +} + +static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx) +{ + return __raw_readl(base_addr + idx); +} + +#define REG_FLD_MOD(base, idx, val, start, end) \ + hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ + val, start, end)) +#define REG_GET(base, idx, start, end) \ + FLD_GET(hdmi_read_reg(base, idx), start, end) + +static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, + const u32 idx, int b2, int b1, u32 val) +{ + u32 t = 0, v; + while (val != (v = REG_GET(base_addr, idx, b2, b1))) { + if (t++ > 10000) + return v; + udelay(1); + } + return v; +} + +/* HDMI wrapper funcs */ +int hdmi_wp_video_start(struct hdmi_wp_data *wp); +void hdmi_wp_video_stop(struct hdmi_wp_data *wp); +void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s); +u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp); +void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus); +void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask); +void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask); +int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val); +int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val); +void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, + struct hdmi_video_format *video_fmt); +void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, + struct omap_video_timings *timings); +void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, + struct omap_video_timings *timings); +void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, + struct omap_video_timings *timings, struct hdmi_config *param); +int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); + +/* HDMI PLL funcs */ +int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); +void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); +void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); +void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy); +int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); + +/* HDMI PHY funcs */ +int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, + struct hdmi_config *cfg); +void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp); +void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); +int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); + +/* HDMI common funcs */ +const struct hdmi_config *hdmi_default_timing(void); +const struct hdmi_config *hdmi_get_timings(int mode, int code); +struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing); + +#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); +int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); +int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); +void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, + struct hdmi_audio_format *aud_fmt); +void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, + struct hdmi_audio_dma *aud_dma); +static inline bool hdmi_mode_has_audio(int mode) +{ + return mode == HDMI_HDMI ? true : false; +} +#endif +#endif diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c new file mode 100644 index 000000000000..4a74538f9ea5 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi4.c @@ -0,0 +1,700 @@ +/* + * HDMI interface DSS driver for TI's OMAP4 family of SoCs. + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Yong Zhi + * Mythri pk <mythripk@ti.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define DSS_SUBSYS_NAME "HDMI" + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/clk.h> +#include <linux/gpio.h> +#include <linux/regulator/consumer.h> +#include <video/omapdss.h> + +#include "hdmi4_core.h" +#include "dss.h" +#include "dss_features.h" + +static struct { + struct mutex lock; + struct platform_device *pdev; + + struct hdmi_wp_data wp; + struct hdmi_pll_data pll; + struct hdmi_phy_data phy; + struct hdmi_core_data core; + + struct hdmi_config cfg; + + struct clk *sys_clk; + struct regulator *vdda_hdmi_dac_reg; + + bool core_enabled; + + struct omap_dss_device output; +} hdmi; + +static int hdmi_runtime_get(void) +{ + int r; + + DSSDBG("hdmi_runtime_get\n"); + + r = pm_runtime_get_sync(&hdmi.pdev->dev); + WARN_ON(r < 0); + if (r < 0) + return r; + + return 0; +} + +static void hdmi_runtime_put(void) +{ + int r; + + DSSDBG("hdmi_runtime_put\n"); + + r = pm_runtime_put_sync(&hdmi.pdev->dev); + WARN_ON(r < 0 && r != -ENOSYS); +} + +static int hdmi_init_regulator(void) +{ + struct regulator *reg; + + if (hdmi.vdda_hdmi_dac_reg != NULL) + return 0; + + reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); + + /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ + if (IS_ERR(reg)) + reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC"); + + if (IS_ERR(reg)) { + if (PTR_ERR(reg) != -EPROBE_DEFER) + DSSERR("can't get VDDA_HDMI_DAC regulator\n"); + return PTR_ERR(reg); + } + + hdmi.vdda_hdmi_dac_reg = reg; + + return 0; +} + +static int hdmi_power_on_core(struct omap_dss_device *dssdev) +{ + int r; + + r = regulator_enable(hdmi.vdda_hdmi_dac_reg); + if (r) + return r; + + r = hdmi_runtime_get(); + if (r) + goto err_runtime_get; + + /* Make selection of HDMI in DSS */ + dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); + + hdmi.core_enabled = true; + + return 0; + +err_runtime_get: + regulator_disable(hdmi.vdda_hdmi_dac_reg); + + return r; +} + +static void hdmi_power_off_core(struct omap_dss_device *dssdev) +{ + hdmi.core_enabled = false; + + hdmi_runtime_put(); + regulator_disable(hdmi.vdda_hdmi_dac_reg); +} + +static int hdmi_power_on_full(struct omap_dss_device *dssdev) +{ + int r; + struct omap_video_timings *p; + struct omap_overlay_manager *mgr = hdmi.output.manager; + unsigned long phy; + + r = hdmi_power_on_core(dssdev); + if (r) + return r; + + p = &hdmi.cfg.timings; + + DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); + + phy = p->pixel_clock; + + hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy); + + /* config the PLL and PHY hdmi_set_pll_pwrfirst */ + r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp); + if (r) { + DSSDBG("Failed to lock PLL\n"); + goto err_pll_enable; + } + + r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg); + if (r) { + DSSDBG("Failed to start PHY\n"); + goto err_phy_enable; + } + + hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); + + /* bypass TV gamma table */ + dispc_enable_gamma_table(0); + + /* tv size */ + dss_mgr_set_timings(mgr, p); + + r = hdmi_wp_video_start(&hdmi.wp); + if (r) + goto err_vid_enable; + + r = dss_mgr_enable(mgr); + if (r) + goto err_mgr_enable; + + return 0; + +err_mgr_enable: + hdmi_wp_video_stop(&hdmi.wp); +err_vid_enable: + hdmi_phy_disable(&hdmi.phy, &hdmi.wp); +err_phy_enable: + hdmi_pll_disable(&hdmi.pll, &hdmi.wp); +err_pll_enable: + hdmi_power_off_core(dssdev); + return -EIO; +} + +static void hdmi_power_off_full(struct omap_dss_device *dssdev) +{ + struct omap_overlay_manager *mgr = hdmi.output.manager; + + dss_mgr_disable(mgr); + + hdmi_wp_video_stop(&hdmi.wp); + hdmi_phy_disable(&hdmi.phy, &hdmi.wp); + hdmi_pll_disable(&hdmi.pll, &hdmi.wp); + + hdmi_power_off_core(dssdev); +} + +static int hdmi_display_check_timing(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct omap_dss_device *out = &hdmi.output; + + if (!dispc_mgr_timings_ok(out->dispc_channel, timings)) + return -EINVAL; + + return 0; +} + +static void hdmi_display_set_timing(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + struct hdmi_cm cm; + const struct hdmi_config *t; + + mutex_lock(&hdmi.lock); + + cm = hdmi_get_code(timings); + hdmi.cfg.cm = cm; + + t = hdmi_get_timings(cm.mode, cm.code); + if (t != NULL) { + hdmi.cfg = *t; + + dispc_set_tv_pclk(t->timings.pixel_clock * 1000); + } else { + hdmi.cfg.timings = *timings; + hdmi.cfg.cm.code = 0; + hdmi.cfg.cm.mode = HDMI_DVI; + + dispc_set_tv_pclk(timings->pixel_clock * 1000); + } + + DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ? + "DVI" : "HDMI", hdmi.cfg.cm.code); + + mutex_unlock(&hdmi.lock); +} + +static void hdmi_display_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + const struct hdmi_config *cfg; + struct hdmi_cm cm = hdmi.cfg.cm; + + cfg = hdmi_get_timings(cm.mode, cm.code); + if (cfg == NULL) + cfg = hdmi_default_timing(); + + memcpy(timings, &cfg->timings, sizeof(cfg->timings)); +} + +static void hdmi_dump_regs(struct seq_file *s) +{ + mutex_lock(&hdmi.lock); + + if (hdmi_runtime_get()) { + mutex_unlock(&hdmi.lock); + return; + } + + hdmi_wp_dump(&hdmi.wp, s); + hdmi_pll_dump(&hdmi.pll, s); + hdmi_phy_dump(&hdmi.phy, s); + hdmi4_core_dump(&hdmi.core, s); + + hdmi_runtime_put(); + mutex_unlock(&hdmi.lock); +} + +static int read_edid(u8 *buf, int len) +{ + int r; + + mutex_lock(&hdmi.lock); + + r = hdmi_runtime_get(); + BUG_ON(r); + + r = hdmi4_read_edid(&hdmi.core, buf, len); + + hdmi_runtime_put(); + mutex_unlock(&hdmi.lock); + + return r; +} + +static int hdmi_display_enable(struct omap_dss_device *dssdev) +{ + struct omap_dss_device *out = &hdmi.output; + int r = 0; + + DSSDBG("ENTER hdmi_display_enable\n"); + + mutex_lock(&hdmi.lock); + + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); + r = -ENODEV; + goto err0; + } + + r = hdmi_power_on_full(dssdev); + if (r) { + DSSERR("failed to power on device\n"); + goto err0; + } + + mutex_unlock(&hdmi.lock); + return 0; + +err0: + mutex_unlock(&hdmi.lock); + return r; +} + +static void hdmi_display_disable(struct omap_dss_device *dssdev) +{ + DSSDBG("Enter hdmi_display_disable\n"); + + mutex_lock(&hdmi.lock); + + hdmi_power_off_full(dssdev); + + mutex_unlock(&hdmi.lock); +} + +static int hdmi_core_enable(struct omap_dss_device *dssdev) +{ + int r = 0; + + DSSDBG("ENTER omapdss_hdmi_core_enable\n"); + + mutex_lock(&hdmi.lock); + + r = hdmi_power_on_core(dssdev); + if (r) { + DSSERR("failed to power on device\n"); + goto err0; + } + + mutex_unlock(&hdmi.lock); + return 0; + +err0: + mutex_unlock(&hdmi.lock); + return r; +} + +static void hdmi_core_disable(struct omap_dss_device *dssdev) +{ + DSSDBG("Enter omapdss_hdmi_core_disable\n"); + + mutex_lock(&hdmi.lock); + + hdmi_power_off_core(dssdev); + + mutex_unlock(&hdmi.lock); +} + +static int hdmi_get_clocks(struct platform_device *pdev) +{ + struct clk *clk; + + clk = devm_clk_get(&pdev->dev, "sys_clk"); + if (IS_ERR(clk)) { + DSSERR("can't get sys_clk\n"); + return PTR_ERR(clk); + } + + hdmi.sys_clk = clk; + + return 0; +} + +static int hdmi_connect(struct omap_dss_device *dssdev, + struct omap_dss_device *dst) +{ + struct omap_overlay_manager *mgr; + int r; + + r = hdmi_init_regulator(); + if (r) + return r; + + mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); + if (!mgr) + return -ENODEV; + + r = dss_mgr_connect(mgr, dssdev); + if (r) + return r; + + r = omapdss_output_set_device(dssdev, dst); + if (r) { + DSSERR("failed to connect output to new device: %s\n", + dst->name); + dss_mgr_disconnect(mgr, dssdev); + return r; + } + + return 0; +} + +static void hdmi_disconnect(struct omap_dss_device *dssdev, + struct omap_dss_device *dst) +{ + WARN_ON(dst != dssdev->dst); + + if (dst != dssdev->dst) + return; + + omapdss_output_unset_device(dssdev); + + if (dssdev->manager) + dss_mgr_disconnect(dssdev->manager, dssdev); +} + +static int hdmi_read_edid(struct omap_dss_device *dssdev, + u8 *edid, int len) +{ + bool need_enable; + int r; + + need_enable = hdmi.core_enabled == false; + + if (need_enable) { + r = hdmi_core_enable(dssdev); + if (r) + return r; + } + + r = read_edid(edid, len); + + if (need_enable) + hdmi_core_disable(dssdev); + + return r; +} + +#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +static int hdmi_audio_enable(struct omap_dss_device *dssdev) +{ + int r; + + mutex_lock(&hdmi.lock); + + if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { + r = -EPERM; + goto err; + } + + r = hdmi_wp_audio_enable(&hdmi.wp, true); + if (r) + goto err; + + mutex_unlock(&hdmi.lock); + return 0; + +err: + mutex_unlock(&hdmi.lock); + return r; +} + +static void hdmi_audio_disable(struct omap_dss_device *dssdev) +{ + hdmi_wp_audio_enable(&hdmi.wp, false); +} + +static int hdmi_audio_start(struct omap_dss_device *dssdev) +{ + return hdmi4_audio_start(&hdmi.core, &hdmi.wp); +} + +static void hdmi_audio_stop(struct omap_dss_device *dssdev) +{ + hdmi4_audio_stop(&hdmi.core, &hdmi.wp); +} + +static bool hdmi_audio_supported(struct omap_dss_device *dssdev) +{ + bool r; + + mutex_lock(&hdmi.lock); + + r = hdmi_mode_has_audio(hdmi.cfg.cm.mode); + + mutex_unlock(&hdmi.lock); + return r; +} + +static int hdmi_audio_config(struct omap_dss_device *dssdev, + struct omap_dss_audio *audio) +{ + int r; + u32 pclk = hdmi.cfg.timings.pixel_clock; + + mutex_lock(&hdmi.lock); + + if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { + r = -EPERM; + goto err; + } + + r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk); + if (r) + goto err; + + mutex_unlock(&hdmi.lock); + return 0; + +err: + mutex_unlock(&hdmi.lock); + return r; +} +#else +static int hdmi_audio_enable(struct omap_dss_device *dssdev) +{ + return -EPERM; +} + +static void hdmi_audio_disable(struct omap_dss_device *dssdev) +{ +} + +static int hdmi_audio_start(struct omap_dss_device *dssdev) +{ + return -EPERM; +} + +static void hdmi_audio_stop(struct omap_dss_device *dssdev) +{ +} + +static bool hdmi_audio_supported(struct omap_dss_device *dssdev) +{ + return false; +} + +static int hdmi_audio_config(struct omap_dss_device *dssdev, + struct omap_dss_audio *audio) +{ + return -EPERM; +} +#endif + +static const struct omapdss_hdmi_ops hdmi_ops = { + .connect = hdmi_connect, + .disconnect = hdmi_disconnect, + + .enable = hdmi_display_enable, + .disable = hdmi_display_disable, + + .check_timings = hdmi_display_check_timing, + .set_timings = hdmi_display_set_timing, + .get_timings = hdmi_display_get_timings, + + .read_edid = hdmi_read_edid, + + .audio_enable = hdmi_audio_enable, + .audio_disable = hdmi_audio_disable, + .audio_start = hdmi_audio_start, + .audio_stop = hdmi_audio_stop, + .audio_supported = hdmi_audio_supported, + .audio_config = hdmi_audio_config, +}; + +static void hdmi_init_output(struct platform_device *pdev) +{ + struct omap_dss_device *out = &hdmi.output; + + out->dev = &pdev->dev; + out->id = OMAP_DSS_OUTPUT_HDMI; + out->output_type = OMAP_DISPLAY_TYPE_HDMI; + out->name = "hdmi.0"; + out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; + out->ops.hdmi = &hdmi_ops; + out->owner = THIS_MODULE; + + omapdss_register_output(out); +} + +static void __exit hdmi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_device *out = &hdmi.output; + + omapdss_unregister_output(out); +} + +/* HDMI HW IP initialisation */ +static int omapdss_hdmihw_probe(struct platform_device *pdev) +{ + int r; + + hdmi.pdev = pdev; + + mutex_init(&hdmi.lock); + + r = hdmi_wp_init(pdev, &hdmi.wp); + if (r) + return r; + + r = hdmi_pll_init(pdev, &hdmi.pll); + if (r) + return r; + + r = hdmi_phy_init(pdev, &hdmi.phy); + if (r) + return r; + + r = hdmi4_core_init(pdev, &hdmi.core); + if (r) + return r; + + r = hdmi_get_clocks(pdev); + if (r) { + DSSERR("can't get clocks\n"); + return r; + } + + pm_runtime_enable(&pdev->dev); + + hdmi_init_output(pdev); + + dss_debugfs_create_file("hdmi", hdmi_dump_regs); + + return 0; +} + +static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) +{ + hdmi_uninit_output(pdev); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int hdmi_runtime_suspend(struct device *dev) +{ + clk_disable_unprepare(hdmi.sys_clk); + + dispc_runtime_put(); + + return 0; +} + +static int hdmi_runtime_resume(struct device *dev) +{ + int r; + + r = dispc_runtime_get(); + if (r < 0) + return r; + + clk_prepare_enable(hdmi.sys_clk); + + return 0; +} + +static const struct dev_pm_ops hdmi_pm_ops = { + .runtime_suspend = hdmi_runtime_suspend, + .runtime_resume = hdmi_runtime_resume, +}; + +static struct platform_driver omapdss_hdmihw_driver = { + .probe = omapdss_hdmihw_probe, + .remove = __exit_p(omapdss_hdmihw_remove), + .driver = { + .name = "omapdss_hdmi", + .owner = THIS_MODULE, + .pm = &hdmi_pm_ops, + }, +}; + +int __init hdmi4_init_platform_driver(void) +{ + return platform_driver_register(&omapdss_hdmihw_driver); +} + +void __exit hdmi4_uninit_platform_driver(void) +{ + platform_driver_unregister(&omapdss_hdmihw_driver); +} diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/hdmi4_core.c index 3dfe00956a4f..2eb04dcf807c 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/hdmi4_core.c @@ -19,6 +19,8 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#define DSS_SUBSYS_NAME "HDMICORE" + #include <linux/kernel.h> #include <linux/module.h> #include <linux/err.h> @@ -26,6 +28,7 @@ #include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/delay.h> +#include <linux/platform_device.h> #include <linux/string.h> #include <linux/seq_file.h> #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) @@ -33,304 +36,19 @@ #include <sound/asoundef.h> #endif -#include "ti_hdmi_4xxx_ip.h" -#include "dss.h" +#include "hdmi4_core.h" #include "dss_features.h" -#define HDMI_IRQ_LINK_CONNECT (1 << 25) -#define HDMI_IRQ_LINK_DISCONNECT (1 << 26) - -static inline void hdmi_write_reg(void __iomem *base_addr, - const u16 idx, u32 val) -{ - __raw_writel(val, base_addr + idx); -} - -static inline u32 hdmi_read_reg(void __iomem *base_addr, - const u16 idx) -{ - return __raw_readl(base_addr + idx); -} - -static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data) -{ - return ip_data->base_wp; -} +#define HDMI_CORE_AV 0x500 -static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data) +static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core) { - return ip_data->base_wp + ip_data->phy_offset; + return core->base + HDMI_CORE_AV; } -static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data) +static int hdmi_core_ddc_init(struct hdmi_core_data *core) { - return ip_data->base_wp + ip_data->pll_offset; -} - -static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) -{ - return ip_data->base_wp + ip_data->core_av_offset; -} - -static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data) -{ - return ip_data->base_wp + ip_data->core_sys_offset; -} - -static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, - const u16 idx, - int b2, int b1, u32 val) -{ - u32 t = 0; - while (val != REG_GET(base_addr, idx, b2, b1)) { - udelay(1); - if (t++ > 10000) - return !val; - } - return val; -} - -static int hdmi_pll_init(struct hdmi_ip_data *ip_data) -{ - u32 r; - void __iomem *pll_base = hdmi_pll_base(ip_data); - struct hdmi_pll_info *fmt = &ip_data->pll_data; - - /* PLL start always use manual mode */ - REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); - - r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); - r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ - r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ - - hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); - - r = hdmi_read_reg(pll_base, PLLCTRL_CFG2); - - r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ - r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ - r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ - r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ - - if (fmt->dcofreq) { - /* divider programming for frequency beyond 1000Mhz */ - REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10); - r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ - } else { - r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ - } - - hdmi_write_reg(pll_base, PLLCTRL_CFG2, r); - - r = hdmi_read_reg(pll_base, PLLCTRL_CFG4); - r = FLD_MOD(r, fmt->regm2, 24, 18); - r = FLD_MOD(r, fmt->regmf, 17, 0); - - hdmi_write_reg(pll_base, PLLCTRL_CFG4, r); - - /* go now */ - REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0); - - /* wait for bit change */ - if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO, - 0, 0, 1) != 1) { - pr_err("PLL GO bit not set\n"); - return -ETIMEDOUT; - } - - /* Wait till the lock bit is set in PLL status */ - if (hdmi_wait_for_bit_change(pll_base, - PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { - pr_err("cannot lock PLL\n"); - pr_err("CFG1 0x%x\n", - hdmi_read_reg(pll_base, PLLCTRL_CFG1)); - pr_err("CFG2 0x%x\n", - hdmi_read_reg(pll_base, PLLCTRL_CFG2)); - pr_err("CFG4 0x%x\n", - hdmi_read_reg(pll_base, PLLCTRL_CFG4)); - return -ETIMEDOUT; - } - - pr_debug("PLL locked!\n"); - - return 0; -} - -/* PHY_PWR_CMD */ -static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val) -{ - /* Return if already the state */ - if (REG_GET(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, 5, 4) == val) - return 0; - - /* Command for power control of HDMI PHY */ - REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6); - - /* Status of the power control of HDMI PHY */ - if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), - HDMI_WP_PWR_CTRL, 5, 4, val) != val) { - pr_err("Failed to set PHY power mode to %d\n", val); - return -ETIMEDOUT; - } - - return 0; -} - -/* PLL_PWR_CMD */ -static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val) -{ - /* Command for power control of HDMI PLL */ - REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2); - - /* wait till PHY_PWR_STATUS is set */ - if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, - 1, 0, val) != val) { - pr_err("Failed to set PLL_PWR_STATUS\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int hdmi_pll_reset(struct hdmi_ip_data *ip_data) -{ - /* SYSRESET controlled by power FSM */ - REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3); - - /* READ 0x0 reset is in progress */ - if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), - PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { - pr_err("Failed to sysreset PLL\n"); - return -ETIMEDOUT; - } - - return 0; -} - -int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data) -{ - u16 r = 0; - - r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); - if (r) - return r; - - r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); - if (r) - return r; - - r = hdmi_pll_reset(ip_data); - if (r) - return r; - - r = hdmi_pll_init(ip_data); - if (r) - return r; - - return 0; -} - -void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) -{ - hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); -} - -static irqreturn_t hdmi_irq_handler(int irq, void *data) -{ - struct hdmi_ip_data *ip_data = data; - void __iomem *wp_base = hdmi_wp_base(ip_data); - u32 irqstatus; - - irqstatus = hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); - hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, irqstatus); - /* flush posted write */ - hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); - - if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && - irqstatus & HDMI_IRQ_LINK_DISCONNECT) { - /* - * If we get both connect and disconnect interrupts at the same - * time, turn off the PHY, clear interrupts, and restart, which - * raises connect interrupt if a cable is connected, or nothing - * if cable is not connected. - */ - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); - - hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, - HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); - /* flush posted write */ - hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); - - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); - } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); - } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); - } - - return IRQ_HANDLED; -} - -int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) -{ - u16 r = 0; - void __iomem *phy_base = hdmi_phy_base(ip_data); - - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_CLR, - 0xffffffff); - - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQSTATUS, - HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); - - r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); - if (r) - return r; - - /* - * Read address 0 in order to get the SCP reset done completed - * Dummy access performed to make sure reset is done - */ - hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL); - - /* - * Write to phy address 0 to configure the clock - * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field - */ - REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); - - /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ - hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); - - /* Setup max LDO voltage */ - REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); - - /* Write to phy address 3 to change the polarity control */ - REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); - - r = request_threaded_irq(ip_data->irq, NULL, hdmi_irq_handler, - IRQF_ONESHOT, "OMAP HDMI", ip_data); - if (r) { - DSSERR("HDMI IRQ request failed\n"); - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); - return r; - } - - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_SET, - HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); - - return 0; -} - -void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) -{ - free_irq(ip_data->irq, ip_data); - - hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); -} - -static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) -{ - void __iomem *base = hdmi_core_sys_base(ip_data); + void __iomem *base = core->base; /* Turn on CLK for DDC */ REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); @@ -370,10 +88,10 @@ static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) return 0; } -static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, +static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, int ext) { - void __iomem *base = hdmi_core_sys_base(ip_data); + void __iomem *base = core->base; u32 i; char checksum; u32 offset = 0; @@ -409,12 +127,12 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, /* HDMI_CORE_DDC_STATUS_BUS_LOW */ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { - pr_err("I2C Bus Low?\n"); + DSSERR("I2C Bus Low?\n"); return -EIO; } /* HDMI_CORE_DDC_STATUS_NO_ACK */ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { - pr_err("I2C No Ack\n"); + DSSERR("I2C No Ack\n"); return -EIO; } @@ -445,33 +163,32 @@ static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, checksum += pedid[i]; if (checksum != 0) { - pr_err("E-EDID checksum failed!!\n"); + DSSERR("E-EDID checksum failed!!\n"); return -EIO; } return 0; } -int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, - u8 *edid, int len) +int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len) { int r, l; if (len < 128) return -EINVAL; - r = hdmi_core_ddc_init(ip_data); + r = hdmi_core_ddc_init(core); if (r) return r; - r = hdmi_core_ddc_edid(ip_data, edid, 0); + r = hdmi_core_ddc_edid(core, edid, 0); if (r) return r; l = 128; if (len >= 128 * 2 && edid[0x7e] > 0) { - r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); + r = hdmi_core_ddc_edid(core, edid + 0x80, 1); if (r) return r; l += 128; @@ -484,7 +201,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, struct hdmi_core_infoframe_avi *avi_cfg, struct hdmi_core_packet_enable_repeat *repeat_cfg) { - pr_debug("Enter hdmi_core_init\n"); + DSSDBG("Enter hdmi_core_init\n"); /* video core */ video_cfg->ip_bus_width = HDMI_INPUT_8BIT; @@ -508,7 +225,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, avi_cfg->db3_nup_scaling = 0; avi_cfg->db4_videocode = 0; avi_cfg->db5_pixel_repeat = 0; - avi_cfg->db6_7_line_eoftop = 0 ; + avi_cfg->db6_7_line_eoftop = 0; avi_cfg->db8_9_line_sofbottom = 0; avi_cfg->db10_11_pixel_eofleft = 0; avi_cfg->db12_13_pixel_sofright = 0; @@ -524,38 +241,39 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, repeat_cfg->generic_pkt_repeat = 0; } -static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data) +static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) { - pr_debug("Enter hdmi_core_powerdown_disable\n"); - REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0); + DSSDBG("Enter hdmi_core_powerdown_disable\n"); + REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0); } -static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data) +static void hdmi_core_swreset_release(struct hdmi_core_data *core) { - pr_debug("Enter hdmi_core_swreset_release\n"); - REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0); + DSSDBG("Enter hdmi_core_swreset_release\n"); + REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0); } -static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data) +static void hdmi_core_swreset_assert(struct hdmi_core_data *core) { - pr_debug("Enter hdmi_core_swreset_assert\n"); - REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0); + DSSDBG("Enter hdmi_core_swreset_assert\n"); + REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0); } /* HDMI_CORE_VIDEO_CONFIG */ -static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, +static void hdmi_core_video_config(struct hdmi_core_data *core, struct hdmi_core_video_config *cfg) { u32 r = 0; - void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); + void __iomem *core_sys_base = core->base; + void __iomem *core_av_base = hdmi_av_base(core); /* sys_ctrl1 default configuration not tunable */ - r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1); - r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); - r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); - r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); - r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); - hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r); + r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1); + r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5); + r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4); + r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2); + r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1); + hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r); REG_FLD_MOD(core_sys_base, HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); @@ -574,23 +292,23 @@ static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); /* HDMI_Ctrl */ - r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL); + r = hdmi_read_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL); r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); r = FLD_MOD(r, cfg->pkt_mode, 5, 3); r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); - hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r); + hdmi_write_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL, r); /* TMDS_CTRL */ REG_FLD_MOD(core_sys_base, HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); } -static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data) +static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core) { u32 val; char sum = 0, checksum = 0; - void __iomem *av_base = hdmi_av_base(ip_data); - struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg; + void __iomem *av_base = hdmi_av_base(core); + struct hdmi_core_infoframe_avi info_avi = core->avi_cfg; sum += 0x82 + 0x002 + 0x00D; hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); @@ -661,160 +379,64 @@ static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data) hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); } -static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, +static void hdmi_core_av_packet_config(struct hdmi_core_data *core, struct hdmi_core_packet_enable_repeat repeat_cfg) { /* enable/repeat the infoframe */ - hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1, + hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL1, (repeat_cfg.audio_pkt << 5) | (repeat_cfg.audio_pkt_repeat << 4) | (repeat_cfg.avi_infoframe << 1) | (repeat_cfg.avi_infoframe_repeat)); /* enable/repeat the packet */ - hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2, + hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL2, (repeat_cfg.gen_cntrl_pkt << 3) | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | (repeat_cfg.generic_pkt << 1) | (repeat_cfg.generic_pkt_repeat)); } -static void hdmi_wp_init(struct omap_video_timings *timings, - struct hdmi_video_format *video_fmt) -{ - pr_debug("Enter hdmi_wp_init\n"); - - timings->hbp = 0; - timings->hfp = 0; - timings->hsw = 0; - timings->vbp = 0; - timings->vfp = 0; - timings->vsw = 0; - - video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; - video_fmt->y_res = 0; - video_fmt->x_res = 0; - -} - -int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data) -{ - REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31); - return 0; -} - -void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data) -{ - REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31); -} - -static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, - struct omap_video_timings *timings, struct hdmi_config *param) -{ - pr_debug("Enter hdmi_wp_video_init_format\n"); - - video_fmt->y_res = param->timings.y_res; - video_fmt->x_res = param->timings.x_res; - - timings->hbp = param->timings.hbp; - timings->hfp = param->timings.hfp; - timings->hsw = param->timings.hsw; - timings->vbp = param->timings.vbp; - timings->vfp = param->timings.vfp; - timings->vsw = param->timings.vsw; -} - -static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, - struct hdmi_video_format *video_fmt) -{ - u32 l = 0; - - REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, - video_fmt->packing_mode, 10, 8); - - l |= FLD_VAL(video_fmt->y_res, 31, 16); - l |= FLD_VAL(video_fmt->x_res, 15, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); -} - -static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data) -{ - u32 r; - bool vsync_pol, hsync_pol; - pr_debug("Enter hdmi_wp_video_config_interface\n"); - - vsync_pol = ip_data->cfg.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; - hsync_pol = ip_data->cfg.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; - - r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); - r = FLD_MOD(r, vsync_pol, 7, 7); - r = FLD_MOD(r, hsync_pol, 6, 6); - r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3); - r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); -} - -static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data, - struct omap_video_timings *timings) -{ - u32 timing_h = 0; - u32 timing_v = 0; - - pr_debug("Enter hdmi_wp_video_config_timing\n"); - - timing_h |= FLD_VAL(timings->hbp, 31, 20); - timing_h |= FLD_VAL(timings->hfp, 19, 8); - timing_h |= FLD_VAL(timings->hsw, 7, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h); - - timing_v |= FLD_VAL(timings->vbp, 31, 20); - timing_v |= FLD_VAL(timings->vfp, 19, 8); - timing_v |= FLD_VAL(timings->vsw, 7, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v); -} - -void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) +void hdmi4_configure(struct hdmi_core_data *core, + struct hdmi_wp_data *wp, struct hdmi_config *cfg) { /* HDMI */ struct omap_video_timings video_timing; struct hdmi_video_format video_format; /* HDMI core */ - struct hdmi_core_infoframe_avi *avi_cfg = &ip_data->avi_cfg; + struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg; struct hdmi_core_video_config v_core_cfg; struct hdmi_core_packet_enable_repeat repeat_cfg; - struct hdmi_config *cfg = &ip_data->cfg; - - hdmi_wp_init(&video_timing, &video_format); hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg); - hdmi_wp_video_init_format(&video_format, &video_timing, cfg); + hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); - hdmi_wp_video_config_timing(ip_data, &video_timing); + hdmi_wp_video_config_timing(wp, &video_timing); /* video config */ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; - hdmi_wp_video_config_format(ip_data, &video_format); + hdmi_wp_video_config_format(wp, &video_format); - hdmi_wp_video_config_interface(ip_data); + hdmi_wp_video_config_interface(wp, &video_timing); /* * configure core video part * set software reset in the core */ - hdmi_core_swreset_assert(ip_data); + hdmi_core_swreset_assert(core); /* power down off */ - hdmi_core_powerdown_disable(ip_data); + hdmi_core_powerdown_disable(core); v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; v_core_cfg.hdmi_dvi = cfg->cm.mode; - hdmi_core_video_config(ip_data, &v_core_cfg); + hdmi_core_video_config(core, &v_core_cfg); /* release software reset in the core */ - hdmi_core_swreset_release(ip_data); + hdmi_core_swreset_release(core); /* * configure packet @@ -839,7 +461,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) avi_cfg->db10_11_pixel_eofleft = 0; avi_cfg->db12_13_pixel_sofright = 0; - hdmi_core_aux_infoframe_avi_config(ip_data); + hdmi_core_aux_infoframe_avi_config(core); /* enable/repeat the infoframe */ repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; @@ -847,65 +469,30 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) /* wakeup */ repeat_cfg.audio_pkt = HDMI_PACKETENABLE; repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; - hdmi_core_av_packet_config(ip_data, repeat_cfg); -} - -void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) -{ -#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_wp_base(ip_data), r)) - - DUMPREG(HDMI_WP_REVISION); - DUMPREG(HDMI_WP_SYSCONFIG); - DUMPREG(HDMI_WP_IRQSTATUS_RAW); - DUMPREG(HDMI_WP_IRQSTATUS); - DUMPREG(HDMI_WP_PWR_CTRL); - DUMPREG(HDMI_WP_IRQENABLE_SET); - DUMPREG(HDMI_WP_VIDEO_CFG); - DUMPREG(HDMI_WP_VIDEO_SIZE); - DUMPREG(HDMI_WP_VIDEO_TIMING_H); - DUMPREG(HDMI_WP_VIDEO_TIMING_V); - DUMPREG(HDMI_WP_WP_CLK); - DUMPREG(HDMI_WP_AUDIO_CFG); - DUMPREG(HDMI_WP_AUDIO_CFG2); - DUMPREG(HDMI_WP_AUDIO_CTRL); - DUMPREG(HDMI_WP_AUDIO_DATA); -} - -void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) -{ -#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_pll_base(ip_data), r)) - - DUMPPLL(PLLCTRL_PLL_CONTROL); - DUMPPLL(PLLCTRL_PLL_STATUS); - DUMPPLL(PLLCTRL_PLL_GO); - DUMPPLL(PLLCTRL_CFG1); - DUMPPLL(PLLCTRL_CFG2); - DUMPPLL(PLLCTRL_CFG3); - DUMPPLL(PLLCTRL_CFG4); + hdmi_core_av_packet_config(core, repeat_cfg); } -void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s) { int i; #define CORE_REG(i, name) name(i) #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_core_sys_base(ip_data), r)) + hdmi_read_reg(core->base, r)) #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_av_base(ip_data), r)) + hdmi_read_reg(hdmi_av_base(core), r)) #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \ - hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r))) + hdmi_read_reg(hdmi_av_base(core), CORE_REG(i, r))) DUMPCORE(HDMI_CORE_SYS_VND_IDL); DUMPCORE(HDMI_CORE_SYS_DEV_IDL); DUMPCORE(HDMI_CORE_SYS_DEV_IDH); DUMPCORE(HDMI_CORE_SYS_DEV_REV); DUMPCORE(HDMI_CORE_SYS_SRST); - DUMPCORE(HDMI_CORE_CTRL1); + DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1); DUMPCORE(HDMI_CORE_SYS_SYS_STAT); + DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3); DUMPCORE(HDMI_CORE_SYS_DE_DLY); DUMPCORE(HDMI_CORE_SYS_DE_CTRL); DUMPCORE(HDMI_CORE_SYS_DE_TOP); @@ -913,14 +500,58 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) DUMPCORE(HDMI_CORE_SYS_DE_CNTH); DUMPCORE(HDMI_CORE_SYS_DE_LINL); DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); + DUMPCORE(HDMI_CORE_SYS_HRES_L); + DUMPCORE(HDMI_CORE_SYS_HRES_H); + DUMPCORE(HDMI_CORE_SYS_VRES_L); + DUMPCORE(HDMI_CORE_SYS_VRES_H); + DUMPCORE(HDMI_CORE_SYS_IADJUST); + DUMPCORE(HDMI_CORE_SYS_POLDETECT); + DUMPCORE(HDMI_CORE_SYS_HWIDTH1); + DUMPCORE(HDMI_CORE_SYS_HWIDTH2); + DUMPCORE(HDMI_CORE_SYS_VWIDTH); + DUMPCORE(HDMI_CORE_SYS_VID_CTRL); DUMPCORE(HDMI_CORE_SYS_VID_ACEN); DUMPCORE(HDMI_CORE_SYS_VID_MODE); + DUMPCORE(HDMI_CORE_SYS_VID_BLANK1); + DUMPCORE(HDMI_CORE_SYS_VID_BLANK3); + DUMPCORE(HDMI_CORE_SYS_VID_BLANK1); + DUMPCORE(HDMI_CORE_SYS_DC_HEADER); + DUMPCORE(HDMI_CORE_SYS_VID_DITHER); + DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT); + DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW); + DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP); + DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW); + DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP); + DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW); + DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP); + DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW); + DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP); DUMPCORE(HDMI_CORE_SYS_INTR_STATE); DUMPCORE(HDMI_CORE_SYS_INTR1); DUMPCORE(HDMI_CORE_SYS_INTR2); DUMPCORE(HDMI_CORE_SYS_INTR3); DUMPCORE(HDMI_CORE_SYS_INTR4); - DUMPCORE(HDMI_CORE_SYS_UMASK1); + DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1); + DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2); + DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3); + DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4); + DUMPCORE(HDMI_CORE_SYS_INTR_CTRL); DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); DUMPCORE(HDMI_CORE_DDC_ADDR); @@ -1009,60 +640,12 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); } -void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) -{ -#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ - hdmi_read_reg(hdmi_phy_base(ip_data), r)) - - DUMPPHY(HDMI_TXPHY_TX_CTRL); - DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); - DUMPPHY(HDMI_TXPHY_POWER_CTRL); - DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); -} - #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) -static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data, - struct hdmi_audio_format *aud_fmt) -{ - u32 r; - - DSSDBG("Enter hdmi_wp_audio_config_format\n"); - - r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG); - r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); - r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); - r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); - r = FLD_MOD(r, aud_fmt->type, 4, 4); - r = FLD_MOD(r, aud_fmt->justification, 3, 3); - r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); - r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); - r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); -} - -static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data, - struct hdmi_audio_dma *aud_dma) -{ - u32 r; - - DSSDBG("Enter hdmi_wp_audio_config_dma\n"); - - r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2); - r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); - r = FLD_MOD(r, aud_dma->block_size, 7, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r); - - r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL); - r = FLD_MOD(r, aud_dma->mode, 9, 9); - r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); - hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); -} - -static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data, +static void hdmi_core_audio_config(struct hdmi_core_data *core, struct hdmi_core_audio_config *cfg) { u32 r; - void __iomem *av_base = hdmi_av_base(ip_data); + void __iomem *av_base = hdmi_av_base(core); /* * Parameters for generation of Audio Clock Recovery packets @@ -1157,11 +740,11 @@ static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data, REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5); } -static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data, +static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core, struct snd_cea_861_aud_if *info_aud) { u8 sum = 0, checksum = 0; - void __iomem *av_base = hdmi_av_base(ip_data); + void __iomem *av_base = hdmi_av_base(core); /* * Set audio info frame type, version and length as @@ -1207,20 +790,20 @@ static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data, */ } -int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, - struct omap_dss_audio *audio) +int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, + struct omap_dss_audio *audio, u32 pclk) { struct hdmi_audio_format audio_format; struct hdmi_audio_dma audio_dma; - struct hdmi_core_audio_config core; + struct hdmi_core_audio_config acore; int err, n, cts, channel_count; unsigned int fs_nr; bool word_length_16b = false; - if (!audio || !audio->iec || !audio->cea || !ip_data) + if (!audio || !audio->iec || !audio->cea || !core) return -EINVAL; - core.iec60958_cfg = audio->iec; + acore.iec60958_cfg = audio->iec; /* * In the IEC-60958 status word, check if the audio sample word length * is 16-bit as several optimizations can be performed in such case. @@ -1231,22 +814,22 @@ int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, /* I2S configuration. See Phillips' specification */ if (word_length_16b) - core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; + acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; else - core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; + acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; /* * The I2S input word length is twice the lenght given in the IEC-60958 * status word. If the word size is greater than * 20 bits, increment by one. */ - core.i2s_cfg.in_length_bits = audio->iec->status[4] + acore.i2s_cfg.in_length_bits = audio->iec->status[4] & IEC958_AES4_CON_WORDLEN; if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) - core.i2s_cfg.in_length_bits++; - core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; - core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; - core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; - core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; + acore.i2s_cfg.in_length_bits++; + acore.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; + acore.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; + acore.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; + acore.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; /* convert sample frequency to a number */ switch (audio->iec->status[3] & IEC958_AES3_CON_FS) { @@ -1275,23 +858,23 @@ int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, return -EINVAL; } - err = hdmi_compute_acr(fs_nr, &n, &cts); + err = hdmi_compute_acr(pclk, fs_nr, &n, &cts); /* Audio clock regeneration settings */ - core.n = n; - core.cts = cts; + acore.n = n; + acore.cts = cts; if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { - core.aud_par_busclk = 0; - core.cts_mode = HDMI_AUDIO_CTS_MODE_SW; - core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); + acore.aud_par_busclk = 0; + acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW; + acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); } else { - core.aud_par_busclk = (((128 * 31) - 1) << 8); - core.cts_mode = HDMI_AUDIO_CTS_MODE_HW; - core.use_mclk = true; + acore.aud_par_busclk = (((128 * 31) - 1) << 8); + acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW; + acore.use_mclk = true; } - if (core.use_mclk) - core.mclk_mode = HDMI_AUDIO_MCLK_128FS; + if (acore.use_mclk) + acore.mclk_mode = HDMI_AUDIO_MCLK_128FS; /* Audio channels settings */ channel_count = (audio->cea->db1_ct_cc & @@ -1329,25 +912,25 @@ int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, */ if (channel_count == 2) { audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; - core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; - core.layout = HDMI_AUDIO_LAYOUT_2CH; + acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; + acore.layout = HDMI_AUDIO_LAYOUT_2CH; } else { audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS; - core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN | + acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN | HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | HDMI_AUDIO_I2S_SD3_EN; - core.layout = HDMI_AUDIO_LAYOUT_8CH; + acore.layout = HDMI_AUDIO_LAYOUT_8CH; } - core.en_spdif = false; + acore.en_spdif = false; /* use sample frequency from channel status word */ - core.fs_override = true; + acore.fs_override = true; /* enable ACR packets */ - core.en_acr_pkt = true; + acore.en_acr_pkt = true; /* disable direct streaming digital audio */ - core.en_dsd_audio = false; + acore.en_dsd_audio = false; /* use parallel audio interface */ - core.en_parallel_aud_input = true; + acore.en_parallel_aud_input = true; /* DMA settings */ if (word_length_16b) @@ -1374,49 +957,37 @@ int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; /* configure DMA and audio FIFO format*/ - ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma); - ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format); + hdmi_wp_audio_config_dma(wp, &audio_dma); + hdmi_wp_audio_config_format(wp, &audio_format); /* configure the core*/ - ti_hdmi_4xxx_core_audio_config(ip_data, &core); + hdmi_core_audio_config(core, &acore); /* configure CEA 861 audio infoframe*/ - ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea); + hdmi_core_audio_infoframe_cfg(core, audio->cea); return 0; } -int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data) +int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp) { - REG_FLD_MOD(hdmi_wp_base(ip_data), - HDMI_WP_AUDIO_CTRL, true, 31, 31); - return 0; -} + REG_FLD_MOD(hdmi_av_base(core), + HDMI_CORE_AV_AUD_MODE, true, 0, 0); -void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data) -{ - REG_FLD_MOD(hdmi_wp_base(ip_data), - HDMI_WP_AUDIO_CTRL, false, 31, 31); -} + hdmi_wp_audio_core_req_enable(wp, true); -int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data) -{ - REG_FLD_MOD(hdmi_av_base(ip_data), - HDMI_CORE_AV_AUD_MODE, true, 0, 0); - REG_FLD_MOD(hdmi_wp_base(ip_data), - HDMI_WP_AUDIO_CTRL, true, 30, 30); return 0; } -void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data) +void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp) { - REG_FLD_MOD(hdmi_av_base(ip_data), + REG_FLD_MOD(hdmi_av_base(core), HDMI_CORE_AV_AUD_MODE, false, 0, 0); - REG_FLD_MOD(hdmi_wp_base(ip_data), - HDMI_WP_AUDIO_CTRL, false, 30, 30); + + hdmi_wp_audio_core_req_enable(wp, false); } -int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size) +int hdmi4_audio_get_dma_port(u32 *offset, u32 *size) { if (!offset || !size) return -EINVAL; @@ -1424,4 +995,42 @@ int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size) *size = 4; return 0; } + #endif + +#define CORE_OFFSET 0x400 +#define CORE_SIZE 0xc00 + +int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) +{ + struct resource *res; + struct resource temp_res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); + if (!res) { + DSSDBG("can't get CORE mem resource by name\n"); + /* + * if hwmod/DT doesn't have the memory resource information + * split into HDMI sub blocks by name, we try again by getting + * the platform's first resource. this code will be removed when + * the driver can get the mem resources by name + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get CORE mem resource\n"); + return -EINVAL; + } + + temp_res.start = res->start + CORE_OFFSET; + temp_res.end = temp_res.start + CORE_SIZE - 1; + res = &temp_res; + } + + core->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!core->base) { + DSSERR("can't ioremap CORE\n"); + return -ENOMEM; + } + + return 0; +} diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/hdmi4_core.h index 6ef2f929a76d..bb646896fa82 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h +++ b/drivers/video/omap2/dss/hdmi4_core.h @@ -1,7 +1,5 @@ /* - * ti_hdmi_4xxx_ip.h - * - * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors. + * HDMI header definition for OMAP4 HDMI core IP * * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ * @@ -18,41 +16,22 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _HDMI_TI_4xxx_H_ -#define _HDMI_TI_4xxx_H_ - -#include <linux/string.h> -#include <video/omapdss.h> -#include "ti_hdmi.h" - -/* HDMI Wrapper */ +#ifndef _HDMI4_CORE_H_ +#define _HDMI4_CORE_H_ -#define HDMI_WP_REVISION 0x0 -#define HDMI_WP_SYSCONFIG 0x10 -#define HDMI_WP_IRQSTATUS_RAW 0x24 -#define HDMI_WP_IRQSTATUS 0x28 -#define HDMI_WP_PWR_CTRL 0x40 -#define HDMI_WP_IRQENABLE_SET 0x2C -#define HDMI_WP_IRQENABLE_CLR 0x30 -#define HDMI_WP_VIDEO_CFG 0x50 -#define HDMI_WP_VIDEO_SIZE 0x60 -#define HDMI_WP_VIDEO_TIMING_H 0x68 -#define HDMI_WP_VIDEO_TIMING_V 0x6C -#define HDMI_WP_WP_CLK 0x70 -#define HDMI_WP_AUDIO_CFG 0x80 -#define HDMI_WP_AUDIO_CFG2 0x84 -#define HDMI_WP_AUDIO_CTRL 0x88 -#define HDMI_WP_AUDIO_DATA 0x8C +#include "hdmi.h" -/* HDMI IP Core System */ +/* OMAP4 HDMI IP Core System */ #define HDMI_CORE_SYS_VND_IDL 0x0 #define HDMI_CORE_SYS_DEV_IDL 0x8 #define HDMI_CORE_SYS_DEV_IDH 0xC #define HDMI_CORE_SYS_DEV_REV 0x10 #define HDMI_CORE_SYS_SRST 0x14 -#define HDMI_CORE_CTRL1 0x20 +#define HDMI_CORE_SYS_SYS_CTRL1 0x20 #define HDMI_CORE_SYS_SYS_STAT 0x24 +#define HDMI_CORE_SYS_SYS_CTRL3 0x28 +#define HDMI_CORE_SYS_DCTL 0x34 #define HDMI_CORE_SYS_DE_DLY 0xC8 #define HDMI_CORE_SYS_DE_CTRL 0xCC #define HDMI_CORE_SYS_DE_TOP 0xD0 @@ -60,20 +39,65 @@ #define HDMI_CORE_SYS_DE_CNTH 0xDC #define HDMI_CORE_SYS_DE_LINL 0xE0 #define HDMI_CORE_SYS_DE_LINH_1 0xE4 +#define HDMI_CORE_SYS_HRES_L 0xE8 +#define HDMI_CORE_SYS_HRES_H 0xEC +#define HDMI_CORE_SYS_VRES_L 0xF0 +#define HDMI_CORE_SYS_VRES_H 0xF4 +#define HDMI_CORE_SYS_IADJUST 0xF8 +#define HDMI_CORE_SYS_POLDETECT 0xFC +#define HDMI_CORE_SYS_HWIDTH1 0x110 +#define HDMI_CORE_SYS_HWIDTH2 0x114 +#define HDMI_CORE_SYS_VWIDTH 0x11C +#define HDMI_CORE_SYS_VID_CTRL 0x120 #define HDMI_CORE_SYS_VID_ACEN 0x124 #define HDMI_CORE_SYS_VID_MODE 0x128 +#define HDMI_CORE_SYS_VID_BLANK1 0x12C +#define HDMI_CORE_SYS_VID_BLANK2 0x130 +#define HDMI_CORE_SYS_VID_BLANK3 0x134 +#define HDMI_CORE_SYS_DC_HEADER 0x138 +#define HDMI_CORE_SYS_VID_DITHER 0x13C +#define HDMI_CORE_SYS_RGB2XVYCC_CT 0x140 +#define HDMI_CORE_SYS_R2Y_COEFF_LOW 0x144 +#define HDMI_CORE_SYS_R2Y_COEFF_UP 0x148 +#define HDMI_CORE_SYS_G2Y_COEFF_LOW 0x14C +#define HDMI_CORE_SYS_G2Y_COEFF_UP 0x150 +#define HDMI_CORE_SYS_B2Y_COEFF_LOW 0x154 +#define HDMI_CORE_SYS_B2Y_COEFF_UP 0x158 +#define HDMI_CORE_SYS_R2CB_COEFF_LOW 0x15C +#define HDMI_CORE_SYS_R2CB_COEFF_UP 0x160 +#define HDMI_CORE_SYS_G2CB_COEFF_LOW 0x164 +#define HDMI_CORE_SYS_G2CB_COEFF_UP 0x168 +#define HDMI_CORE_SYS_B2CB_COEFF_LOW 0x16C +#define HDMI_CORE_SYS_B2CB_COEFF_UP 0x170 +#define HDMI_CORE_SYS_R2CR_COEFF_LOW 0x174 +#define HDMI_CORE_SYS_R2CR_COEFF_UP 0x178 +#define HDMI_CORE_SYS_G2CR_COEFF_LOW 0x17C +#define HDMI_CORE_SYS_G2CR_COEFF_UP 0x180 +#define HDMI_CORE_SYS_B2CR_COEFF_LOW 0x184 +#define HDMI_CORE_SYS_B2CR_COEFF_UP 0x188 +#define HDMI_CORE_SYS_RGB_OFFSET_LOW 0x18C +#define HDMI_CORE_SYS_RGB_OFFSET_UP 0x190 +#define HDMI_CORE_SYS_Y_OFFSET_LOW 0x194 +#define HDMI_CORE_SYS_Y_OFFSET_UP 0x198 +#define HDMI_CORE_SYS_CBCR_OFFSET_LOW 0x19C +#define HDMI_CORE_SYS_CBCR_OFFSET_UP 0x1A0 #define HDMI_CORE_SYS_INTR_STATE 0x1C0 #define HDMI_CORE_SYS_INTR1 0x1C4 #define HDMI_CORE_SYS_INTR2 0x1C8 #define HDMI_CORE_SYS_INTR3 0x1CC #define HDMI_CORE_SYS_INTR4 0x1D0 -#define HDMI_CORE_SYS_UMASK1 0x1D4 +#define HDMI_CORE_SYS_INTR_UNMASK1 0x1D4 +#define HDMI_CORE_SYS_INTR_UNMASK2 0x1D8 +#define HDMI_CORE_SYS_INTR_UNMASK3 0x1DC +#define HDMI_CORE_SYS_INTR_UNMASK4 0x1E0 +#define HDMI_CORE_SYS_INTR_CTRL 0x1E4 #define HDMI_CORE_SYS_TMDS_CTRL 0x208 -#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 -#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 -#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 -#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 +/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */ +#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC 0x1 +#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC 0x1 +#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS 0x1 +#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE 0x1 /* HDMI DDC E-DID */ #define HDMI_CORE_DDC_ADDR 0x3B4 @@ -158,35 +182,6 @@ #define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 -/* PLL */ - -#define PLLCTRL_PLL_CONTROL 0x0 -#define PLLCTRL_PLL_STATUS 0x4 -#define PLLCTRL_PLL_GO 0x8 -#define PLLCTRL_CFG1 0xC -#define PLLCTRL_CFG2 0x10 -#define PLLCTRL_CFG3 0x14 -#define PLLCTRL_CFG4 0x20 - -/* HDMI PHY */ - -#define HDMI_TXPHY_TX_CTRL 0x0 -#define HDMI_TXPHY_DIGITAL_CTRL 0x4 -#define HDMI_TXPHY_POWER_CTRL 0x8 -#define HDMI_TXPHY_PAD_CFG_CTRL 0xC - -#define REG_FLD_MOD(base, idx, val, start, end) \ - hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ - val, start, end)) -#define REG_GET(base, idx, start, end) \ - FLD_GET(hdmi_read_reg(base, idx), start, end) - -enum hdmi_phy_pwr { - HDMI_PHYPWRCMD_OFF = 0, - HDMI_PHYPWRCMD_LDOON = 1, - HDMI_PHYPWRCMD_TXON = 2 -}; - enum hdmi_core_inputbus_width { HDMI_INPUT_8BIT = 0, HDMI_INPUT_10BIT = 1, @@ -229,114 +224,6 @@ enum hdmi_core_packet_ctrl { HDMI_PACKETREPEATOFF = 0 }; -/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ -enum hdmi_core_infoframe { - HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, - HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, - HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, - HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, - HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, - HDMI_INFOFRAME_AVI_DB1B_NO = 0, - HDMI_INFOFRAME_AVI_DB1B_VERT = 1, - HDMI_INFOFRAME_AVI_DB1B_HORI = 2, - HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, - HDMI_INFOFRAME_AVI_DB1S_0 = 0, - HDMI_INFOFRAME_AVI_DB1S_1 = 1, - HDMI_INFOFRAME_AVI_DB1S_2 = 2, - HDMI_INFOFRAME_AVI_DB2C_NO = 0, - HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, - HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, - HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, - HDMI_INFOFRAME_AVI_DB2M_NO = 0, - HDMI_INFOFRAME_AVI_DB2M_43 = 1, - HDMI_INFOFRAME_AVI_DB2M_169 = 2, - HDMI_INFOFRAME_AVI_DB2R_SAME = 8, - HDMI_INFOFRAME_AVI_DB2R_43 = 9, - HDMI_INFOFRAME_AVI_DB2R_169 = 10, - HDMI_INFOFRAME_AVI_DB2R_149 = 11, - HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, - HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, - HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, - HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, - HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, - HDMI_INFOFRAME_AVI_DB3Q_LR = 1, - HDMI_INFOFRAME_AVI_DB3Q_FR = 2, - HDMI_INFOFRAME_AVI_DB3SC_NO = 0, - HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, - HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, - HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, - HDMI_INFOFRAME_AVI_DB5PR_NO = 0, - HDMI_INFOFRAME_AVI_DB5PR_2 = 1, - HDMI_INFOFRAME_AVI_DB5PR_3 = 2, - HDMI_INFOFRAME_AVI_DB5PR_4 = 3, - HDMI_INFOFRAME_AVI_DB5PR_5 = 4, - HDMI_INFOFRAME_AVI_DB5PR_6 = 5, - HDMI_INFOFRAME_AVI_DB5PR_7 = 6, - HDMI_INFOFRAME_AVI_DB5PR_8 = 7, - HDMI_INFOFRAME_AVI_DB5PR_9 = 8, - HDMI_INFOFRAME_AVI_DB5PR_10 = 9, -}; - -enum hdmi_packing_mode { - HDMI_PACK_10b_RGB_YUV444 = 0, - HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, - HDMI_PACK_20b_YUV422 = 2, - HDMI_PACK_ALREADYPACKED = 7 -}; - -enum hdmi_core_audio_layout { - HDMI_AUDIO_LAYOUT_2CH = 0, - HDMI_AUDIO_LAYOUT_8CH = 1 -}; - -enum hdmi_core_cts_mode { - HDMI_AUDIO_CTS_MODE_HW = 0, - HDMI_AUDIO_CTS_MODE_SW = 1 -}; - -enum hdmi_stereo_channels { - HDMI_AUDIO_STEREO_NOCHANNELS = 0, - HDMI_AUDIO_STEREO_ONECHANNEL = 1, - HDMI_AUDIO_STEREO_TWOCHANNELS = 2, - HDMI_AUDIO_STEREO_THREECHANNELS = 3, - HDMI_AUDIO_STEREO_FOURCHANNELS = 4 -}; - -enum hdmi_audio_type { - HDMI_AUDIO_TYPE_LPCM = 0, - HDMI_AUDIO_TYPE_IEC = 1 -}; - -enum hdmi_audio_justify { - HDMI_AUDIO_JUSTIFY_LEFT = 0, - HDMI_AUDIO_JUSTIFY_RIGHT = 1 -}; - -enum hdmi_audio_sample_order { - HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, - HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 -}; - -enum hdmi_audio_samples_perword { - HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, - HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 -}; - -enum hdmi_audio_sample_size { - HDMI_AUDIO_SAMPLE_16BITS = 0, - HDMI_AUDIO_SAMPLE_24BITS = 1 -}; - -enum hdmi_audio_transf_mode { - HDMI_AUDIO_TRANSF_DMA = 0, - HDMI_AUDIO_TRANSF_IRQ = 1 -}; - -enum hdmi_audio_blk_strt_end_sig { - HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, - HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 -}; - enum hdmi_audio_i2s_config { HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, @@ -352,17 +239,6 @@ enum hdmi_audio_i2s_config { HDMI_AUDIO_I2S_SD3_EN = 1 << 3, }; -enum hdmi_audio_mclk_mode { - HDMI_AUDIO_MCLK_128FS = 0, - HDMI_AUDIO_MCLK_256FS = 1, - HDMI_AUDIO_MCLK_384FS = 2, - HDMI_AUDIO_MCLK_512FS = 3, - HDMI_AUDIO_MCLK_768FS = 4, - HDMI_AUDIO_MCLK_1024FS = 5, - HDMI_AUDIO_MCLK_1152FS = 6, - HDMI_AUDIO_MCLK_192FS = 7 -}; - struct hdmi_core_video_config { enum hdmi_core_inputbus_width ip_bus_width; enum hdmi_core_dither_trunc op_dither_truc; @@ -383,55 +259,18 @@ struct hdmi_core_packet_enable_repeat { u32 generic_pkt_repeat; }; -struct hdmi_video_format { - enum hdmi_packing_mode packing_mode; - u32 y_res; /* Line per panel */ - u32 x_res; /* pixel per line */ -}; - -struct hdmi_audio_format { - enum hdmi_stereo_channels stereo_channels; - u8 active_chnnls_msk; - enum hdmi_audio_type type; - enum hdmi_audio_justify justification; - enum hdmi_audio_sample_order sample_order; - enum hdmi_audio_samples_perword samples_per_word; - enum hdmi_audio_sample_size sample_size; - enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; -}; - -struct hdmi_audio_dma { - u8 transfer_size; - u8 block_size; - enum hdmi_audio_transf_mode mode; - u16 fifo_threshold; -}; - -struct hdmi_core_audio_i2s_config { - u8 in_length_bits; - u8 justification; - u8 sck_edge_mode; - u8 vbit; - u8 direction; - u8 shift; - u8 active_sds; -}; - -struct hdmi_core_audio_config { - struct hdmi_core_audio_i2s_config i2s_cfg; - struct snd_aes_iec958 *iec60958_cfg; - bool fs_override; - u32 n; - u32 cts; - u32 aud_par_busclk; - enum hdmi_core_audio_layout layout; - enum hdmi_core_cts_mode cts_mode; - bool use_mclk; - enum hdmi_audio_mclk_mode mclk_mode; - bool en_acr_pkt; - bool en_dsd_audio; - bool en_parallel_aud_input; - bool en_spdif; -}; +int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len); +void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, + struct hdmi_config *cfg); +void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); +int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); + +#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); +void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); +int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, + struct omap_dss_audio *audio, u32 pclk); +int hdmi4_audio_get_dma_port(u32 *offset, u32 *size); +#endif #endif diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/omap2/dss/hdmi_common.c new file mode 100644 index 000000000000..0614922902dd --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_common.c @@ -0,0 +1,425 @@ + +/* + * Logic for the below structure : + * user enters the CEA or VESA timings by specifying the HDMI/DVI code. + * There is a correspondence between CEA/VESA timing and code, please + * refer to section 6.3 in HDMI 1.3 specification for timing code. + * + * In the below structure, cea_vesa_timings corresponds to all OMAP4 + * supported CEA and VESA timing values.code_cea corresponds to the CEA + * code, It is used to get the timing from cea_vesa_timing array.Similarly + * with code_vesa. Code_index is used for back mapping, that is once EDID + * is read from the TV, EDID is parsed to find the timing values and then + * map it to corresponding CEA or VESA index. + */ + +#define DSS_SUBSYS_NAME "HDMI" + +#include <linux/kernel.h> +#include <linux/err.h> +#include <video/omapdss.h> + +#include "hdmi.h" + +static const struct hdmi_config cea_timings[] = { + { + { 640, 480, 25200, 96, 16, 48, 2, 10, 33, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 1, HDMI_HDMI }, + }, + { + { 720, 480, 27027, 62, 16, 60, 6, 9, 30, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 2, HDMI_HDMI }, + }, + { + { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 4, HDMI_HDMI }, + }, + { + { 1920, 540, 74250, 44, 88, 148, 5, 2, 15, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + true, }, + { 5, HDMI_HDMI }, + }, + { + { 1440, 240, 27027, 124, 38, 114, 3, 4, 15, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + true, }, + { 6, HDMI_HDMI }, + }, + { + { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 16, HDMI_HDMI }, + }, + { + { 720, 576, 27000, 64, 12, 68, 5, 5, 39, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 17, HDMI_HDMI }, + }, + { + { 1280, 720, 74250, 40, 440, 220, 5, 5, 20, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 19, HDMI_HDMI }, + }, + { + { 1920, 540, 74250, 44, 528, 148, 5, 2, 15, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + true, }, + { 20, HDMI_HDMI }, + }, + { + { 1440, 288, 27000, 126, 24, 138, 3, 2, 19, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + true, }, + { 21, HDMI_HDMI }, + }, + { + { 1440, 576, 54000, 128, 24, 136, 5, 5, 39, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 29, HDMI_HDMI }, + }, + { + { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 31, HDMI_HDMI }, + }, + { + { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 32, HDMI_HDMI }, + }, + { + { 2880, 480, 108108, 248, 64, 240, 6, 9, 30, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 35, HDMI_HDMI }, + }, + { + { 2880, 576, 108000, 256, 48, 272, 5, 5, 39, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 37, HDMI_HDMI }, + }, +}; + +static const struct hdmi_config vesa_timings[] = { +/* VESA From Here */ + { + { 640, 480, 25175, 96, 16, 48, 2, 11, 31, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 4, HDMI_DVI }, + }, + { + { 800, 600, 40000, 128, 40, 88, 4, 1, 23, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 9, HDMI_DVI }, + }, + { + { 848, 480, 33750, 112, 16, 112, 8, 6, 23, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0xE, HDMI_DVI }, + }, + { + { 1280, 768, 79500, 128, 64, 192, 7, 3, 20, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x17, HDMI_DVI }, + }, + { + { 1280, 800, 83500, 128, 72, 200, 6, 3, 22, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x1C, HDMI_DVI }, + }, + { + { 1360, 768, 85500, 112, 64, 256, 6, 3, 18, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x27, HDMI_DVI }, + }, + { + { 1280, 960, 108000, 112, 96, 312, 3, 1, 36, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x20, HDMI_DVI }, + }, + { + { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x23, HDMI_DVI }, + }, + { + { 1024, 768, 65000, 136, 24, 160, 6, 3, 29, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x10, HDMI_DVI }, + }, + { + { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x2A, HDMI_DVI }, + }, + { + { 1440, 900, 106500, 152, 80, 232, 6, 3, 25, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x2F, HDMI_DVI }, + }, + { + { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, + false, }, + { 0x3A, HDMI_DVI }, + }, + { + { 1366, 768, 85500, 143, 70, 213, 3, 3, 24, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x51, HDMI_DVI }, + }, + { + { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x52, HDMI_DVI }, + }, + { + { 1280, 768, 68250, 32, 48, 80, 7, 3, 12, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x16, HDMI_DVI }, + }, + { + { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x29, HDMI_DVI }, + }, + { + { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x39, HDMI_DVI }, + }, + { + { 1280, 800, 79500, 32, 48, 80, 6, 3, 14, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x1B, HDMI_DVI }, + }, + { + { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, + OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x55, HDMI_DVI }, + }, + { + { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26, + OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, + false, }, + { 0x44, HDMI_DVI }, + }, +}; + +const struct hdmi_config *hdmi_default_timing(void) +{ + return &vesa_timings[0]; +} + +static const struct hdmi_config *hdmi_find_timing(int code, + const struct hdmi_config *timings_arr, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (timings_arr[i].cm.code == code) + return &timings_arr[i]; + } + + return NULL; +} + +const struct hdmi_config *hdmi_get_timings(int mode, int code) +{ + const struct hdmi_config *arr; + int len; + + if (mode == HDMI_DVI) { + arr = vesa_timings; + len = ARRAY_SIZE(vesa_timings); + } else { + arr = cea_timings; + len = ARRAY_SIZE(cea_timings); + } + + return hdmi_find_timing(code, arr, len); +} + +static bool hdmi_timings_compare(struct omap_video_timings *timing1, + const struct omap_video_timings *timing2) +{ + int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; + + if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == + DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && + (timing2->x_res == timing1->x_res) && + (timing2->y_res == timing1->y_res)) { + + timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; + timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; + timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; + timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp; + + DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ + "timing2_hsync = %d timing2_vsync = %d\n", + timing1_hsync, timing1_vsync, + timing2_hsync, timing2_vsync); + + if ((timing1_hsync == timing2_hsync) && + (timing1_vsync == timing2_vsync)) { + return true; + } + } + return false; +} + +struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) +{ + int i; + struct hdmi_cm cm = {-1}; + DSSDBG("hdmi_get_code\n"); + + for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { + if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { + cm = cea_timings[i].cm; + goto end; + } + } + for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { + if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { + cm = vesa_timings[i].cm; + goto end; + } + } + +end: + return cm; +} + +#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) +{ + u32 deep_color; + bool deep_color_correct = false; + + if (n == NULL || cts == NULL) + return -EINVAL; + + /* TODO: When implemented, query deep color mode here. */ + deep_color = 100; + + /* + * When using deep color, the default N value (as in the HDMI + * specification) yields to an non-integer CTS. Hence, we + * modify it while keeping the restrictions described in + * section 7.2.1 of the HDMI 1.4a specification. + */ + switch (sample_freq) { + case 32000: + case 48000: + case 96000: + case 192000: + if (deep_color == 125) + if (pclk == 27027 || pclk == 74250) + deep_color_correct = true; + if (deep_color == 150) + if (pclk == 27027) + deep_color_correct = true; + break; + case 44100: + case 88200: + case 176400: + if (deep_color == 125) + if (pclk == 27027) + deep_color_correct = true; + break; + default: + return -EINVAL; + } + + if (deep_color_correct) { + switch (sample_freq) { + case 32000: + *n = 8192; + break; + case 44100: + *n = 12544; + break; + case 48000: + *n = 8192; + break; + case 88200: + *n = 25088; + break; + case 96000: + *n = 16384; + break; + case 176400: + *n = 50176; + break; + case 192000: + *n = 32768; + break; + default: + return -EINVAL; + } + } else { + switch (sample_freq) { + case 32000: + *n = 4096; + break; + case 44100: + *n = 6272; + break; + case 48000: + *n = 6144; + break; + case 88200: + *n = 12544; + break; + case 96000: + *n = 12288; + break; + case 176400: + *n = 25088; + break; + case 192000: + *n = 24576; + break; + default: + return -EINVAL; + } + } + /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ + *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); + + return 0; +} +#endif diff --git a/drivers/video/omap2/dss/hdmi_phy.c b/drivers/video/omap2/dss/hdmi_phy.c new file mode 100644 index 000000000000..dd376ce8da01 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_phy.c @@ -0,0 +1,160 @@ +/* + * HDMI PHY + * + * Copyright (C) 2013 Texas Instruments Incorporated + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <video/omapdss.h> + +#include "dss.h" +#include "hdmi.h" + +void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s) +{ +#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ + hdmi_read_reg(phy->base, r)) + + DUMPPHY(HDMI_TXPHY_TX_CTRL); + DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); + DUMPPHY(HDMI_TXPHY_POWER_CTRL); + DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); +} + +static irqreturn_t hdmi_irq_handler(int irq, void *data) +{ + struct hdmi_wp_data *wp = data; + u32 irqstatus; + + irqstatus = hdmi_wp_get_irqstatus(wp); + hdmi_wp_set_irqstatus(wp, irqstatus); + + if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && + irqstatus & HDMI_IRQ_LINK_DISCONNECT) { + /* + * If we get both connect and disconnect interrupts at the same + * time, turn off the PHY, clear interrupts, and restart, which + * raises connect interrupt if a cable is connected, or nothing + * if cable is not connected. + */ + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); + + hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | + HDMI_IRQ_LINK_DISCONNECT); + + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); + } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + } + + return IRQ_HANDLED; +} + +int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, + struct hdmi_config *cfg) +{ + u16 r = 0; + u32 irqstatus; + + hdmi_wp_clear_irqenable(wp, 0xffffffff); + + irqstatus = hdmi_wp_get_irqstatus(wp); + hdmi_wp_set_irqstatus(wp, irqstatus); + + r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + if (r) + return r; + + /* + * Read address 0 in order to get the SCP reset done completed + * Dummy access performed to make sure reset is done + */ + hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL); + + /* + * Write to phy address 0 to configure the clock + * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field + */ + REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); + + /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ + hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); + + /* Setup max LDO voltage */ + REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); + + /* Write to phy address 3 to change the polarity control */ + REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); + + r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler, + IRQF_ONESHOT, "OMAP HDMI", wp); + if (r) { + DSSERR("HDMI IRQ request failed\n"); + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); + return r; + } + + hdmi_wp_set_irqenable(wp, + HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); + + return 0; +} + +void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp) +{ + free_irq(phy->irq, wp); + + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); +} + +#define PHY_OFFSET 0x300 +#define PHY_SIZE 0x100 + +int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) +{ + struct resource *res; + struct resource temp_res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); + if (!res) { + DSSDBG("can't get PHY mem resource by name\n"); + /* + * if hwmod/DT doesn't have the memory resource information + * split into HDMI sub blocks by name, we try again by getting + * the platform's first resource. this code will be removed when + * the driver can get the mem resources by name + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get PHY mem resource\n"); + return -EINVAL; + } + + temp_res.start = res->start + PHY_OFFSET; + temp_res.end = temp_res.start + PHY_SIZE - 1; + res = &temp_res; + } + + phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!phy->base) { + DSSERR("can't ioremap TX PHY\n"); + return -ENOMEM; + } + + phy->irq = platform_get_irq(pdev, 0); + if (phy->irq < 0) { + DSSERR("platform_get_irq failed\n"); + return -ENODEV; + } + + return 0; +} diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/omap2/dss/hdmi_pll.c new file mode 100644 index 000000000000..5fc71215c303 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_pll.c @@ -0,0 +1,232 @@ +/* + * HDMI PLL + * + * Copyright (C) 2013 Texas Instruments Incorporated + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#define DSS_SUBSYS_NAME "HDMIPLL" + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <video/omapdss.h> + +#include "dss.h" +#include "hdmi.h" + +#define HDMI_DEFAULT_REGN 16 +#define HDMI_DEFAULT_REGM2 1 + +void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) +{ +#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ + hdmi_read_reg(pll->base, r)) + + DUMPPLL(PLLCTRL_PLL_CONTROL); + DUMPPLL(PLLCTRL_PLL_STATUS); + DUMPPLL(PLLCTRL_PLL_GO); + DUMPPLL(PLLCTRL_CFG1); + DUMPPLL(PLLCTRL_CFG2); + DUMPPLL(PLLCTRL_CFG3); + DUMPPLL(PLLCTRL_SSC_CFG1); + DUMPPLL(PLLCTRL_SSC_CFG2); + DUMPPLL(PLLCTRL_CFG4); +} + +void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy) +{ + struct hdmi_pll_info *pi = &pll->info; + unsigned long refclk; + u32 mf; + + /* use our funky units */ + clkin /= 10000; + + /* + * Input clock is predivided by N + 1 + * out put of which is reference clk + */ + + pi->regn = HDMI_DEFAULT_REGN; + + refclk = clkin / pi->regn; + + pi->regm2 = HDMI_DEFAULT_REGM2; + + /* + * multiplier is pixel_clk/ref_clk + * Multiplying by 100 to avoid fractional part removal + */ + pi->regm = phy * pi->regm2 / refclk; + + /* + * fractional multiplier is remainder of the difference between + * multiplier and actual phy(required pixel clock thus should be + * multiplied by 2^18(262144) divided by the reference clock + */ + mf = (phy - pi->regm / pi->regm2 * refclk) * 262144; + pi->regmf = pi->regm2 * mf / refclk; + + /* + * Dcofreq should be set to 1 if required pixel clock + * is greater than 1000MHz + */ + pi->dcofreq = phy > 1000 * 100; + pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; + + /* Set the reference clock to sysclk reference */ + pi->refsel = HDMI_REFSEL_SYSCLK; + + DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); + DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); +} + + +static int hdmi_pll_config(struct hdmi_pll_data *pll) +{ + u32 r; + struct hdmi_pll_info *fmt = &pll->info; + + /* PLL start always use manual mode */ + REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); + + r = hdmi_read_reg(pll->base, PLLCTRL_CFG1); + r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ + r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ + hdmi_write_reg(pll->base, PLLCTRL_CFG1, r); + + r = hdmi_read_reg(pll->base, PLLCTRL_CFG2); + + r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ + r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ + r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ + r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ + + if (fmt->dcofreq) { + /* divider programming for frequency beyond 1000Mhz */ + REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10); + r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ + } else { + r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ + } + + hdmi_write_reg(pll->base, PLLCTRL_CFG2, r); + + r = hdmi_read_reg(pll->base, PLLCTRL_CFG4); + r = FLD_MOD(r, fmt->regm2, 24, 18); + r = FLD_MOD(r, fmt->regmf, 17, 0); + hdmi_write_reg(pll->base, PLLCTRL_CFG4, r); + + /* go now */ + REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0); + + /* wait for bit change */ + if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO, + 0, 0, 1) != 1) { + DSSERR("PLL GO bit not set\n"); + return -ETIMEDOUT; + } + + /* Wait till the lock bit is set in PLL status */ + if (hdmi_wait_for_bit_change(pll->base, + PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { + DSSERR("cannot lock PLL\n"); + DSSERR("CFG1 0x%x\n", + hdmi_read_reg(pll->base, PLLCTRL_CFG1)); + DSSERR("CFG2 0x%x\n", + hdmi_read_reg(pll->base, PLLCTRL_CFG2)); + DSSERR("CFG4 0x%x\n", + hdmi_read_reg(pll->base, PLLCTRL_CFG4)); + return -ETIMEDOUT; + } + + DSSDBG("PLL locked!\n"); + + return 0; +} + +static int hdmi_pll_reset(struct hdmi_pll_data *pll) +{ + /* SYSRESET controlled by power FSM */ + REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3); + + /* READ 0x0 reset is in progress */ + if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) + != 1) { + DSSERR("Failed to sysreset PLL\n"); + return -ETIMEDOUT; + } + + return 0; +} + +int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) +{ + u16 r = 0; + + r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); + if (r) + return r; + + r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); + if (r) + return r; + + r = hdmi_pll_reset(pll); + if (r) + return r; + + r = hdmi_pll_config(pll); + if (r) + return r; + + return 0; +} + +void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) +{ + hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); +} + +#define PLL_OFFSET 0x200 +#define PLL_SIZE 0x100 + +int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) +{ + struct resource *res; + struct resource temp_res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); + if (!res) { + DSSDBG("can't get PLL mem resource by name\n"); + /* + * if hwmod/DT doesn't have the memory resource information + * split into HDMI sub blocks by name, we try again by getting + * the platform's first resource. this code will be removed when + * the driver can get the mem resources by name + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get PLL mem resource\n"); + return -EINVAL; + } + + temp_res.start = res->start + PLL_OFFSET; + temp_res.end = temp_res.start + PLL_SIZE - 1; + res = &temp_res; + } + + pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!pll->base) { + DSSERR("can't ioremap PLLCTRL\n"); + return -ENOMEM; + } + + return 0; +} diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/omap2/dss/hdmi_wp.c new file mode 100644 index 000000000000..cd620c6e43a0 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_wp.c @@ -0,0 +1,273 @@ +/* + * HDMI wrapper + * + * Copyright (C) 2013 Texas Instruments Incorporated + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#define DSS_SUBSYS_NAME "HDMIWP" + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <video/omapdss.h> + +#include "dss.h" +#include "hdmi.h" + +void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s) +{ +#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r)) + + DUMPREG(HDMI_WP_REVISION); + DUMPREG(HDMI_WP_SYSCONFIG); + DUMPREG(HDMI_WP_IRQSTATUS_RAW); + DUMPREG(HDMI_WP_IRQSTATUS); + DUMPREG(HDMI_WP_IRQENABLE_SET); + DUMPREG(HDMI_WP_IRQENABLE_CLR); + DUMPREG(HDMI_WP_IRQWAKEEN); + DUMPREG(HDMI_WP_PWR_CTRL); + DUMPREG(HDMI_WP_DEBOUNCE); + DUMPREG(HDMI_WP_VIDEO_CFG); + DUMPREG(HDMI_WP_VIDEO_SIZE); + DUMPREG(HDMI_WP_VIDEO_TIMING_H); + DUMPREG(HDMI_WP_VIDEO_TIMING_V); + DUMPREG(HDMI_WP_CLK); + DUMPREG(HDMI_WP_AUDIO_CFG); + DUMPREG(HDMI_WP_AUDIO_CFG2); + DUMPREG(HDMI_WP_AUDIO_CTRL); + DUMPREG(HDMI_WP_AUDIO_DATA); +} + +u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp) +{ + return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS); +} + +void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus) +{ + hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus); + /* flush posted write */ + hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS); +} + +void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask) +{ + hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask); +} + +void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask) +{ + hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask); +} + +/* PHY_PWR_CMD */ +int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val) +{ + /* Return if already the state */ + if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val) + return 0; + + /* Command for power control of HDMI PHY */ + REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6); + + /* Status of the power control of HDMI PHY */ + if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val) + != val) { + DSSERR("Failed to set PHY power mode to %d\n", val); + return -ETIMEDOUT; + } + + return 0; +} + +/* PLL_PWR_CMD */ +int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val) +{ + /* Command for power control of HDMI PLL */ + REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2); + + /* wait till PHY_PWR_STATUS is set */ + if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val) + != val) { + DSSERR("Failed to set PLL_PWR_STATUS\n"); + return -ETIMEDOUT; + } + + return 0; +} + +int hdmi_wp_video_start(struct hdmi_wp_data *wp) +{ + REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31); + + return 0; +} + +void hdmi_wp_video_stop(struct hdmi_wp_data *wp) +{ + REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); +} + +void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, + struct hdmi_video_format *video_fmt) +{ + u32 l = 0; + + REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, + 10, 8); + + l |= FLD_VAL(video_fmt->y_res, 31, 16); + l |= FLD_VAL(video_fmt->x_res, 15, 0); + hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l); +} + +void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, + struct omap_video_timings *timings) +{ + u32 r; + bool vsync_pol, hsync_pol; + DSSDBG("Enter hdmi_wp_video_config_interface\n"); + + vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; + + r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); + r = FLD_MOD(r, vsync_pol, 7, 7); + r = FLD_MOD(r, hsync_pol, 6, 6); + r = FLD_MOD(r, timings->interlace, 3, 3); + r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ + hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r); +} + +void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, + struct omap_video_timings *timings) +{ + u32 timing_h = 0; + u32 timing_v = 0; + + DSSDBG("Enter hdmi_wp_video_config_timing\n"); + + timing_h |= FLD_VAL(timings->hbp, 31, 20); + timing_h |= FLD_VAL(timings->hfp, 19, 8); + timing_h |= FLD_VAL(timings->hsw, 7, 0); + hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); + + timing_v |= FLD_VAL(timings->vbp, 31, 20); + timing_v |= FLD_VAL(timings->vfp, 19, 8); + timing_v |= FLD_VAL(timings->vsw, 7, 0); + hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); +} + +void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, + struct omap_video_timings *timings, struct hdmi_config *param) +{ + DSSDBG("Enter hdmi_wp_video_init_format\n"); + + video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; + video_fmt->y_res = param->timings.y_res; + video_fmt->x_res = param->timings.x_res; + + timings->hbp = param->timings.hbp; + timings->hfp = param->timings.hfp; + timings->hsw = param->timings.hsw; + timings->vbp = param->timings.vbp; + timings->vfp = param->timings.vfp; + timings->vsw = param->timings.vsw; + timings->vsync_level = param->timings.vsync_level; + timings->hsync_level = param->timings.hsync_level; + timings->interlace = param->timings.interlace; +} + +#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, + struct hdmi_audio_format *aud_fmt) +{ + u32 r; + + DSSDBG("Enter hdmi_wp_audio_config_format\n"); + + r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG); + r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); + r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); + r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); + r = FLD_MOD(r, aud_fmt->type, 4, 4); + r = FLD_MOD(r, aud_fmt->justification, 3, 3); + r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); + r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); + r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); + hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r); +} + +void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, + struct hdmi_audio_dma *aud_dma) +{ + u32 r; + + DSSDBG("Enter hdmi_wp_audio_config_dma\n"); + + r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2); + r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); + r = FLD_MOD(r, aud_dma->block_size, 7, 0); + hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r); + + r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL); + r = FLD_MOD(r, aud_dma->mode, 9, 9); + r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); + hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r); +} + +int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable) +{ + REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31); + + return 0; +} + +int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable) +{ + REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30); + + return 0; +} +#endif + +#define WP_SIZE 0x200 + +int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) +{ + struct resource *res; + struct resource temp_res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp"); + if (!res) { + DSSDBG("can't get WP mem resource by name\n"); + /* + * if hwmod/DT doesn't have the memory resource information + * split into HDMI sub blocks by name, we try again by getting + * the platform's first resource. this code will be removed when + * the driver can get the mem resources by name + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DSSERR("can't get WP mem resource\n"); + return -EINVAL; + } + + temp_res.start = res->start; + temp_res.end = temp_res.start + WP_SIZE - 1; + res = &temp_res; + } + + wp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!wp->base) { + DSSERR("can't ioremap HDMI WP\n"); + return -ENOMEM; + } + + return 0; +} diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index eccde322c28a..2f7cee985cdd 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -113,11 +113,6 @@ void dss_uninit_overlays(struct platform_device *pdev) int dss_ovl_simple_check(struct omap_overlay *ovl, const struct omap_overlay_info *info) { - if (info->paddr == 0) { - DSSERR("check_overlay: paddr cannot be 0\n"); - return -EINVAL; - } - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { if (info->out_width != 0 && info->width != info->out_width) { DSSERR("check_overlay: overlay %d doesn't support " diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3bf47c92aedf..efb9ee9e3c96 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -264,7 +264,8 @@ static int sdi_init_regulator(void) vdds_sdi = devm_regulator_get(&sdi.pdev->dev, "vdds_sdi"); if (IS_ERR(vdds_sdi)) { - DSSERR("can't get VDDS_SDI regulator\n"); + if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER) + DSSERR("can't get VDDS_SDI regulator\n"); return PTR_ERR(vdds_sdi); } diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h deleted file mode 100644 index 45215f44617c..000000000000 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * ti_hdmi.h - * - * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor. - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _TI_HDMI_H -#define _TI_HDMI_H - -struct hdmi_ip_data; - -enum hdmi_pll_pwr { - HDMI_PLLPWRCMD_ALLOFF = 0, - HDMI_PLLPWRCMD_PLLONLY = 1, - HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, - HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 -}; - -enum hdmi_core_hdmi_dvi { - HDMI_DVI = 0, - HDMI_HDMI = 1 -}; - -enum hdmi_clk_refsel { - HDMI_REFSEL_PCLK = 0, - HDMI_REFSEL_REF1 = 1, - HDMI_REFSEL_REF2 = 2, - HDMI_REFSEL_SYSCLK = 3 -}; - -struct hdmi_cm { - int code; - int mode; -}; - -struct hdmi_config { - struct omap_video_timings timings; - struct hdmi_cm cm; -}; - -/* HDMI PLL structure */ -struct hdmi_pll_info { - u16 regn; - u16 regm; - u32 regmf; - u16 regm2; - u16 regsd; - u16 dcofreq; - enum hdmi_clk_refsel refsel; -}; - -struct ti_hdmi_ip_ops { - - void (*video_configure)(struct hdmi_ip_data *ip_data); - - int (*phy_enable)(struct hdmi_ip_data *ip_data); - - void (*phy_disable)(struct hdmi_ip_data *ip_data); - - int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); - - int (*pll_enable)(struct hdmi_ip_data *ip_data); - - void (*pll_disable)(struct hdmi_ip_data *ip_data); - - int (*video_enable)(struct hdmi_ip_data *ip_data); - - void (*video_disable)(struct hdmi_ip_data *ip_data); - - void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); - - void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); - - void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s); - - void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); - -#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) - int (*audio_enable)(struct hdmi_ip_data *ip_data); - - void (*audio_disable)(struct hdmi_ip_data *ip_data); - - int (*audio_start)(struct hdmi_ip_data *ip_data); - - void (*audio_stop)(struct hdmi_ip_data *ip_data); - - int (*audio_config)(struct hdmi_ip_data *ip_data, - struct omap_dss_audio *audio); - - int (*audio_get_dma_port)(u32 *offset, u32 *size); -#endif - -}; - -/* - * Refer to section 8.2 in HDMI 1.3 specification for - * details about infoframe databytes - */ -struct hdmi_core_infoframe_avi { - /* Y0, Y1 rgb,yCbCr */ - u8 db1_format; - /* A0 Active information Present */ - u8 db1_active_info; - /* B0, B1 Bar info data valid */ - u8 db1_bar_info_dv; - /* S0, S1 scan information */ - u8 db1_scan_info; - /* C0, C1 colorimetry */ - u8 db2_colorimetry; - /* M0, M1 Aspect ratio (4:3, 16:9) */ - u8 db2_aspect_ratio; - /* R0...R3 Active format aspect ratio */ - u8 db2_active_fmt_ar; - /* ITC IT content. */ - u8 db3_itc; - /* EC0, EC1, EC2 Extended colorimetry */ - u8 db3_ec; - /* Q1, Q0 Quantization range */ - u8 db3_q_range; - /* SC1, SC0 Non-uniform picture scaling */ - u8 db3_nup_scaling; - /* VIC0..6 Video format identification */ - u8 db4_videocode; - /* PR0..PR3 Pixel repetition factor */ - u8 db5_pixel_repeat; - /* Line number end of top bar */ - u16 db6_7_line_eoftop; - /* Line number start of bottom bar */ - u16 db8_9_line_sofbottom; - /* Pixel number end of left bar */ - u16 db10_11_pixel_eofleft; - /* Pixel number start of right bar */ - u16 db12_13_pixel_sofright; -}; - -struct hdmi_ip_data { - void __iomem *base_wp; /* HDMI wrapper */ - unsigned long core_sys_offset; - unsigned long core_av_offset; - unsigned long pll_offset; - unsigned long phy_offset; - int irq; - const struct ti_hdmi_ip_ops *ops; - struct hdmi_config cfg; - struct hdmi_pll_info pll_data; - struct hdmi_core_infoframe_avi avi_cfg; - - /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ - struct mutex lock; -}; -int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); -int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); -int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data); -int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); -void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); -void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); -void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); -#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) -int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts); -int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data); -int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data); -void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); -int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, - struct omap_dss_audio *audio); -int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size); -#endif -#endif diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 5f88ac47b7fa..2cd7f7e42105 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -639,7 +639,8 @@ static int venc_init_regulator(void) vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); if (IS_ERR(vdda_dac)) { - DSSERR("can't get VDDA_DAC regulator\n"); + if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) + DSSERR("can't get VDDA_DAC regulator\n"); return PTR_ERR(vdda_dac); } diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 27d6905683f3..fcb9e932d00c 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1833,6 +1833,16 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev) if (fbdev == NULL) return; + for (i = 0; i < fbdev->num_fbs; i++) { + struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); + int j; + + for (j = 0; j < ofbi->num_overlays; j++) { + struct omap_overlay *ovl = ofbi->overlays[j]; + ovl->disable(ovl); + } + } + for (i = 0; i < fbdev->num_fbs; i++) unregister_framebuffer(fbdev->fbs[i]); @@ -2557,6 +2567,15 @@ static int omapfb_probe(struct platform_device *pdev) goto cleanup; } + if (def_display) { + u16 w, h; + + def_display->driver->get_resolution(def_display, &w, &h); + + dev_info(fbdev->dev, "using display '%s' mode %dx%d\n", + def_display->name, w, h); + } + return 0; cleanup: diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 4b23af6e5c28..367cea8f43f3 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -339,8 +339,6 @@ static int p9100_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 3d86bac62d3e..4c9299576827 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -403,7 +403,7 @@ try_again: if (rc < 0) return rc; - printk(KERN_INFO "fb%d: Apple Platinum frame buffer device\n", info->node); + fb_info(info, "Apple Platinum frame buffer device\n"); return 0; } @@ -639,7 +639,6 @@ static int platinumfb_probe(struct platform_device* odev) iounmap(pinfo->frame_buffer); iounmap(pinfo->platinum_regs); iounmap(pinfo->cmap_regs); - dev_set_drvdata(&odev->dev, NULL); framebuffer_release(info); } diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 81354eeab021..3b85b647bc10 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1694,8 +1694,8 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (retval < 0) goto err_exit_all; - printk(KERN_INFO "fb%d: %s frame buffer device, memory = %dK.\n", - info->node, info->fix.id, pm2fb_fix.smem_len / 1024); + fb_info(info, "%s frame buffer device, memory = %dK\n", + info->fix.id, pm2fb_fix.smem_len / 1024); /* * Our driver data @@ -1744,7 +1744,6 @@ static void pm2fb_remove(struct pci_dev *pdev) iounmap(par->v_regs); release_mem_region(fix->mmio_start, fix->mmio_len); - pci_set_drvdata(pdev, NULL); fb_dealloc_cmap(&info->cmap); kfree(info->pixmap.addr); framebuffer_release(info); diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 7718faa4a73b..4bf3273d0433 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c @@ -1445,8 +1445,7 @@ static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) retval = -EINVAL; goto err_exit_all; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); pci_set_drvdata(dev, info); return 0; @@ -1489,7 +1488,6 @@ static void pm3fb_remove(struct pci_dev *dev) iounmap(par->v_regs); release_mem_region(fix->mmio_start, fix->mmio_len); - pci_set_drvdata(dev, NULL); kfree(info->pixmap.addr); framebuffer_release(info); } diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index d1e46cedb1f7..914a52ba8477 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -212,8 +212,8 @@ static int pmagbafb_probe(struct device *dev) get_device(dev); - pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev_name(dev)); + fb_info(info, "%s frame buffer device at %s\n", + info->fix.id, dev_name(dev)); return 0; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 0e1317400328..0822b6f8dddc 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -328,11 +328,10 @@ static int pmagbbfb_probe(struct device *dev) snprintf(freq1, sizeof(freq1), "%u.%03uMHz", par->osc1 / 1000, par->osc1 % 1000); - pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev_name(dev)); - pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n", - info->node, freq0, par->osc1 ? freq1 : "disabled", - par->osc1 != 0); + fb_info(info, "%s frame buffer device at %s\n", + info->fix.id, dev_name(dev)); + fb_info(info, "Osc0: %s, Osc1: %s, Osc%u selected\n", + freq0, par->osc1 ? freq1 : "disabled", par->osc1 != 0); return 0; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index df07860563e6..167cffff3d4e 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -817,24 +817,25 @@ static int pvr2fb_common_init(void) rev = fb_readl(par->mmio_base + 0x04); - printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n", - fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, - modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10)); - printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", - fb_info->node, fb_info->var.xres, fb_info->var.yres, - fb_info->var.bits_per_pixel, - get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), - (char *)pvr2_get_param(cables, NULL, cable_type, 3), - (char *)pvr2_get_param(outputs, NULL, video_output, 3)); + fb_info(fb_info, "%s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n", + fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, + modememused >> 10, + (unsigned long)(fb_info->fix.smem_len >> 10)); + fb_info(fb_info, "Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", + fb_info->var.xres, fb_info->var.yres, + fb_info->var.bits_per_pixel, + get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), + (char *)pvr2_get_param(cables, NULL, cable_type, 3), + (char *)pvr2_get_param(outputs, NULL, video_output, 3)); #ifdef CONFIG_SH_STORE_QUEUES - printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node); + fb_notice(fb_info, "registering with SQ API\n"); pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len, fb_info->fix.id, PAGE_SHARED); - printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n", - fb_info->node, pvr2fb_map); + fb_notice(fb_info, "Mapped video memory to SQ addr 0x%lx\n", + pvr2fb_map); #endif return 0; diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c index aa9bd1f76d60..c95b9e46d48f 100644 --- a/drivers/video/pxa168fb.c +++ b/drivers/video/pxa168fb.c @@ -364,7 +364,7 @@ static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset) static void set_dumb_panel_control(struct fb_info *info) { struct pxa168fb_info *fbi = info->par; - struct pxa168fb_mach_info *mi = fbi->dev->platform_data; + struct pxa168fb_mach_info *mi = dev_get_platdata(fbi->dev); u32 x; /* @@ -407,7 +407,7 @@ static int pxa168fb_set_par(struct fb_info *info) u32 x; struct pxa168fb_mach_info *mi; - mi = fbi->dev->platform_data; + mi = dev_get_platdata(fbi->dev); /* * Set additional mode info. @@ -609,7 +609,7 @@ static int pxa168fb_probe(struct platform_device *pdev) struct clk *clk; int irq, ret; - mi = pdev->dev.platform_data; + mi = dev_get_platdata(&pdev->dev); if (mi == NULL) { dev_err(&pdev->dev, "no platform data defined\n"); return -EINVAL; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index eca2de45f7a6..1ecd9cec2921 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -457,7 +457,7 @@ static int pxafb_adjust_timing(struct pxafb_info *fbi, static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct pxafb_info *fbi = (struct pxafb_info *)info; - struct pxafb_mach_info *inf = fbi->dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); int err; if (inf->fixed_modes) { @@ -1230,7 +1230,7 @@ static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk) static void setup_smart_timing(struct pxafb_info *fbi, struct fb_var_screeninfo *var) { - struct pxafb_mach_info *inf = fbi->dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); struct pxafb_mode_info *mode = &inf->modes[0]; unsigned long lclk = clk_get_rate(fbi->clk); unsigned t1, t2, t3, t4; @@ -1258,14 +1258,14 @@ static void setup_smart_timing(struct pxafb_info *fbi, static int pxafb_smart_thread(void *arg) { struct pxafb_info *fbi = arg; - struct pxafb_mach_info *inf = fbi->dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev); if (!inf->smart_update) { pr_err("%s: not properly initialized, thread terminated\n", __func__); return -EINVAL; } - inf = fbi->dev->platform_data; + inf = dev_get_platdata(fbi->dev); pr_debug("%s(): task starting\n", __func__); @@ -1793,7 +1793,7 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev) { struct pxafb_info *fbi; void *addr; - struct pxafb_mach_info *inf = dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(dev); /* Alloc the pxafb_info and pseudo_palette in one step */ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); @@ -1855,7 +1855,7 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev) #ifdef CONFIG_FB_PXA_PARAMETERS static int parse_opt_mode(struct device *dev, const char *this_opt) { - struct pxafb_mach_info *inf = dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(dev); const char *name = this_opt+5; unsigned int namelen = strlen(name); @@ -1914,7 +1914,7 @@ done: static int parse_opt(struct device *dev, char *this_opt) { - struct pxafb_mach_info *inf = dev->platform_data; + struct pxafb_mach_info *inf = dev_get_platdata(dev); struct pxafb_mode_info *mode = &inf->modes[0]; char s[64]; @@ -2102,7 +2102,7 @@ static int pxafb_probe(struct platform_device *dev) dev_dbg(&dev->dev, "pxafb_probe\n"); - inf = dev->dev.platform_data; + inf = dev_get_platdata(&dev->dev); ret = -ENOMEM; fbi = NULL; if (!inf) diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index d44c7351de0f..7487f76f6275 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -119,8 +119,7 @@ static int q40fb_probe(struct platform_device *dev) return -EINVAL; } - printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !\n", - info->node); + fb_info(info, "Q40 frame buffer alive and kicking !\n"); return 0; } diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 9536715b5a1b..8a8d7f060784 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -1185,11 +1185,6 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (rivafb_do_maximize(info, var, nom, den) < 0) return -EINVAL; - if (var->xoffset < 0) - var->xoffset = 0; - if (var->yoffset < 0) - var->yoffset = 0; - /* truncate xoffset and yoffset to maximum if too high */ if (var->xoffset > var->xres_virtual - var->xres) var->xoffset = var->xres_virtual - var->xres - 1; @@ -2133,7 +2128,6 @@ static void rivafb_remove(struct pci_dev *pd) pci_release_regions(pd); kfree(info->pixmap.addr); framebuffer_release(info); - pci_set_drvdata(pd, NULL); NVTRACE_LEAVE(); } diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 05c2dc3d4bc0..83433cb0dfba 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -777,8 +777,8 @@ static int s1d13xxxfb_probe(struct platform_device *pdev) printk(KERN_INFO "Epson S1D13XXX FB Driver\n"); /* enable platform-dependent hardware glue, if any */ - if (pdev->dev.platform_data) - pdata = pdev->dev.platform_data; + if (dev_get_platdata(&pdev->dev)) + pdata = dev_get_platdata(&pdev->dev); if (pdata && pdata->platform_init_video) pdata->platform_init_video(); @@ -901,8 +901,7 @@ static int s1d13xxxfb_probe(struct platform_device *pdev) goto bail; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; @@ -923,8 +922,8 @@ static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state) lcd_enable(s1dfb, 0); crt_enable(s1dfb, 0); - if (dev->dev.platform_data) - pdata = dev->dev.platform_data; + if (dev_get_platdata(&dev->dev)) + pdata = dev_get_platdata(&dev->dev); #if 0 if (!s1dfb->disp_save) @@ -973,8 +972,8 @@ static int s1d13xxxfb_resume(struct platform_device *dev) while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01)) udelay(10); - if (dev->dev.platform_data) - pdata = dev->dev.platform_data; + if (dev_get_platdata(&dev->dev)) + pdata = dev_get_platdata(&dev->dev); if (s1dfb->regs_save) { /* will write RO regs, *should* get away with it :) */ diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 2e7991c7ca08..62acae2694a9 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1378,7 +1378,7 @@ static int s3c_fb_probe(struct platform_device *pdev) return -EINVAL; } - pd = pdev->dev.platform_data; + pd = dev_get_platdata(&pdev->dev); if (!pd) { dev_err(dev, "no platform data specified\n"); return -EINVAL; diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 21a32adbb8ea..81af5a63e9e1 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -123,7 +123,7 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct s3c2410fb_info *fbi = info->par; - struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; + struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev); struct s3c2410fb_display *display = NULL; struct s3c2410fb_display *default_display = mach_info->displays + mach_info->default_display; @@ -686,7 +686,7 @@ static inline void modify_gpio(void __iomem *reg, static int s3c2410fb_init_registers(struct fb_info *info) { struct s3c2410fb_info *fbi = info->par; - struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; + struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev); unsigned long flags; void __iomem *regs = fbi->io; void __iomem *tpal; @@ -833,7 +833,7 @@ static int s3c24xxfb_probe(struct platform_device *pdev, int size; u32 lcdcon1; - mach_info = pdev->dev.platform_data; + mach_info = dev_get_platdata(&pdev->dev); if (mach_info == NULL) { dev_err(&pdev->dev, "no platform data for lcd, cannot attach\n"); diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index d838ba829459..968b2997175a 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -306,8 +306,8 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) if ((map->width != 8) || (map->height != 16) || (map->depth != 1) || (map->length != 256)) { - printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n", - info->node, map->width, map->height, map->depth, map->length); + fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n", + map->width, map->height, map->depth, map->length); return; } @@ -476,7 +476,7 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + fb_err(info, "cannot set requested pixclock, keeping old value\n"); return; } @@ -569,7 +569,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) rv = -EINVAL; if (rv < 0) { - printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node); + fb_err(info, "unsupported mode requested\n"); return rv; } @@ -587,22 +587,21 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) /* Check whether have enough memory */ mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual; if (mem > info->screen_size) { - printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", - info->node, mem >> 10, (unsigned int) (info->screen_size >> 10)); + fb_err(info, "not enough framebuffer memory (%d kB requested , %u kB available)\n", + mem >> 10, (unsigned int) (info->screen_size >> 10)); return -EINVAL; } rv = svga_check_timings (&s3_timing_regs, var, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: invalid timings requested\n", info->node); + fb_err(info, "invalid timings requested\n"); return rv; } rv = svga_compute_pll(&s3_pll, PICOS2KHZ(var->pixclock), &m, &n, &r, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: invalid pixclock value requested\n", - info->node); + fb_err(info, "invalid pixclock value requested\n"); return rv; } @@ -686,7 +685,7 @@ static int s3fb_set_par(struct fb_info *info) /* Set the offset register */ - pr_debug("fb%d: offset register : %d\n", info->node, offset_value); + fb_dbg(info, "offset register : %d\n", offset_value); svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); if (par->chip != CHIP_357_VIRGE_GX2 && @@ -769,7 +768,7 @@ static int s3fb_set_par(struct fb_info *info) /* Set mode-specific register values */ switch (mode) { case 0: - pr_debug("fb%d: text mode\n", info->node); + fb_dbg(info, "text mode\n"); svga_set_textmode_vga_regs(par->state.vgabase); /* Set additional registers like in 8-bit mode */ @@ -780,12 +779,12 @@ static int s3fb_set_par(struct fb_info *info) svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); if (fasttext) { - pr_debug("fb%d: high speed text mode set\n", info->node); + fb_dbg(info, "high speed text mode set\n"); svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40); } break; case 1: - pr_debug("fb%d: 4 bit pseudocolor\n", info->node); + fb_dbg(info, "4 bit pseudocolor\n"); vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); /* Set additional registers like in 8-bit mode */ @@ -796,7 +795,7 @@ static int s3fb_set_par(struct fb_info *info) svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); break; case 2: - pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); + fb_dbg(info, "4 bit pseudocolor, planar\n"); /* Set additional registers like in 8-bit mode */ svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); @@ -806,7 +805,7 @@ static int s3fb_set_par(struct fb_info *info) svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); break; case 3: - pr_debug("fb%d: 8 bit pseudocolor\n", info->node); + fb_dbg(info, "8 bit pseudocolor\n"); svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); if (info->var.pixclock > 20000 || par->chip == CHIP_357_VIRGE_GX2 || @@ -822,7 +821,7 @@ static int s3fb_set_par(struct fb_info *info) } break; case 4: - pr_debug("fb%d: 5/5/5 truecolor\n", info->node); + fb_dbg(info, "5/5/5 truecolor\n"); if (par->chip == CHIP_988_VIRGE_VX) { if (info->var.pixclock > 20000) svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); @@ -850,7 +849,7 @@ static int s3fb_set_par(struct fb_info *info) } break; case 5: - pr_debug("fb%d: 5/6/5 truecolor\n", info->node); + fb_dbg(info, "5/6/5 truecolor\n"); if (par->chip == CHIP_988_VIRGE_VX) { if (info->var.pixclock > 20000) svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); @@ -879,16 +878,16 @@ static int s3fb_set_par(struct fb_info *info) break; case 6: /* VIRGE VX case */ - pr_debug("fb%d: 8/8/8 truecolor\n", info->node); + fb_dbg(info, "8/8/8 truecolor\n"); svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); break; case 7: - pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); + fb_dbg(info, "8/8/8/8 truecolor\n"); svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30); svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); break; default: - printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); + fb_err(info, "unsupported mode - bug\n"); return -EINVAL; } @@ -991,27 +990,27 @@ static int s3fb_blank(int blank_mode, struct fb_info *info) switch (blank_mode) { case FB_BLANK_UNBLANK: - pr_debug("fb%d: unblank\n", info->node); + fb_dbg(info, "unblank\n"); svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); break; case FB_BLANK_NORMAL: - pr_debug("fb%d: blank\n", info->node); + fb_dbg(info, "blank\n"); svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_HSYNC_SUSPEND: - pr_debug("fb%d: hsync\n", info->node); + fb_dbg(info, "hsync\n"); svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_VSYNC_SUSPEND: - pr_debug("fb%d: vsync\n", info->node); + fb_dbg(info, "vsync\n"); svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_POWERDOWN: - pr_debug("fb%d: sync down\n", info->node); + fb_dbg(info, "sync down\n"); svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; @@ -1352,13 +1351,16 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) goto err_reg_fb; } - printk(KERN_INFO "fb%d: %s on %s, %d MB RAM, %d MHz MCLK\n", info->node, info->fix.id, - pci_name(dev), info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000); + fb_info(info, "%s on %s, %d MB RAM, %d MHz MCLK\n", + info->fix.id, pci_name(dev), + info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000); if (par->chip == CHIP_UNKNOWN) - printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", - info->node, vga_rcrt(par->state.vgabase, 0x2d), vga_rcrt(par->state.vgabase, 0x2e), - vga_rcrt(par->state.vgabase, 0x2f), vga_rcrt(par->state.vgabase, 0x30)); + fb_info(info, "unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", + vga_rcrt(par->state.vgabase, 0x2d), + vga_rcrt(par->state.vgabase, 0x2e), + vga_rcrt(par->state.vgabase, 0x2f), + vga_rcrt(par->state.vgabase, 0x30)); /* Record a reference to the driver data */ pci_set_drvdata(dev, info); @@ -1424,7 +1426,6 @@ static void s3_pci_remove(struct pci_dev *dev) pci_release_regions(dev); /* pci_disable_device(dev); */ - pci_set_drvdata(dev, NULL); framebuffer_release(info); } } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index de76da0c6429..580c444ec301 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1116,7 +1116,7 @@ static struct fb_monspecs monspecs = { static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev) { - struct sa1100fb_mach_info *inf = dev->platform_data; + struct sa1100fb_mach_info *inf = dev_get_platdata(dev); struct sa1100fb_info *fbi; unsigned i; @@ -1201,7 +1201,7 @@ static int sa1100fb_probe(struct platform_device *pdev) struct resource *res; int ret, irq; - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform LCD data\n"); return -EINVAL; } diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 741b2395d01e..4dbf45f3b21a 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -2362,12 +2362,6 @@ static void savagefb_remove(struct pci_dev *dev) kfree(info->pixmap.addr); pci_release_regions(dev); framebuffer_release(info); - - /* - * Ensure that the driver data is no longer - * valid. - */ - pci_set_drvdata(dev, NULL); } } diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 296afae442f4..a350209ffbd3 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -186,7 +186,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, } default: return -EINVAL; - }; + } } EXPORT_SYMBOL(sbusfb_ioctl_helper); diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index a9ac3ce2d0e9..bc74d0408998 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -803,8 +803,8 @@ static int sgivwfb_probe(struct platform_device *dev) platform_set_drvdata(dev, info); - printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n", - info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys); + fb_info(info, "SGI DBE frame buffer device, using %ldK of video memory at %#lx\n", + sgivwfb_mem_size >> 10, sgivwfb_mem_phys); return 0; fail_register_framebuffer: diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index bfe4728480fd..9a33ee0413fb 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c @@ -498,7 +498,7 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi) static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) { u8 data; - struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; + struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev); /* * [7:4] L/R data swap control @@ -815,7 +815,7 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, unsigned long *parent_rate) { unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error; - struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; + struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev); *hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target); if ((long)*hdmi_rate < 0) @@ -1271,7 +1271,7 @@ static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi) static int __init sh_hdmi_probe(struct platform_device *pdev) { - struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; + struct sh_mobile_hdmi_info *pdata = dev_get_platdata(&pdev->dev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *htop1_res; int irq = platform_get_irq(pdev, 0), ret; @@ -1290,7 +1290,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) } } - hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); + hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { dev_err(&pdev->dev, "Cannot allocate device data\n"); return -ENOMEM; @@ -1304,7 +1304,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) if (IS_ERR(hdmi->hdmi_clk)) { ret = PTR_ERR(hdmi->hdmi_clk); dev_err(&pdev->dev, "Unable to get clock: %d\n", ret); - goto egetclk; + return ret; } /* select register access functions */ @@ -1326,7 +1326,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) goto erate; } - ret = clk_enable(hdmi->hdmi_clk); + ret = clk_prepare_enable(hdmi->hdmi_clk); if (ret < 0) { dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret); goto erate; @@ -1404,11 +1404,9 @@ emap_htop1: emap: release_mem_region(res->start, resource_size(res)); ereqreg: - clk_disable(hdmi->hdmi_clk); + clk_disable_unprepare(hdmi->hdmi_clk); erate: clk_put(hdmi->hdmi_clk); -egetclk: - kfree(hdmi); return ret; } @@ -1427,13 +1425,12 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) cancel_delayed_work_sync(&hdmi->edid_work); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - clk_disable(hdmi->hdmi_clk); + clk_disable_unprepare(hdmi->hdmi_clk); clk_put(hdmi->hdmi_clk); if (hdmi->htop1) iounmap(hdmi->htop1); iounmap(hdmi->base); release_mem_region(res->start, resource_size(res)); - kfree(hdmi); return 0; } diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 0264704a52be..2bcc84ac18c7 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -344,7 +344,7 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) { if (atomic_inc_and_test(&priv->hw_usecnt)) { if (priv->dot_clk) - clk_enable(priv->dot_clk); + clk_prepare_enable(priv->dot_clk); pm_runtime_get_sync(priv->dev); if (priv->meram_dev && priv->meram_dev->pdev) pm_runtime_get_sync(&priv->meram_dev->pdev->dev); @@ -358,7 +358,7 @@ static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) pm_runtime_put_sync(&priv->meram_dev->pdev->dev); pm_runtime_put(priv->dev); if (priv->dot_clk) - clk_disable(priv->dot_clk); + clk_disable_unprepare(priv->dot_clk); } } @@ -574,8 +574,9 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, switch (event) { case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: /* HDMI plug in */ + console_lock(); if (lock_fb_info(info)) { - console_lock(); + ch->display.width = monspec->max_x * 10; ch->display.height = monspec->max_y * 10; @@ -594,19 +595,20 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, fb_set_suspend(info, 0); } - console_unlock(); + unlock_fb_info(info); } + console_unlock(); break; case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: /* HDMI disconnect */ + console_lock(); if (lock_fb_info(info)) { - console_lock(); fb_set_suspend(info, 1); - console_unlock(); unlock_fb_info(info); } + console_unlock(); break; case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: @@ -1225,7 +1227,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) /* Free the MERAM cache. */ if (ch->cache) { sh_mobile_meram_cache_free(priv->meram_dev, ch->cache); - ch->cache = 0; + ch->cache = NULL; } } diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c index e0f098562a74..a297de5cc859 100644 --- a/drivers/video/sh_mobile_meram.c +++ b/drivers/video/sh_mobile_meram.c @@ -569,6 +569,7 @@ EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update); * Power management */ +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static int sh_mobile_meram_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -611,6 +612,7 @@ static int sh_mobile_meram_resume(struct device *dev) meram_write_reg(priv->base, common_regs[i], priv->regs[i]); return 0; } +#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */ static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops, sh_mobile_meram_suspend, diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c index 8d7810613058..210f3a02121a 100644 --- a/drivers/video/simplefb.c +++ b/drivers/video/simplefb.c @@ -66,8 +66,15 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return 0; } +static void simplefb_destroy(struct fb_info *info) +{ + if (info->screen_base) + iounmap(info->screen_base); +} + static struct fb_ops simplefb_ops = { .owner = THIS_MODULE, + .fb_destroy = simplefb_destroy, .fb_setcolreg = simplefb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -132,7 +139,7 @@ static int simplefb_parse_dt(struct platform_device *pdev, static int simplefb_parse_pd(struct platform_device *pdev, struct simplefb_params *params) { - struct simplefb_platform_data *pd = pdev->dev.platform_data; + struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev); int i; params->width = pd->width; @@ -167,7 +174,7 @@ static int simplefb_probe(struct platform_device *pdev) return -ENODEV; ret = -ENODEV; - if (pdev->dev.platform_data) + if (dev_get_platdata(&pdev->dev)) ret = simplefb_parse_pd(pdev, ¶ms); else if (pdev->dev.of_node) ret = simplefb_parse_dt(pdev, ¶ms); @@ -212,17 +219,26 @@ static int simplefb_probe(struct platform_device *pdev) info->fbops = &simplefb_ops; info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE; - info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start, - info->fix.smem_len); + info->screen_base = ioremap_wc(info->fix.smem_start, + info->fix.smem_len); if (!info->screen_base) { framebuffer_release(info); return -ENODEV; } info->pseudo_palette = (void *)(info + 1); + dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", + info->fix.smem_start, info->fix.smem_len, + info->screen_base); + dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n", + params.format->name, + info->var.xres, info->var.yres, + info->var.bits_per_pixel, info->fix.line_length); + ret = register_framebuffer(info); if (ret < 0) { dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret); + iounmap(info->screen_base); framebuffer_release(info); return ret; } diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c index f082ae55c0c9..4f26bc28e60b 100644 --- a/drivers/video/sis/init.c +++ b/drivers/video/sis/init.c @@ -3320,9 +3320,8 @@ SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo) } #ifndef GETBITSTR -#define BITMASK(h,l) (((unsigned)(1U << ((h)-(l)+1))-1)<<(l)) -#define GENMASK(mask) BITMASK(1?mask,0?mask) -#define GETBITS(var,mask) (((var) & GENMASK(mask)) >> (0?mask)) +#define GENBITSMASK(mask) GENMASK(1?mask,0?mask) +#define GETBITS(var,mask) (((var) & GENBITSMASK(mask)) >> (0?mask)) #define GETBITSTR(val,from,to) ((GETBITS(val,from)) << (0?to)) #endif diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 977e27927a21..22ad028bf123 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -5994,7 +5994,6 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if(!ivideo->sisvga_enabled) { if(pci_enable_device(pdev)) { if(ivideo->nbridge) pci_dev_put(ivideo->nbridge); - pci_set_drvdata(pdev, NULL); framebuffer_release(sis_fb_info); return -EIO; } @@ -6211,7 +6210,6 @@ error_3: vfree(ivideo->bios_abase); pci_dev_put(ivideo->lpcdev); if(ivideo->nbridge) pci_dev_put(ivideo->nbridge); - pci_set_drvdata(pdev, NULL); if(!ivideo->sisvga_enabled) pci_disable_device(pdev); framebuffer_release(sis_fb_info); @@ -6480,8 +6478,8 @@ error_3: vfree(ivideo->bios_abase); "disabled"); - printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n", - sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); + fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n", + ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL); printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n"); @@ -6523,8 +6521,6 @@ static void sisfb_remove(struct pci_dev *pdev) mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size); #endif - pci_set_drvdata(pdev, NULL); - /* If device was disabled when starting, disable * it when quitting. */ diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 2d4694c6b9e0..fefde7c6add7 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -824,8 +824,7 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent) fb_dealloc_cmap(&info->cmap); return -EINVAL; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ return 0; } diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c index e188ada2ffd1..d513ed6a49f2 100644 --- a/drivers/video/smscufx.c +++ b/drivers/video/smscufx.c @@ -1147,7 +1147,7 @@ static void ufx_free_framebuffer_work(struct work_struct *work) fb_destroy_modelist(&info->modelist); - dev->info = 0; + dev->info = NULL; /* Assume info structure is freed after this point */ framebuffer_release(info); diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 44967c8fef2b..f4daa59f0a80 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c @@ -569,7 +569,7 @@ static struct i2c_driver ssd1307fb_driver = { .id_table = ssd1307fb_i2c_id, .driver = { .name = "ssd1307fb", - .of_match_table = of_match_ptr(ssd1307fb_of_match), + .of_match_table = ssd1307fb_of_match, .owner = THIS_MODULE, }, }; diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 9c00026e3ae2..f0cb279ef333 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -706,10 +706,10 @@ static void sstfb_setvgapass( struct fb_info *info, int enable ) fbiinit0 = sst_read (FBIINIT0); if (par->vgapass) { sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH); - printk(KERN_INFO "fb%d: Enabling VGA pass-through\n", info->node ); + fb_info(info, "Enabling VGA pass-through\n"); } else { sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH); - printk(KERN_INFO "fb%d: Disabling VGA pass-through\n", info->node ); + fb_info(info, "Disabling VGA pass-through\n"); } pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); } @@ -1437,8 +1437,8 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_WARNING "sstfb: can't create sysfs entry.\n"); - printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n", - info->node, fix->id, info->screen_base); + fb_info(info, "%s frame buffer device at 0x%p\n", + fix->id, info->screen_base); return 0; diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index addf7b615ef8..af1619536ac8 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h @@ -18,6 +18,9 @@ #define STI_FONT_HPROMAN8 1 #define STI_FONT_KANA8 2 +#define ALT_CODE_TYPE_UNKNOWN 0x00 /* alt code type values */ +#define ALT_CODE_TYPE_PA_RISC_64 0x01 + /* The latency of the STI functions cannot really be reduced by setting * this to 0; STI doesn't seem to be designed to allow calling a different * function (or the same function with different arguments) after a @@ -40,14 +43,6 @@ #define STI_PTR(p) ( virt_to_phys(p) ) #define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) -#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ - ({ \ - pdc_sti_call( func, STI_PTR(flags), \ - STI_PTR(inptr), \ - STI_PTR(outptr), \ - STI_PTR(glob_cfg)); \ - }) - #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) @@ -56,6 +51,12 @@ #define sti_font_x(sti) (PTR_STI(sti->font)->width) #define sti_font_y(sti) (PTR_STI(sti->font)->height) +#ifdef CONFIG_64BIT +#define STI_LOWMEM (GFP_KERNEL | GFP_DMA) +#else +#define STI_LOWMEM (GFP_KERNEL) +#endif + /* STI function configuration structs */ @@ -306,6 +307,34 @@ struct sti_blkmv_outptr { }; +/* sti_all_data is an internal struct which needs to be allocated in + * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */ + +struct sti_all_data { + struct sti_glob_cfg glob_cfg; + struct sti_glob_cfg_ext glob_cfg_ext; + + struct sti_conf_inptr inq_inptr; + struct sti_conf_outptr inq_outptr; /* configuration */ + struct sti_conf_outptr_ext inq_outptr_ext; + + struct sti_init_inptr_ext init_inptr_ext; + struct sti_init_inptr init_inptr; + struct sti_init_outptr init_outptr; + + struct sti_blkmv_inptr blkmv_inptr; + struct sti_blkmv_outptr blkmv_outptr; + + struct sti_font_inptr font_inptr; + struct sti_font_outptr font_outptr; + + /* leave as last entries */ + unsigned long save_addr[1024 / sizeof(unsigned long)]; + /* min 256 bytes which is STI default, max sti->sti_mem_request */ + unsigned long sti_mem_addr[256 / sizeof(unsigned long)]; + /* do not add something below here ! */ +}; + /* internal generic STI struct */ struct sti_struct { @@ -330,11 +359,9 @@ struct sti_struct { region_t regions[STI_REGION_MAX]; unsigned long regions_phys[STI_REGION_MAX]; - struct sti_glob_cfg *glob_cfg; - struct sti_cooked_font *font; /* ptr to selected font (cooked) */ + struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */ - struct sti_conf_outptr outptr; /* configuration */ - struct sti_conf_outptr_ext outptr_ext; + struct sti_cooked_font *font; /* ptr to selected font (cooked) */ struct pci_dev *pd; @@ -343,6 +370,9 @@ struct sti_struct { /* pointer to the fb_info where this STI device is used */ struct fb_info *info; + + /* pointer to all internal data */ + struct sti_all_data *sti_data; }; @@ -350,6 +380,14 @@ struct sti_struct { struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ + +/* sticore main function to call STI firmware */ + +int sti_call(const struct sti_struct *sti, unsigned long func, + const void *flags, void *inptr, void *outptr, + struct sti_glob_cfg *glob_cfg); + + /* functions to call the STI ROM directly */ void sti_putc(struct sti_struct *sti, int c, int y, int x); diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 876648e15e9d..cfe8a2f905c5 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1101,6 +1101,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) var = &info->var; fb->sti = sti; + dev_name = sti->sti_data->inq_outptr.dev_name; /* store upper 32bits of the graphics id */ fb->id = fb->sti->graphics_id[0]; @@ -1114,11 +1115,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) Since this driver only supports standard mode, we check if the device name contains the string "DX" and tell the user how to reconfigure the card. */ - if (strstr(sti->outptr.dev_name, "DX")) { + if (strstr(dev_name, "DX")) { printk(KERN_WARNING "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", - sti->outptr.dev_name); + dev_name); goto out_err0; } /* fall though */ @@ -1130,7 +1131,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) break; default: printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", - sti->outptr.dev_name, fb->id); + dev_name, fb->id); goto out_err0; } @@ -1154,7 +1155,6 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) fb->id = S9000_ID_A1659A; break; case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ - dev_name = fb->sti->outptr.dev_name; if (strstr(dev_name, "GRAYSCALE") || strstr(dev_name, "Grayscale") || strstr(dev_name, "grayscale")) @@ -1283,14 +1283,12 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) sti->info = info; /* save for unregister_framebuffer() */ - printk(KERN_INFO - "fb%d: %s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n", - fb->info.node, + fb_info(&fb->info, "%s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n", fix->id, var->xres, var->yres, var->bits_per_pixel, - sti->outptr.dev_name, + dev_name, fb->id, fix->mmio_start); diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index cc6f48bba36b..58241b47a96d 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c @@ -186,8 +186,6 @@ static int gfb_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c index 33df9ec91795..9e01322fabe3 100644 --- a/drivers/video/svgalib.c +++ b/drivers/video/svgalib.c @@ -198,8 +198,8 @@ void svga_settile(struct fb_info *info, struct fb_tilemap *map) if ((map->width != 8) || (map->height != 16) || (map->depth != 1) || (map->length != 256)) { - printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n", - info->node, map->width, map->height, map->depth, map->length); + fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n", + map->width, map->height, map->depth, map->length); return; } diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c index 186c6f607be2..a4d05b1b17d7 100644 --- a/drivers/video/sysimgblt.c +++ b/drivers/video/sysimgblt.c @@ -152,7 +152,7 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p, } shift += bpp; shift &= (32 - 1); - if (!l) { l = 8; s++; }; + if (!l) { l = 8; s++; } } /* write trailing bits */ diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index c000852500aa..7fb2d696fac7 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -232,7 +232,7 @@ tcx_blank(int blank, struct fb_info *info) case FB_BLANK_POWERDOWN: /* Poweroff */ break; - }; + } sbus_writel(val, &thc->thc_misc); @@ -434,7 +434,7 @@ static int tcx_probe(struct platform_device *op) default: j = i; break; - }; + } par->mmap_map[i].poff = op->resource[j].start; } @@ -498,8 +498,6 @@ static int tcx_remove(struct platform_device *op) framebuffer_release(info); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 64bc28ba4037..f761fe375f5b 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -1646,7 +1646,6 @@ static void tdfxfb_remove(struct pci_dev *pdev) pci_resource_len(pdev, 1)); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - pci_set_drvdata(pdev, NULL); fb_dealloc_cmap(&info->cmap); framebuffer_release(info); } diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index c9c8e5a1fdee..07c7df9ee77b 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -32,12 +32,6 @@ #include <video/tgafb.h> -#ifdef CONFIG_PCI -#define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type) -#else -#define TGA_BUS_PCI(dev) 0 -#endif - #ifdef CONFIG_TC #define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type) #else @@ -236,7 +230,7 @@ tgafb_set_par(struct fb_info *info) }; struct tga_par *par = (struct tga_par *) info->par; - int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_pci = dev_is_pci(par->dev); int tga_bus_tc = TGA_BUS_TC(par->dev); u32 htimings, vtimings, pll_freq; u8 tga_type; @@ -519,7 +513,7 @@ tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { struct tga_par *par = (struct tga_par *) info->par; - int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_pci = dev_is_pci(par->dev); int tga_bus_tc = TGA_BUS_TC(par->dev); if (regno > 255) @@ -1472,7 +1466,7 @@ static void tgafb_init_fix(struct fb_info *info) { struct tga_par *par = (struct tga_par *)info->par; - int tga_bus_pci = TGA_BUS_PCI(par->dev); + int tga_bus_pci = dev_is_pci(par->dev); int tga_bus_tc = TGA_BUS_TC(par->dev); u8 tga_type = par->tga_type; const char *tga_type_name = NULL; @@ -1496,10 +1490,9 @@ tgafb_init_fix(struct fb_info *info) if (tga_bus_tc) tga_type_name = "Digital ZLX-E3"; break; - default: - tga_type_name = "Unknown"; - break; } + if (!tga_type_name) + tga_type_name = "Unknown"; strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id)); @@ -1560,7 +1553,7 @@ static int tgafb_register(struct device *dev) const struct fb_videomode *modedb_tga = NULL; resource_size_t bar0_start = 0, bar0_len = 0; const char *mode_option_tga = NULL; - int tga_bus_pci = TGA_BUS_PCI(dev); + int tga_bus_pci = dev_is_pci(dev); int tga_bus_tc = TGA_BUS_TC(dev); unsigned int modedbsize_tga = 0; void __iomem *mem_base; @@ -1671,8 +1664,8 @@ static int tgafb_register(struct device *dev) if (tga_bus_tc) pr_info("tgafb: SFB+ detected, rev=0x%02x\n", par->tga_chip_rev); - pr_info("fb%d: %s frame buffer device at 0x%lx\n", - info->node, info->fix.id, (long)bar0_start); + fb_info(info, "%s frame buffer device at 0x%lx\n", + info->fix.id, (long)bar0_start); return 0; @@ -1690,7 +1683,7 @@ static int tgafb_register(struct device *dev) static void tgafb_unregister(struct device *dev) { resource_size_t bar0_start = 0, bar0_len = 0; - int tga_bus_pci = TGA_BUS_PCI(dev); + int tga_bus_pci = dev_is_pci(dev); int tga_bus_tc = TGA_BUS_TC(dev); struct fb_info *info = NULL; struct tga_par *par; diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index deb8733f3c70..7fb4e321a431 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -250,7 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) */ static int tmiofb_hw_stop(struct platform_device *dev) { - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = dev_get_platdata(&dev->dev); struct fb_info *info = platform_get_drvdata(dev); struct tmiofb_par *par = info->par; @@ -311,7 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev) */ static void tmiofb_hw_mode(struct platform_device *dev) { - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = dev_get_platdata(&dev->dev); struct fb_info *info = platform_get_drvdata(dev); struct fb_videomode *mode = info->mode; struct tmiofb_par *par = info->par; @@ -557,7 +557,7 @@ static int tmiofb_ioctl(struct fb_info *fbi, static struct fb_videomode * tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var) { - struct tmio_fb_data *data = info->device->platform_data; + struct tmio_fb_data *data = dev_get_platdata(info->device); struct fb_videomode *best = NULL; int i; @@ -577,7 +577,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct fb_videomode *mode; - struct tmio_fb_data *data = info->device->platform_data; + struct tmio_fb_data *data = dev_get_platdata(info->device); mode = tmiofb_find_mode(info, var); if (!mode || var->bits_per_pixel > 16) @@ -678,7 +678,7 @@ static struct fb_ops tmiofb_ops = { static int tmiofb_probe(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); - struct tmio_fb_data *data = dev->dev.platform_data; + struct tmio_fb_data *data = dev_get_platdata(&dev->dev); struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); @@ -781,8 +781,7 @@ static int tmiofb_probe(struct platform_device *dev) if (retval < 0) goto err_register_framebuffer; - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index ab57d387d6b5..7ed9a227f5ea 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1553,7 +1553,6 @@ static void trident_pci_remove(struct pci_dev *dev) iounmap(info->screen_base); release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); - pci_set_drvdata(dev, NULL); kfree(info->pixmap.addr); fb_dealloc_cmap(&info->cmap); framebuffer_release(info); diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index d2e5bc3cf969..025f14e30eed 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -1166,7 +1166,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info) int new_len; unsigned char *old_fb = info->screen_base; unsigned char *new_fb; - unsigned char *new_back = 0; + unsigned char *new_back = NULL; pr_warn("Reallocating framebuffer. Addresses will change!\n"); diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 7aec6f39fdd5..256fba7f4641 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -233,8 +233,7 @@ out: static void uvesafb_free(struct uvesafb_ktask *task) { if (task) { - if (task->done) - kfree(task->done); + kfree(task->done); kfree(task); } } @@ -1332,8 +1331,8 @@ setmode: FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.line_length = mode->bytes_per_scan_line; -out: if (crtc != NULL) - kfree(crtc); +out: + kfree(crtc); uvesafb_free(task); return err; @@ -1771,13 +1770,11 @@ static int uvesafb_probe(struct platform_device *dev) "using %dk, total %dk\n", info->fix.smem_start, info->screen_base, info->fix.smem_len/1024, par->vbe_ib.total_memory * 64); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp); if (err != 0) - printk(KERN_WARNING "fb%d: failed to register attributes\n", - info->node); + fb_warn(info, "failed to register attributes\n"); return 0; @@ -1793,8 +1790,7 @@ out_mode: fb_destroy_modedb(info->monspecs.modedb); fb_dealloc_cmap(&info->cmap); out: - if (par->vbe_modes) - kfree(par->vbe_modes); + kfree(par->vbe_modes); framebuffer_release(info); return err; @@ -1817,12 +1813,9 @@ static int uvesafb_remove(struct platform_device *dev) fb_dealloc_cmap(&info->cmap); if (par) { - if (par->vbe_modes) - kfree(par->vbe_modes); - if (par->vbe_state_orig) - kfree(par->vbe_state_orig); - if (par->vbe_state_saved) - kfree(par->vbe_state_saved); + kfree(par->vbe_modes); + kfree(par->vbe_state_orig); + kfree(par->vbe_state_saved); } framebuffer_release(info); diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 3f5a041601da..e287ebc47817 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -392,7 +392,7 @@ int __init valkyriefb_init(void) if ((err = register_framebuffer(&p->info)) != 0) goto out_cmap_free; - printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", p->info.node); + fb_info(&p->info, "valkyrie frame buffer device\n"); return 0; out_cmap_free: diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 09a136633f35..048a66640b03 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c @@ -383,7 +383,6 @@ static void vmlfb_disable_mmio(struct vml_par *par) static void vmlfb_release_devices(struct vml_par *par) { if (atomic_dec_and_test(&par->refcount)) { - pci_set_drvdata(par->vdc, NULL); pci_disable_device(par->gpu); pci_disable_device(par->vdc); } diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index bd83233ec227..1c7da3b098d6 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -489,8 +489,7 @@ static int vesafb_probe(struct platform_device *dev) fb_dealloc_cmap(&info->cmap); goto err; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; err: if (info->screen_base) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index ee5985efa15c..70a897b1e458 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -390,9 +390,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { if (var->vmode & FB_VMODE_YWRAP) { - if (var->yoffset < 0 - || var->yoffset >= info->var.yres_virtual - || var->xoffset) + if (var->yoffset >= info->var.yres_virtual || + var->xoffset) return -EINVAL; } else { if (var->xoffset + info->var.xres > info->var.xres_virtual || @@ -527,9 +526,8 @@ static int vfb_probe(struct platform_device *dev) goto err2; platform_set_drvdata(dev, info); - printk(KERN_INFO - "fb%d: Virtual frame buffer device, using %ldK of video memory\n", - info->node, videomemorysize >> 10); + fb_info(info, "Virtual frame buffer device, using %ldK of video memory\n", + videomemorysize >> 10); return 0; err2: fb_dealloc_cmap(&info->cmap); diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 2827333703d9..283d335a759f 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1377,8 +1377,7 @@ static int vga16fb_probe(struct platform_device *dev) goto err_check_var; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); platform_set_drvdata(dev, info); return 0; diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index 897484903c30..a8f2b280f796 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c @@ -293,8 +293,7 @@ static int vt8500lcd_probe(struct platform_device *pdev) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) { dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); - ret = -ENOMEM; - goto failed; + return -ENOMEM; } strcpy(fbi->fb.fix.id, "VT8500 LCD"); @@ -327,15 +326,13 @@ static int vt8500lcd_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); - ret = -ENODEV; - goto failed_fbi; + return -ENODEV; } res = request_mem_region(res->start, resource_size(res), "vt8500lcd"); if (res == NULL) { dev_err(&pdev->dev, "failed to request I/O memory\n"); - ret = -EBUSY; - goto failed_fbi; + return -EBUSY; } fbi->regbase = ioremap(res->start, resource_size(res)); @@ -346,17 +343,19 @@ static int vt8500lcd_probe(struct platform_device *pdev) } disp_timing = of_get_display_timings(pdev->dev.of_node); - if (!disp_timing) - return -EINVAL; + if (!disp_timing) { + ret = -EINVAL; + goto failed_free_io; + } ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode, OF_USE_NATIVE_MODE); if (ret) - return ret; + goto failed_free_io; ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp); if (ret) - return ret; + goto failed_free_io; /* try allocating the framebuffer */ fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); @@ -364,8 +363,9 @@ static int vt8500lcd_probe(struct platform_device *pdev) GFP_KERNEL); if (!fb_mem_virt) { pr_err("%s: Failed to allocate framebuffer\n", __func__); - return -ENOMEM; - }; + ret = -ENOMEM; + goto failed_free_io; + } fbi->fb.fix.smem_start = fb_mem_phys; fbi->fb.fix.smem_len = fb_mem_len; @@ -447,9 +447,6 @@ failed_free_io: iounmap(fbi->regbase); failed_free_res: release_mem_region(res->start, resource_size(res)); -failed_fbi: - kfree(fbi); -failed: return ret; } diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index e9557fa014ee..8bc6e0958a09 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c @@ -266,7 +266,7 @@ static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock) rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); + fb_err(info, "cannot set requested pixclock, keeping old value\n"); return; } @@ -335,7 +335,7 @@ static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf rv = svga_match_format (vt8623fb_formats, var, NULL); if (rv < 0) { - printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node); + fb_err(info, "unsupported mode requested\n"); return rv; } @@ -354,21 +354,23 @@ static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual; if (mem > info->screen_size) { - printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10)); + fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n", + mem >> 10, (unsigned int) (info->screen_size >> 10)); return -EINVAL; } /* Text mode is limited to 256 kB of memory */ if ((var->bits_per_pixel == 0) && (mem > (256*1024))) { - printk(KERN_ERR "fb%d: text framebuffer size too large (%d kB requested, 256 kB possible)\n", info->node, mem >> 10); + fb_err(info, "text framebuffer size too large (%d kB requested, 256 kB possible)\n", + mem >> 10); return -EINVAL; } rv = svga_check_timings (&vt8623_timing_regs, var, info->node); if (rv < 0) { - printk(KERN_ERR "fb%d: invalid timings requested\n", info->node); + fb_err(info, "invalid timings requested\n"); return rv; } @@ -474,32 +476,32 @@ static int vt8623fb_set_par(struct fb_info *info) mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix)); switch (mode) { case 0: - pr_debug("fb%d: text mode\n", info->node); + fb_dbg(info, "text mode\n"); svga_set_textmode_vga_regs(par->state.vgabase); svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70); break; case 1: - pr_debug("fb%d: 4 bit pseudocolor\n", info->node); + fb_dbg(info, "4 bit pseudocolor\n"); vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE); svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); break; case 2: - pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); + fb_dbg(info, "4 bit pseudocolor, planar\n"); svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE); svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70); break; case 3: - pr_debug("fb%d: 8 bit pseudocolor\n", info->node); + fb_dbg(info, "8 bit pseudocolor\n"); svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE); break; case 4: - pr_debug("fb%d: 5/6/5 truecolor\n", info->node); + fb_dbg(info, "5/6/5 truecolor\n"); svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE); break; case 5: - pr_debug("fb%d: 8/8/8 truecolor\n", info->node); + fb_dbg(info, "8/8/8 truecolor\n"); svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE); break; default: @@ -584,27 +586,27 @@ static int vt8623fb_blank(int blank_mode, struct fb_info *info) switch (blank_mode) { case FB_BLANK_UNBLANK: - pr_debug("fb%d: unblank\n", info->node); + fb_dbg(info, "unblank\n"); svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); break; case FB_BLANK_NORMAL: - pr_debug("fb%d: blank\n", info->node); + fb_dbg(info, "blank\n"); svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_HSYNC_SUSPEND: - pr_debug("fb%d: DPMS standby (hsync off)\n", info->node); + fb_dbg(info, "DPMS standby (hsync off)\n"); svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_VSYNC_SUSPEND: - pr_debug("fb%d: DPMS suspend (vsync off)\n", info->node); + fb_dbg(info, "DPMS suspend (vsync off)\n"); svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; case FB_BLANK_POWERDOWN: - pr_debug("fb%d: DPMS off (no sync)\n", info->node); + fb_dbg(info, "DPMS off (no sync)\n"); svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30); svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); break; @@ -769,12 +771,12 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) rc = register_framebuffer(info); if (rc < 0) { - dev_err(info->device, "cannot register framebugger\n"); + dev_err(info->device, "cannot register framebuffer\n"); goto err_reg_fb; } - printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id, - pci_name(dev), info->fix.smem_len >> 20); + fb_info(info, "%s on %s, %d MB RAM\n", + info->fix.id, pci_name(dev), info->fix.smem_len >> 20); /* Record a reference to the driver data */ pci_set_drvdata(dev, info); @@ -829,7 +831,6 @@ static void vt8623_pci_remove(struct pci_dev *dev) pci_release_regions(dev); /* pci_disable_device(dev); */ - pci_set_drvdata(dev, NULL); framebuffer_release(info); } } diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 7a299e951f75..10951c82f6ed 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -680,7 +680,7 @@ int w100fb_probe(struct platform_device *pdev) par = info->par; platform_set_drvdata(pdev, info); - inf = pdev->dev.platform_data; + inf = dev_get_platdata(&pdev->dev); par->chip_id = chip_id; par->mach = inf; par->fastpll_mode = 0; @@ -761,10 +761,9 @@ int w100fb_probe(struct platform_device *pdev) err |= device_create_file(&pdev->dev, &dev_attr_flip); if (err != 0) - printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n", - info->node, err); + fb_warn(info, "failed to register attributes (%d)\n", err); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); + fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; out: if (info) { diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c index 3072f30cad19..537d199612af 100644 --- a/drivers/video/wm8505fb.c +++ b/drivers/video/wm8505fb.c @@ -372,14 +372,12 @@ static int wm8505fb_probe(struct platform_device *pdev) } ret = device_create_file(&pdev->dev, &dev_attr_contrast); - if (ret < 0) { - printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n", - fbi->fb.node, ret); - } + if (ret < 0) + fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret); - printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n", - fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start, - fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); + fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n", + fbi->fb.fix.id, fbi->fb.fix.smem_start, + fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); return 0; } @@ -411,7 +409,7 @@ static struct platform_driver wm8505fb_driver = { .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, - .of_match_table = of_match_ptr(wmt_dt_ids), + .of_match_table = wmt_dt_ids, }, }; diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c index 4aaeb18223bc..b0a9f34b2e01 100644 --- a/drivers/video/wmt_ge_rops.c +++ b/drivers/video/wmt_ge_rops.c @@ -169,13 +169,13 @@ static struct platform_driver wmt_ge_rops_driver = { .driver = { .owner = THIS_MODULE, .name = "wmt_ge_rops", - .of_match_table = of_match_ptr(wmt_dt_ids), + .of_match_table = wmt_dt_ids, }, }; module_platform_driver(wmt_ge_rops_driver); -MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); +MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); MODULE_DESCRIPTION("Accelerators for raster operations using " "WonderMedia Graphics Engine"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 84c664ea8eb9..6ff1a91e9dfd 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -260,10 +260,9 @@ static int xilinxfb_assign(struct platform_device *pdev, res = platform_get_resource(pdev, IORESOURCE_MEM, 0); drvdata->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(drvdata->regs)) { - rc = PTR_ERR(drvdata->regs); - goto err_region; - } + if (IS_ERR(drvdata->regs)) + return PTR_ERR(drvdata->regs); + drvdata->regs_phys = res->start; } @@ -279,11 +278,7 @@ static int xilinxfb_assign(struct platform_device *pdev, if (!drvdata->fb_virt) { dev_err(dev, "Could not allocate frame buffer memory\n"); - rc = -ENOMEM; - if (drvdata->flags & BUS_ACCESS_FLAG) - goto err_fbmem; - else - goto err_region; + return -ENOMEM; } /* Clear (turn to black) the framebuffer */ @@ -363,14 +358,6 @@ err_cmap: /* Turn off the display */ xilinx_fb_out32(drvdata, REG_CTRL, 0); -err_fbmem: - if (drvdata->flags & BUS_ACCESS_FLAG) - devm_iounmap(dev, drvdata->regs); - -err_region: - kfree(drvdata); - dev_set_drvdata(dev, NULL); - return rc; } @@ -395,17 +382,12 @@ static int xilinxfb_release(struct device *dev) /* Turn off the display */ xilinx_fb_out32(drvdata, REG_CTRL, 0); - /* Release the resources, as allocated based on interface */ - if (drvdata->flags & BUS_ACCESS_FLAG) - devm_iounmap(dev, drvdata->regs); #ifdef CONFIG_PPC_DCR - else + /* Release the resources, as allocated based on interface */ + if (!(drvdata->flags & BUS_ACCESS_FLAG)) dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); #endif - kfree(drvdata); - dev_set_drvdata(dev, NULL); - return 0; } @@ -413,7 +395,7 @@ static int xilinxfb_release(struct device *dev) * OF bus binding */ -static int xilinxfb_of_probe(struct platform_device *op) +static int xilinxfb_of_probe(struct platform_device *pdev) { const u32 *prop; u32 tft_access = 0; @@ -425,17 +407,15 @@ static int xilinxfb_of_probe(struct platform_device *op) pdata = xilinx_fb_default_pdata; /* Allocate the driver data region */ - drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) { - dev_err(&op->dev, "Couldn't allocate device private record\n"); + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) return -ENOMEM; - } /* * To check whether the core is connected directly to DCR or BUS * interface and initialize the tft_access accordingly. */ - of_property_read_u32(op->dev.of_node, "xlnx,dcr-splb-slave-if", + of_property_read_u32(pdev->dev.of_node, "xlnx,dcr-splb-slave-if", &tft_access); /* @@ -448,40 +428,39 @@ static int xilinxfb_of_probe(struct platform_device *op) #ifdef CONFIG_PPC_DCR else { int start; - start = dcr_resource_start(op->dev.of_node, 0); - drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0); - drvdata->dcr_host = dcr_map(op->dev.of_node, start, drvdata->dcr_len); + start = dcr_resource_start(pdev->dev.of_node, 0); + drvdata->dcr_len = dcr_resource_len(pdev->dev.of_node, 0); + drvdata->dcr_host = dcr_map(pdev->dev.of_node, start, drvdata->dcr_len); if (!DCR_MAP_OK(drvdata->dcr_host)) { - dev_err(&op->dev, "invalid DCR address\n"); - kfree(drvdata); + dev_err(&pdev->dev, "invalid DCR address\n"); return -ENODEV; } } #endif - prop = of_get_property(op->dev.of_node, "phys-size", &size); + prop = of_get_property(pdev->dev.of_node, "phys-size", &size); if ((prop) && (size >= sizeof(u32)*2)) { pdata.screen_width_mm = prop[0]; pdata.screen_height_mm = prop[1]; } - prop = of_get_property(op->dev.of_node, "resolution", &size); + prop = of_get_property(pdev->dev.of_node, "resolution", &size); if ((prop) && (size >= sizeof(u32)*2)) { pdata.xres = prop[0]; pdata.yres = prop[1]; } - prop = of_get_property(op->dev.of_node, "virtual-resolution", &size); + prop = of_get_property(pdev->dev.of_node, "virtual-resolution", &size); if ((prop) && (size >= sizeof(u32)*2)) { pdata.xvirt = prop[0]; pdata.yvirt = prop[1]; } - if (of_find_property(op->dev.of_node, "rotate-display", NULL)) + if (of_find_property(pdev->dev.of_node, "rotate-display", NULL)) pdata.rotate_screen = 1; - dev_set_drvdata(&op->dev, drvdata); - return xilinxfb_assign(op, drvdata, &pdata); + dev_set_drvdata(&pdev->dev, drvdata); + return xilinxfb_assign(pdev, drvdata, &pdata); } static int xilinxfb_of_remove(struct platform_device *op) |