diff options
author | Manjunathappa, Prakash <prakash.pm@ti.com> | 2012-08-14 09:21:42 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2012-08-23 09:19:27 -0400 |
commit | 1a2b750cddee1c06d01f84ef2c516b4997f88806 (patch) | |
tree | 7200682825a231e397c2ba5242ff27484b6413c6 /drivers/video/da8xx-fb.c | |
parent | 7ed25867478fb8d2118eb84b99c1bf21e4ae695c (diff) |
da8xx-fb: add 24bpp LCD configuration support
LCD controller on am335x supports 24bpp raster configuration in addition
to ones on da850. LCDC also supports 24bpp in unpacked format having
ARGB:8888 32bpp format data in DDR, but it doesn't interpret alpha
component of the data.
Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Cc: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r-- | drivers/video/da8xx-fb.c | 128 |
1 files changed, 95 insertions, 33 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 7ae9d53f2bf1..761c8d1ad9a0 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -86,6 +86,8 @@ | |||
86 | #define LCD_V2_LIDD_CLK_EN BIT(1) | 86 | #define LCD_V2_LIDD_CLK_EN BIT(1) |
87 | #define LCD_V2_CORE_CLK_EN BIT(0) | 87 | #define LCD_V2_CORE_CLK_EN BIT(0) |
88 | #define LCD_V2_LPP_B10 26 | 88 | #define LCD_V2_LPP_B10 26 |
89 | #define LCD_V2_TFT_24BPP_MODE BIT(25) | ||
90 | #define LCD_V2_TFT_24BPP_UNPACK BIT(26) | ||
89 | 91 | ||
90 | /* LCD Raster Timing 2 Register */ | 92 | /* LCD Raster Timing 2 Register */ |
91 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) | 93 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) |
@@ -156,7 +158,6 @@ struct da8xx_fb_par { | |||
156 | unsigned int dma_end; | 158 | unsigned int dma_end; |
157 | struct clk *lcdc_clk; | 159 | struct clk *lcdc_clk; |
158 | int irq; | 160 | int irq; |
159 | unsigned short pseudo_palette[16]; | ||
160 | unsigned int palette_sz; | 161 | unsigned int palette_sz; |
161 | unsigned int pxl_clk; | 162 | unsigned int pxl_clk; |
162 | int blank; | 163 | int blank; |
@@ -175,6 +176,7 @@ struct da8xx_fb_par { | |||
175 | unsigned int lcd_fck_rate; | 176 | unsigned int lcd_fck_rate; |
176 | #endif | 177 | #endif |
177 | void (*panel_power_ctrl)(int); | 178 | void (*panel_power_ctrl)(int); |
179 | u32 pseudo_palette[16]; | ||
178 | }; | 180 | }; |
179 | 181 | ||
180 | /* Variable Screen Information */ | 182 | /* Variable Screen Information */ |
@@ -499,6 +501,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
499 | { | 501 | { |
500 | u32 reg; | 502 | u32 reg; |
501 | 503 | ||
504 | if (bpp > 16 && lcd_revision == LCD_VERSION_1) | ||
505 | return -EINVAL; | ||
506 | |||
502 | /* Set the Panel Width */ | 507 | /* Set the Panel Width */ |
503 | /* Pixels per line = (PPL + 1)*16 */ | 508 | /* Pixels per line = (PPL + 1)*16 */ |
504 | if (lcd_revision == LCD_VERSION_1) { | 509 | if (lcd_revision == LCD_VERSION_1) { |
@@ -542,14 +547,19 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
542 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); | 547 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); |
543 | if (raster_order) | 548 | if (raster_order) |
544 | reg |= LCD_RASTER_ORDER; | 549 | reg |= LCD_RASTER_ORDER; |
545 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 550 | |
551 | par->palette_sz = 16 * 2; | ||
546 | 552 | ||
547 | switch (bpp) { | 553 | switch (bpp) { |
548 | case 1: | 554 | case 1: |
549 | case 2: | 555 | case 2: |
550 | case 4: | 556 | case 4: |
551 | case 16: | 557 | case 16: |
552 | par->palette_sz = 16 * 2; | 558 | break; |
559 | case 24: | ||
560 | reg |= LCD_V2_TFT_24BPP_MODE; | ||
561 | case 32: | ||
562 | reg |= LCD_V2_TFT_24BPP_UNPACK; | ||
553 | break; | 563 | break; |
554 | 564 | ||
555 | case 8: | 565 | case 8: |
@@ -560,9 +570,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
560 | return -EINVAL; | 570 | return -EINVAL; |
561 | } | 571 | } |
562 | 572 | ||
573 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | ||
574 | |||
563 | return 0; | 575 | return 0; |
564 | } | 576 | } |
565 | 577 | ||
578 | #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) | ||
566 | static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | 579 | static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, |
567 | unsigned blue, unsigned transp, | 580 | unsigned blue, unsigned transp, |
568 | struct fb_info *info) | 581 | struct fb_info *info) |
@@ -578,13 +591,38 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
578 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) | 591 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) |
579 | return 1; | 592 | return 1; |
580 | 593 | ||
581 | if (info->var.bits_per_pixel == 4) { | 594 | if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) |
582 | if (regno > 15) | 595 | return -EINVAL; |
583 | return 1; | ||
584 | 596 | ||
585 | if (info->var.grayscale) { | 597 | switch (info->fix.visual) { |
586 | pal = regno; | 598 | case FB_VISUAL_TRUECOLOR: |
587 | } else { | 599 | red = CNVT_TOHW(red, info->var.red.length); |
600 | green = CNVT_TOHW(green, info->var.green.length); | ||
601 | blue = CNVT_TOHW(blue, info->var.blue.length); | ||
602 | break; | ||
603 | case FB_VISUAL_PSEUDOCOLOR: | ||
604 | switch (info->var.bits_per_pixel) { | ||
605 | case 4: | ||
606 | if (regno > 15) | ||
607 | return -EINVAL; | ||
608 | |||
609 | if (info->var.grayscale) { | ||
610 | pal = regno; | ||
611 | } else { | ||
612 | red >>= 4; | ||
613 | green >>= 8; | ||
614 | blue >>= 12; | ||
615 | |||
616 | pal = red & 0x0f00; | ||
617 | pal |= green & 0x00f0; | ||
618 | pal |= blue & 0x000f; | ||
619 | } | ||
620 | if (regno == 0) | ||
621 | pal |= 0x2000; | ||
622 | palette[regno] = pal; | ||
623 | break; | ||
624 | |||
625 | case 8: | ||
588 | red >>= 4; | 626 | red >>= 4; |
589 | green >>= 8; | 627 | green >>= 8; |
590 | blue >>= 12; | 628 | blue >>= 12; |
@@ -592,36 +630,36 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
592 | pal = (red & 0x0f00); | 630 | pal = (red & 0x0f00); |
593 | pal |= (green & 0x00f0); | 631 | pal |= (green & 0x00f0); |
594 | pal |= (blue & 0x000f); | 632 | pal |= (blue & 0x000f); |
595 | } | ||
596 | if (regno == 0) | ||
597 | pal |= 0x2000; | ||
598 | palette[regno] = pal; | ||
599 | 633 | ||
600 | } else if (info->var.bits_per_pixel == 8) { | 634 | if (palette[regno] != pal) { |
601 | red >>= 4; | 635 | update_hw = 1; |
602 | green >>= 8; | 636 | palette[regno] = pal; |
603 | blue >>= 12; | 637 | } |
604 | 638 | break; | |
605 | pal = (red & 0x0f00); | ||
606 | pal |= (green & 0x00f0); | ||
607 | pal |= (blue & 0x000f); | ||
608 | |||
609 | if (palette[regno] != pal) { | ||
610 | update_hw = 1; | ||
611 | palette[regno] = pal; | ||
612 | } | 639 | } |
613 | } else if ((info->var.bits_per_pixel == 16) && regno < 16) { | 640 | break; |
614 | red >>= (16 - info->var.red.length); | 641 | } |
615 | red <<= info->var.red.offset; | ||
616 | 642 | ||
617 | green >>= (16 - info->var.green.length); | 643 | /* Truecolor has hardware independent palette */ |
618 | green <<= info->var.green.offset; | 644 | if (info->fix.visual == FB_VISUAL_TRUECOLOR) { |
645 | u32 v; | ||
619 | 646 | ||
620 | blue >>= (16 - info->var.blue.length); | 647 | if (regno > 15) |
621 | blue <<= info->var.blue.offset; | 648 | return -EINVAL; |
622 | 649 | ||
623 | par->pseudo_palette[regno] = red | green | blue; | 650 | v = (red << info->var.red.offset) | |
651 | (green << info->var.green.offset) | | ||
652 | (blue << info->var.blue.offset); | ||
624 | 653 | ||
654 | switch (info->var.bits_per_pixel) { | ||
655 | case 16: | ||
656 | ((u16 *) (info->pseudo_palette))[regno] = v; | ||
657 | break; | ||
658 | case 24: | ||
659 | case 32: | ||
660 | ((u32 *) (info->pseudo_palette))[regno] = v; | ||
661 | break; | ||
662 | } | ||
625 | if (palette[0] != 0x4000) { | 663 | if (palette[0] != 0x4000) { |
626 | update_hw = 1; | 664 | update_hw = 1; |
627 | palette[0] = 0x4000; | 665 | palette[0] = 0x4000; |
@@ -634,6 +672,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
634 | 672 | ||
635 | return 0; | 673 | return 0; |
636 | } | 674 | } |
675 | #undef CNVT_TOHW | ||
637 | 676 | ||
638 | static void lcd_reset(struct da8xx_fb_par *par) | 677 | static void lcd_reset(struct da8xx_fb_par *par) |
639 | { | 678 | { |
@@ -842,6 +881,9 @@ static int fb_check_var(struct fb_var_screeninfo *var, | |||
842 | { | 881 | { |
843 | int err = 0; | 882 | int err = 0; |
844 | 883 | ||
884 | if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) | ||
885 | return -EINVAL; | ||
886 | |||
845 | switch (var->bits_per_pixel) { | 887 | switch (var->bits_per_pixel) { |
846 | case 1: | 888 | case 1: |
847 | case 8: | 889 | case 8: |
@@ -877,6 +919,26 @@ static int fb_check_var(struct fb_var_screeninfo *var, | |||
877 | var->transp.length = 0; | 919 | var->transp.length = 0; |
878 | var->nonstd = 0; | 920 | var->nonstd = 0; |
879 | break; | 921 | break; |
922 | case 24: | ||
923 | var->red.offset = 16; | ||
924 | var->red.length = 8; | ||
925 | var->green.offset = 8; | ||
926 | var->green.length = 8; | ||
927 | var->blue.offset = 0; | ||
928 | var->blue.length = 8; | ||
929 | var->nonstd = 0; | ||
930 | break; | ||
931 | case 32: | ||
932 | var->transp.offset = 24; | ||
933 | var->transp.length = 8; | ||
934 | var->red.offset = 16; | ||
935 | var->red.length = 8; | ||
936 | var->green.offset = 8; | ||
937 | var->green.length = 8; | ||
938 | var->blue.offset = 0; | ||
939 | var->blue.length = 8; | ||
940 | var->nonstd = 0; | ||
941 | break; | ||
880 | default: | 942 | default: |
881 | err = -EINVAL; | 943 | err = -EINVAL; |
882 | } | 944 | } |