aboutsummaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
commit2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac (patch)
tree9c0927ed1d540e5fd704c1f82689870786514655 /drivers/video
parent2195d2818c37bdf263865f1e9effccdd9fc5f9d4 (diff)
parent87d721ad7a37b7650dd710c88dd5c6a5bf9fe996 (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (257 commits) [ARM] Update mach-types ARM: 5636/1: Move vendor enum to AMBA include ARM: Fix pfn_valid() for sparse memory [ARM] orion5x: Add LaCie NAS 2Big Network support [ARM] pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume ARM: 5686/1: at91: Correct AC97 reset line in at91sam9263ek board ARM: 5640/1: This patch modifies the support of AC97 on the at91sam9263 ek board ARM: 5689/1: Update default config of HP Jornada 700-series machines ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() with highmem ARM: 5688/1: ks8695_serial: disable_irq() lockup ARM: 5687/1: fix an oops with highmem ARM: 5684/1: Add nuc960 platform to w90x900 ARM: 5683/1: Add nuc950 platform to w90x900 ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform ARM: 5626/1: add suspend/resume functions to amba-pl011 serial driver ARM: 5625/1: fix hard coded 4K resource size in amba bus detection MMC: MMCI: convert realview MMC to use gpiolib ARM: 5685/1: Make MMCI driver compile without gpiolib ARM: implement highpte ARM: Show FIQ in /proc/interrupts on CONFIG_FIQ ... Fix up trivial conflict in arch/arm/kernel/signal.c. It was due to the TIF_NOTIFY_RESUME addition in commit d0420c83f ("KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures") and follow-ups.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/atmel_lcdfb.c6
-rw-r--r--drivers/video/backlight/Kconfig2
-rw-r--r--drivers/video/imxfb.c184
4 files changed, 132 insertions, 64 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3b54b394017..1999b183481 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -935,7 +935,7 @@ config FB_S1D13XXX
config FB_ATMEL
tristate "AT91/AT32 LCD Controller support"
- depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || AVR32)
+ depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9G10 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -951,7 +951,7 @@ config FB_INTSRAM
config FB_ATMEL_STN
bool "Use a STN display with AT91/AT32 LCD Controller"
- depends on FB_ATMEL && MACH_AT91SAM9261EK
+ depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
default n
help
Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index da05f0801bb..2830ffd7297 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -182,7 +182,8 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
{
unsigned long value;
- if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000()))
+ if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
+ || cpu_is_at32ap7000()))
return xres;
value = xres;
@@ -824,7 +825,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
info->fix = atmel_lcdfb_fix;
/* Enable LCDC Clocks */
- if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {
+ if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
+ || cpu_is_at32ap7000()) {
sinfo->bus_clk = clk_get(dev, "hck1");
if (IS_ERR(sinfo->bus_clk)) {
ret = PTR_ERR(sinfo->bus_clk);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index f9d19be0554..90861cd9316 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -110,7 +110,7 @@ config BACKLIGHT_CLASS_DEVICE
config BACKLIGHT_ATMEL_LCDC
bool "Atmel LCDC Contrast-as-Backlight control"
depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL
- default y if MACH_SAM9261EK || MACH_SAM9263EK
+ default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
help
This provides a backlight control internal to the Atmel LCDC
driver. If the LCD "contrast control" on your board is wired
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 15a0ee6d8e2..30ae3022f63 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -33,6 +33,7 @@
#include <linux/math64.h>
#include <mach/imxfb.h>
+#include <mach/hardware.h>
/*
* Complain if VAR is out of range.
@@ -129,6 +130,10 @@
#define LCDISR_EOF (1<<1)
#define LCDISR_BOF (1<<0)
+/* Used fb-mode. Can be set on kernel command line, therefore file-static. */
+static const char *fb_mode;
+
+
/*
* These are the bitfields for each
* display depth that we support.
@@ -145,10 +150,6 @@ struct imxfb_info {
void __iomem *regs;
struct clk *clk;
- u_int max_bpp;
- u_int max_xres;
- u_int max_yres;
-
/*
* These are the addresses we mapped
* the framebuffer memory region to.
@@ -172,6 +173,9 @@ struct imxfb_info {
cmap_static:1,
unused:30;
+ struct imx_fb_videomode *mode;
+ int num_modes;
+
void (*lcd_power)(int);
void (*backlight_power)(int);
};
@@ -298,6 +302,18 @@ static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return ret;
}
+static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi)
+{
+ struct imx_fb_videomode *m;
+ int i;
+
+ for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) {
+ if (!strcmp(m->mode.name, fb_mode))
+ return m;
+ }
+ return NULL;
+}
+
/*
* imxfb_check_var():
* Round up in the following order: bits_per_pixel, xres,
@@ -308,35 +324,81 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct imxfb_info *fbi = info->par;
struct imxfb_rgb *rgb;
+ const struct imx_fb_videomode *imxfb_mode;
+ unsigned long lcd_clk;
+ unsigned long long tmp;
+ u32 pcr = 0;
if (var->xres < MIN_XRES)
var->xres = MIN_XRES;
if (var->yres < MIN_YRES)
var->yres = MIN_YRES;
- if (var->xres > fbi->max_xres)
- var->xres = fbi->max_xres;
- if (var->yres > fbi->max_yres)
- var->yres = fbi->max_yres;
- var->xres_virtual = max(var->xres_virtual, var->xres);
- var->yres_virtual = max(var->yres_virtual, var->yres);
+
+ imxfb_mode = imxfb_find_mode(fbi);
+ if (!imxfb_mode)
+ return -EINVAL;
+
+ var->xres = imxfb_mode->mode.xres;
+ var->yres = imxfb_mode->mode.yres;
+ var->bits_per_pixel = imxfb_mode->bpp;
+ var->pixclock = imxfb_mode->mode.pixclock;
+ var->hsync_len = imxfb_mode->mode.hsync_len;
+ var->left_margin = imxfb_mode->mode.left_margin;
+ var->right_margin = imxfb_mode->mode.right_margin;
+ var->vsync_len = imxfb_mode->mode.vsync_len;
+ var->upper_margin = imxfb_mode->mode.upper_margin;
+ var->lower_margin = imxfb_mode->mode.lower_margin;
+ var->sync = imxfb_mode->mode.sync;
+ var->xres_virtual = max(var->xres_virtual, var->xres);
+ var->yres_virtual = max(var->yres_virtual, var->yres);
pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+
+ lcd_clk = clk_get_rate(fbi->clk);
+
+ tmp = var->pixclock * (unsigned long long)lcd_clk;
+
+ do_div(tmp, 1000000);
+
+ if (do_div(tmp, 1000000) > 500000)
+ tmp++;
+
+ pcr = (unsigned int)tmp;
+
+ if (--pcr > 0x3F) {
+ pcr = 0x3F;
+ printk(KERN_WARNING "Must limit pixel clock to %luHz\n",
+ lcd_clk / pcr);
+ }
+
switch (var->bits_per_pixel) {
case 32:
+ pcr |= PCR_BPIX_18;
rgb = &def_rgb_18;
break;
case 16:
default:
- if (fbi->pcr & PCR_TFT)
+ if (cpu_is_mx1())
+ pcr |= PCR_BPIX_12;
+ else
+ pcr |= PCR_BPIX_16;
+
+ if (imxfb_mode->pcr & PCR_TFT)
rgb = &def_rgb_16_tft;
else
rgb = &def_rgb_16_stn;
break;
case 8:
+ pcr |= PCR_BPIX_8;
rgb = &def_rgb_8;
break;
}
+ /* add sync polarities */
+ pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
+
+ fbi->pcr = pcr;
+
/*
* Copy the RGB parameters for this display
* from the machine specific parameters.
@@ -393,10 +455,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
- /* physical screen start address */
- writel(VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4),
- fbi->regs + LCDC_VPW);
-
/* panning offset 0 (0 pixel offset) */
writel(0x00000000, fbi->regs + LCDC_POS);
@@ -468,8 +526,6 @@ static struct fb_ops imxfb_ops = {
static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct imxfb_info *fbi = info->par;
- unsigned int pcr, lcd_clk;
- unsigned long long tmp;
pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
var->xres, var->hsync_len,
@@ -505,6 +561,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
info->fix.id, var->lower_margin);
#endif
+ /* physical screen start address */
+ writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4),
+ fbi->regs + LCDC_VPW);
+
writel(HCR_H_WIDTH(var->hsync_len - 1) |
HCR_H_WAIT_1(var->right_margin - 1) |
HCR_H_WAIT_2(var->left_margin - 3),
@@ -518,22 +578,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
fbi->regs + LCDC_SIZE);
- lcd_clk = clk_get_rate(fbi->clk);
- tmp = var->pixclock * (unsigned long long)lcd_clk;
- do_div(tmp, 1000000);
- if (do_div(tmp, 1000000) > 500000)
- tmp++;
- pcr = (unsigned int)tmp;
- if (--pcr > 0x3F) {
- pcr = 0x3F;
- printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
- lcd_clk / pcr);
- }
-
- /* add sync polarities */
- pcr |= fbi->pcr & ~0x3F;
-
- writel(pcr, fbi->regs + LCDC_PCR);
+ writel(fbi->pcr, fbi->regs + LCDC_PCR);
writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -575,6 +620,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
struct imx_fb_platform_data *pdata = pdev->dev.platform_data;
struct fb_info *info = dev_get_drvdata(&pdev->dev);
struct imxfb_info *fbi = info->par;
+ struct imx_fb_videomode *m;
+ int i;
pr_debug("%s\n",__func__);
@@ -603,35 +650,18 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
info->fbops = &imxfb_ops;
info->flags = FBINFO_FLAG_DEFAULT |
FBINFO_READS_FAST;
-
- fbi->max_xres = pdata->xres;
- info->var.xres = pdata->xres;
- info->var.xres_virtual = pdata->xres;
- fbi->max_yres = pdata->yres;
- info->var.yres = pdata->yres;
- info->var.yres_virtual = pdata->yres;
- fbi->max_bpp = pdata->bpp;
- info->var.bits_per_pixel = pdata->bpp;
- info->var.nonstd = pdata->nonstd;
- info->var.pixclock = pdata->pixclock;
- info->var.hsync_len = pdata->hsync_len;
- info->var.left_margin = pdata->left_margin;
- info->var.right_margin = pdata->right_margin;
- info->var.vsync_len = pdata->vsync_len;
- info->var.upper_margin = pdata->upper_margin;
- info->var.lower_margin = pdata->lower_margin;
- info->var.sync = pdata->sync;
info->var.grayscale = pdata->cmap_greyscale;
fbi->cmap_inverse = pdata->cmap_inverse;
fbi->cmap_static = pdata->cmap_static;
- fbi->pcr = pdata->pcr;
fbi->lscr1 = pdata->lscr1;
fbi->dmacr = pdata->dmacr;
fbi->pwmr = pdata->pwmr;
fbi->lcd_power = pdata->lcd_power;
fbi->backlight_power = pdata->backlight_power;
- info->fix.smem_len = fbi->max_xres * fbi->max_yres *
- fbi->max_bpp / 8;
+
+ for (i = 0, m = &pdata->mode[0]; i < pdata->num_modes; i++, m++)
+ info->fix.smem_len = max_t(size_t, info->fix.smem_len,
+ m->mode.xres * m->mode.yres * m->bpp / 8);
return 0;
}
@@ -642,9 +672,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct imx_fb_platform_data *pdata;
struct resource *res;
- int ret;
+ int ret, i;
- printk("i.MX Framebuffer driver\n");
+ dev_info(&pdev->dev, "i.MX Framebuffer driver\n");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -662,6 +692,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
fbi = info->par;
+ if (!fb_mode)
+ fb_mode = pdata->mode[0].mode.name;
+
platform_set_drvdata(pdev, info);
ret = imxfb_init_fbinfo(pdev);
@@ -684,7 +717,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
fbi->regs = ioremap(res->start, resource_size(res));
if (fbi->regs == NULL) {
- printk(KERN_ERR"Cannot map frame buffer registers\n");
+ dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
goto failed_ioremap;
}
@@ -719,6 +752,13 @@ static int __init imxfb_probe(struct platform_device *pdev)
goto failed_platform_init;
}
+ fbi->mode = pdata->mode;
+ fbi->num_modes = pdata->num_modes;
+
+ INIT_LIST_HEAD(&info->modelist);
+ for (i = 0; i < pdata->num_modes; i++)
+ fb_add_videomode(&pdata->mode[i].mode, &info->modelist);
+
/*
* This makes sure that our colour bitfield
* descriptors are correctly initialised.
@@ -754,7 +794,7 @@ failed_map:
failed_getclock:
iounmap(fbi->regs);
failed_ioremap:
- release_mem_region(res->start, res->end - res->start);
+ release_mem_region(res->start, resource_size(res));
failed_req:
kfree(info->pseudo_palette);
failed_init:
@@ -785,7 +825,7 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
framebuffer_release(info);
iounmap(fbi->regs);
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
clk_disable(fbi->clk);
clk_put(fbi->clk);
@@ -811,8 +851,34 @@ static struct platform_driver imxfb_driver = {
},
};
+static int imxfb_setup(void)
+{
+#ifndef MODULE
+ char *opt, *options = NULL;
+
+ if (fb_get_options("imxfb", &options))
+ return -ENODEV;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+ else
+ fb_mode = opt;
+ }
+#endif
+ return 0;
+}
+
int __init imxfb_init(void)
{
+ int ret = imxfb_setup();
+
+ if (ret < 0)
+ return ret;
+
return platform_driver_probe(&imxfb_driver, imxfb_probe);
}