aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pxafb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pxafb.c')
-rw-r--r--drivers/video/pxafb.c152
1 files changed, 113 insertions, 39 deletions
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index d0746261c957..97204497d9f7 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -30,6 +30,7 @@
30#include <linux/string.h> 30#include <linux/string.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/mm.h>
33#include <linux/fb.h> 34#include <linux/fb.h>
34#include <linux/delay.h> 35#include <linux/delay.h>
35#include <linux/init.h> 36#include <linux/init.h>
@@ -40,17 +41,18 @@
40#include <linux/clk.h> 41#include <linux/clk.h>
41#include <linux/err.h> 42#include <linux/err.h>
42#include <linux/completion.h> 43#include <linux/completion.h>
44#include <linux/mutex.h>
43#include <linux/kthread.h> 45#include <linux/kthread.h>
44#include <linux/freezer.h> 46#include <linux/freezer.h>
45 47
46#include <asm/hardware.h> 48#include <mach/hardware.h>
47#include <asm/io.h> 49#include <asm/io.h>
48#include <asm/irq.h> 50#include <asm/irq.h>
49#include <asm/div64.h> 51#include <asm/div64.h>
50#include <asm/arch/pxa-regs.h> 52#include <mach/pxa-regs.h>
51#include <asm/arch/pxa2xx-gpio.h> 53#include <mach/pxa2xx-gpio.h>
52#include <asm/arch/bitfield.h> 54#include <mach/bitfield.h>
53#include <asm/arch/pxafb.h> 55#include <mach/pxafb.h>
54 56
55/* 57/*
56 * Complain if VAR is out of range. 58 * Complain if VAR is out of range.
@@ -227,6 +229,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
227 case 4: ret = LCCR3_4BPP; break; 229 case 4: ret = LCCR3_4BPP; break;
228 case 8: ret = LCCR3_8BPP; break; 230 case 8: ret = LCCR3_8BPP; break;
229 case 16: ret = LCCR3_16BPP; break; 231 case 16: ret = LCCR3_16BPP; break;
232 case 24:
233 switch (var->red.length + var->green.length +
234 var->blue.length + var->transp.length) {
235 case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
236 case 19: ret = LCCR3_19BPP_P; break;
237 }
238 break;
239 case 32:
240 switch (var->red.length + var->green.length +
241 var->blue.length + var->transp.length) {
242 case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
243 case 19: ret = LCCR3_19BPP; break;
244 case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
245 case 25: ret = LCCR3_25BPP; break;
246 }
247 break;
230 } 248 }
231 return ret; 249 return ret;
232} 250}
@@ -345,6 +363,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
345 var->green.offset = 5; var->green.length = 6; 363 var->green.offset = 5; var->green.length = 6;
346 var->blue.offset = 0; var->blue.length = 5; 364 var->blue.offset = 0; var->blue.length = 5;
347 var->transp.offset = var->transp.length = 0; 365 var->transp.offset = var->transp.length = 0;
366 } else if (var->bits_per_pixel > 16) {
367 struct pxafb_mode_info *mode;
368
369 mode = pxafb_getmode(inf, var);
370 if (!mode)
371 return -EINVAL;
372
373 switch (mode->depth) {
374 case 18: /* RGB666 */
375 var->transp.offset = var->transp.length = 0;
376 var->red.offset = 12; var->red.length = 6;
377 var->green.offset = 6; var->green.length = 6;
378 var->blue.offset = 0; var->blue.length = 6;
379 break;
380 case 19: /* RGBT666 */
381 var->transp.offset = 18; var->transp.length = 1;
382 var->red.offset = 12; var->red.length = 6;
383 var->green.offset = 6; var->green.length = 6;
384 var->blue.offset = 0; var->blue.length = 6;
385 break;
386 case 24: /* RGB888 */
387 var->transp.offset = var->transp.length = 0;
388 var->red.offset = 16; var->red.length = 8;
389 var->green.offset = 8; var->green.length = 8;
390 var->blue.offset = 0; var->blue.length = 8;
391 break;
392 case 25: /* RGBT888 */
393 var->transp.offset = 24; var->transp.length = 1;
394 var->red.offset = 16; var->red.length = 8;
395 var->green.offset = 8; var->green.length = 8;
396 var->blue.offset = 0; var->blue.length = 8;
397 break;
398 default:
399 return -EINVAL;
400 }
348 } else { 401 } else {
349 var->red.offset = var->green.offset = 0; 402 var->red.offset = var->green.offset = 0;
350 var->blue.offset = var->transp.offset = 0; 403 var->blue.offset = var->transp.offset = 0;
@@ -376,7 +429,7 @@ static int pxafb_set_par(struct fb_info *info)
376 struct pxafb_info *fbi = (struct pxafb_info *)info; 429 struct pxafb_info *fbi = (struct pxafb_info *)info;
377 struct fb_var_screeninfo *var = &info->var; 430 struct fb_var_screeninfo *var = &info->var;
378 431
379 if (var->bits_per_pixel == 16) 432 if (var->bits_per_pixel >= 16)
380 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; 433 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
381 else if (!fbi->cmap_static) 434 else if (!fbi->cmap_static)
382 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 435 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +444,7 @@ static int pxafb_set_par(struct fb_info *info)
391 444
392 fbi->fb.fix.line_length = var->xres_virtual * 445 fbi->fb.fix.line_length = var->xres_virtual *
393 var->bits_per_pixel / 8; 446 var->bits_per_pixel / 8;
394 if (var->bits_per_pixel == 16) 447 if (var->bits_per_pixel >= 16)
395 fbi->palette_size = 0; 448 fbi->palette_size = 0;
396 else 449 else
397 fbi->palette_size = var->bits_per_pixel == 1 ? 450 fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +457,7 @@ static int pxafb_set_par(struct fb_info *info)
404 */ 457 */
405 pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); 458 pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
406 459
407 if (fbi->fb.var.bits_per_pixel == 16) 460 if (fbi->fb.var.bits_per_pixel >= 16)
408 fb_dealloc_cmap(&fbi->fb.cmap); 461 fb_dealloc_cmap(&fbi->fb.cmap);
409 else 462 else
410 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0); 463 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +884,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
831 case 4: 884 case 4:
832 case 8: 885 case 8:
833 case 16: 886 case 16:
887 case 24:
888 case 32:
834 break; 889 break;
835 default: 890 default:
836 printk(KERN_ERR "%s: invalid bit depth %d\n", 891 printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,10 +1023,17 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
968 1023
969 for (gpio = 58; ldd_bits; gpio++, ldd_bits--) 1024 for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
970 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT); 1025 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
1026 /* 18 bit interface */
1027 if (fbi->fb.var.bits_per_pixel > 16) {
1028 pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
1029 pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
1030 }
971 pxa_gpio_mode(GPIO74_LCD_FCLK_MD); 1031 pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
972 pxa_gpio_mode(GPIO75_LCD_LCLK_MD); 1032 pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
973 pxa_gpio_mode(GPIO76_LCD_PCLK_MD); 1033 pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
974 pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); 1034
1035 if ((lccr0 & LCCR0_PAS) == 0)
1036 pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD);
975} 1037}
976 1038
977static void pxafb_enable_controller(struct pxafb_info *fbi) 1039static void pxafb_enable_controller(struct pxafb_info *fbi)
@@ -1058,7 +1120,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
1058{ 1120{
1059 u_int old_state; 1121 u_int old_state;
1060 1122
1061 down(&fbi->ctrlr_sem); 1123 mutex_lock(&fbi->ctrlr_lock);
1062 1124
1063 old_state = fbi->state; 1125 old_state = fbi->state;
1064 1126
@@ -1146,7 +1208,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
1146 } 1208 }
1147 break; 1209 break;
1148 } 1210 }
1149 up(&fbi->ctrlr_sem); 1211 mutex_unlock(&fbi->ctrlr_lock);
1150} 1212}
1151 1213
1152/* 1214/*
@@ -1276,7 +1338,7 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
1276 fbi->dma_buff_phys = fbi->map_dma; 1338 fbi->dma_buff_phys = fbi->map_dma;
1277 fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; 1339 fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
1278 1340
1279 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16)); 1341 pr_debug("pxafb: palette_mem_size = 0x%08x\n", fbi->palette_size*sizeof(u16));
1280 1342
1281#ifdef CONFIG_FB_PXA_SMARTPANEL 1343#ifdef CONFIG_FB_PXA_SMARTPANEL
1282 fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; 1344 fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
@@ -1340,6 +1402,8 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi,
1340 if (lcd_conn == LCD_MONO_STN_8BPP) 1402 if (lcd_conn == LCD_MONO_STN_8BPP)
1341 fbi->lccr0 |= LCCR0_DPD; 1403 fbi->lccr0 |= LCCR0_DPD;
1342 1404
1405 fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
1406
1343 fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); 1407 fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
1344 fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; 1408 fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
1345 fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; 1409 fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
@@ -1399,7 +1463,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
1399 1463
1400 init_waitqueue_head(&fbi->ctrlr_wait); 1464 init_waitqueue_head(&fbi->ctrlr_wait);
1401 INIT_WORK(&fbi->task, pxafb_task); 1465 INIT_WORK(&fbi->task, pxafb_task);
1402 init_MUTEX(&fbi->ctrlr_sem); 1466 mutex_init(&fbi->ctrlr_lock);
1403 init_completion(&fbi->disable_done); 1467 init_completion(&fbi->disable_done);
1404#ifdef CONFIG_FB_PXA_SMARTPANEL 1468#ifdef CONFIG_FB_PXA_SMARTPANEL
1405 init_completion(&fbi->command_done); 1469 init_completion(&fbi->command_done);
@@ -1613,53 +1677,63 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
1613#define pxafb_setup_options() (0) 1677#define pxafb_setup_options() (0)
1614#endif 1678#endif
1615 1679
1616static int __devinit pxafb_probe(struct platform_device *dev)
1617{
1618 struct pxafb_info *fbi;
1619 struct pxafb_mach_info *inf;
1620 struct resource *r;
1621 int irq, ret;
1622
1623 dev_dbg(&dev->dev, "pxafb_probe\n");
1624
1625 inf = dev->dev.platform_data;
1626 ret = -ENOMEM;
1627 fbi = NULL;
1628 if (!inf)
1629 goto failed;
1630
1631 ret = pxafb_parse_options(&dev->dev, g_options);
1632 if (ret < 0)
1633 goto failed;
1634
1635#ifdef DEBUG_VAR 1680#ifdef DEBUG_VAR
1636 /* Check for various illegal bit-combinations. Currently only 1681/* Check for various illegal bit-combinations. Currently only
1637 * a warning is given. */ 1682 * a warning is given. */
1683static void __devinit pxafb_check_options(struct device *dev,
1684 struct pxafb_mach_info *inf)
1685{
1686 if (inf->lcd_conn)
1687 return;
1638 1688
1639 if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) 1689 if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
1640 dev_warn(&dev->dev, "machine LCCR0 setting contains " 1690 dev_warn(dev, "machine LCCR0 setting contains "
1641 "illegal bits: %08x\n", 1691 "illegal bits: %08x\n",
1642 inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); 1692 inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
1643 if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) 1693 if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
1644 dev_warn(&dev->dev, "machine LCCR3 setting contains " 1694 dev_warn(dev, "machine LCCR3 setting contains "
1645 "illegal bits: %08x\n", 1695 "illegal bits: %08x\n",
1646 inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); 1696 inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
1647 if (inf->lccr0 & LCCR0_DPD && 1697 if (inf->lccr0 & LCCR0_DPD &&
1648 ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || 1698 ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
1649 (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || 1699 (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
1650 (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) 1700 (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
1651 dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is " 1701 dev_warn(dev, "Double Pixel Data (DPD) mode is "
1652 "only valid in passive mono" 1702 "only valid in passive mono"
1653 " single panel mode\n"); 1703 " single panel mode\n");
1654 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && 1704 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
1655 (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) 1705 (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
1656 dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); 1706 dev_warn(dev, "Dual panel only valid in passive mode\n");
1657 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && 1707 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
1658 (inf->modes->upper_margin || inf->modes->lower_margin)) 1708 (inf->modes->upper_margin || inf->modes->lower_margin))
1659 dev_warn(&dev->dev, "Upper and lower margins must be 0 in " 1709 dev_warn(dev, "Upper and lower margins must be 0 in "
1660 "passive mode\n"); 1710 "passive mode\n");
1711}
1712#else
1713#define pxafb_check_options(...) do {} while (0)
1661#endif 1714#endif
1662 1715
1716static int __devinit pxafb_probe(struct platform_device *dev)
1717{
1718 struct pxafb_info *fbi;
1719 struct pxafb_mach_info *inf;
1720 struct resource *r;
1721 int irq, ret;
1722
1723 dev_dbg(&dev->dev, "pxafb_probe\n");
1724
1725 inf = dev->dev.platform_data;
1726 ret = -ENOMEM;
1727 fbi = NULL;
1728 if (!inf)
1729 goto failed;
1730
1731 ret = pxafb_parse_options(&dev->dev, g_options);
1732 if (ret < 0)
1733 goto failed;
1734
1735 pxafb_check_options(&dev->dev, inf);
1736
1663 dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", 1737 dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
1664 inf->modes->xres, 1738 inf->modes->xres,
1665 inf->modes->yres, 1739 inf->modes->yres,