diff options
-rw-r--r-- | drivers/video/da8xx-fb.c | 301 | ||||
-rw-r--r-- | include/video/da8xx-fb.h | 1 |
2 files changed, 235 insertions, 67 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8d244ba0f601..cad7d45c8bac 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -36,7 +36,9 @@ | |||
36 | #define DRIVER_NAME "da8xx_lcdc" | 36 | #define DRIVER_NAME "da8xx_lcdc" |
37 | 37 | ||
38 | /* LCD Status Register */ | 38 | /* LCD Status Register */ |
39 | #define LCD_END_OF_FRAME1 BIT(9) | ||
39 | #define LCD_END_OF_FRAME0 BIT(8) | 40 | #define LCD_END_OF_FRAME0 BIT(8) |
41 | #define LCD_PL_LOAD_DONE BIT(6) | ||
40 | #define LCD_FIFO_UNDERFLOW BIT(5) | 42 | #define LCD_FIFO_UNDERFLOW BIT(5) |
41 | #define LCD_SYNC_LOST BIT(2) | 43 | #define LCD_SYNC_LOST BIT(2) |
42 | 44 | ||
@@ -58,11 +60,13 @@ | |||
58 | #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) | 60 | #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) |
59 | #define PALETTE_AND_DATA 0x00 | 61 | #define PALETTE_AND_DATA 0x00 |
60 | #define PALETTE_ONLY 0x01 | 62 | #define PALETTE_ONLY 0x01 |
63 | #define DATA_ONLY 0x02 | ||
61 | 64 | ||
62 | #define LCD_MONO_8BIT_MODE BIT(9) | 65 | #define LCD_MONO_8BIT_MODE BIT(9) |
63 | #define LCD_RASTER_ORDER BIT(8) | 66 | #define LCD_RASTER_ORDER BIT(8) |
64 | #define LCD_TFT_MODE BIT(7) | 67 | #define LCD_TFT_MODE BIT(7) |
65 | #define LCD_UNDERFLOW_INT_ENA BIT(6) | 68 | #define LCD_UNDERFLOW_INT_ENA BIT(6) |
69 | #define LCD_PL_ENABLE BIT(4) | ||
66 | #define LCD_MONOCHROME_MODE BIT(1) | 70 | #define LCD_MONOCHROME_MODE BIT(1) |
67 | #define LCD_RASTER_ENABLE BIT(0) | 71 | #define LCD_RASTER_ENABLE BIT(0) |
68 | #define LCD_TFT_ALT_ENABLE BIT(23) | 72 | #define LCD_TFT_ALT_ENABLE BIT(23) |
@@ -87,6 +91,10 @@ | |||
87 | #define LCD_DMA_CTRL_REG 0x40 | 91 | #define LCD_DMA_CTRL_REG 0x40 |
88 | #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 | 92 | #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 |
89 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 | 93 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 |
94 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C | ||
95 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 | ||
96 | |||
97 | #define LCD_NUM_BUFFERS 2 | ||
90 | 98 | ||
91 | #define WSI_TIMEOUT 50 | 99 | #define WSI_TIMEOUT 50 |
92 | #define PALETTE_SIZE 256 | 100 | #define PALETTE_SIZE 256 |
@@ -111,13 +119,20 @@ static inline void lcdc_write(unsigned int val, unsigned int addr) | |||
111 | struct da8xx_fb_par { | 119 | struct da8xx_fb_par { |
112 | resource_size_t p_palette_base; | 120 | resource_size_t p_palette_base; |
113 | unsigned char *v_palette_base; | 121 | unsigned char *v_palette_base; |
122 | dma_addr_t vram_phys; | ||
123 | unsigned long vram_size; | ||
124 | void *vram_virt; | ||
125 | unsigned int dma_start; | ||
126 | unsigned int dma_end; | ||
114 | struct clk *lcdc_clk; | 127 | struct clk *lcdc_clk; |
115 | int irq; | 128 | int irq; |
116 | unsigned short pseudo_palette[16]; | 129 | unsigned short pseudo_palette[16]; |
117 | unsigned int databuf_sz; | ||
118 | unsigned int palette_sz; | 130 | unsigned int palette_sz; |
119 | unsigned int pxl_clk; | 131 | unsigned int pxl_clk; |
120 | int blank; | 132 | int blank; |
133 | wait_queue_head_t vsync_wait; | ||
134 | int vsync_flag; | ||
135 | int vsync_timeout; | ||
121 | #ifdef CONFIG_CPU_FREQ | 136 | #ifdef CONFIG_CPU_FREQ |
122 | struct notifier_block freq_transition; | 137 | struct notifier_block freq_transition; |
123 | #endif | 138 | #endif |
@@ -148,9 +163,9 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = { | |||
148 | .type = FB_TYPE_PACKED_PIXELS, | 163 | .type = FB_TYPE_PACKED_PIXELS, |
149 | .type_aux = 0, | 164 | .type_aux = 0, |
150 | .visual = FB_VISUAL_PSEUDOCOLOR, | 165 | .visual = FB_VISUAL_PSEUDOCOLOR, |
151 | .xpanstep = 1, | 166 | .xpanstep = 0, |
152 | .ypanstep = 1, | 167 | .ypanstep = 1, |
153 | .ywrapstep = 1, | 168 | .ywrapstep = 0, |
154 | .accel = FB_ACCEL_NONE | 169 | .accel = FB_ACCEL_NONE |
155 | }; | 170 | }; |
156 | 171 | ||
@@ -221,22 +236,48 @@ static inline void lcd_disable_raster(void) | |||
221 | 236 | ||
222 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | 237 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) |
223 | { | 238 | { |
224 | u32 tmp = par->p_palette_base + par->databuf_sz - 4; | 239 | u32 start; |
225 | u32 reg; | 240 | u32 end; |
241 | u32 reg_ras; | ||
242 | u32 reg_dma; | ||
243 | |||
244 | /* init reg to clear PLM (loading mode) fields */ | ||
245 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | ||
246 | reg_ras &= ~(3 << 20); | ||
247 | |||
248 | reg_dma = lcdc_read(LCD_DMA_CTRL_REG); | ||
249 | |||
250 | if (load_mode == LOAD_DATA) { | ||
251 | start = par->dma_start; | ||
252 | end = par->dma_end; | ||
253 | |||
254 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); | ||
255 | reg_dma |= LCD_END_OF_FRAME_INT_ENA; | ||
256 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; | ||
257 | |||
258 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
259 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
260 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
261 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
262 | } else if (load_mode == LOAD_PALETTE) { | ||
263 | start = par->p_palette_base; | ||
264 | end = start + par->palette_sz - 1; | ||
265 | |||
266 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | ||
267 | reg_ras |= LCD_PL_ENABLE; | ||
268 | |||
269 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
270 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
271 | } | ||
226 | 272 | ||
227 | /* Update the databuf in the hw. */ | 273 | lcdc_write(reg_dma, LCD_DMA_CTRL_REG); |
228 | lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 274 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
229 | lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
230 | 275 | ||
231 | /* Start the DMA. */ | 276 | /* |
232 | reg = lcdc_read(LCD_RASTER_CTRL_REG); | 277 | * The Raster enable bit must be set after all other control fields are |
233 | reg &= ~(3 << 20); | 278 | * set. |
234 | if (load_mode == LOAD_DATA) | 279 | */ |
235 | reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA); | 280 | lcd_enable_raster(); |
236 | else if (load_mode == LOAD_PALETTE) | ||
237 | reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | ||
238 | |||
239 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | ||
240 | } | 281 | } |
241 | 282 | ||
242 | /* Configure the Burst Size of DMA */ | 283 | /* Configure the Burst Size of DMA */ |
@@ -368,12 +409,8 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
368 | static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | 409 | static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, |
369 | u32 bpp, u32 raster_order) | 410 | u32 bpp, u32 raster_order) |
370 | { | 411 | { |
371 | u32 bpl, reg; | 412 | u32 reg; |
372 | 413 | ||
373 | /* Disable Dual Frame Buffer. */ | ||
374 | reg = lcdc_read(LCD_DMA_CTRL_REG); | ||
375 | lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE, | ||
376 | LCD_DMA_CTRL_REG); | ||
377 | /* Set the Panel Width */ | 414 | /* Set the Panel Width */ |
378 | /* Pixels per line = (PPL + 1)*16 */ | 415 | /* Pixels per line = (PPL + 1)*16 */ |
379 | /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ | 416 | /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ |
@@ -410,9 +447,6 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
410 | return -EINVAL; | 447 | return -EINVAL; |
411 | } | 448 | } |
412 | 449 | ||
413 | bpl = width * bpp / 8; | ||
414 | par->databuf_sz = height * bpl + par->palette_sz; | ||
415 | |||
416 | return 0; | 450 | return 0; |
417 | } | 451 | } |
418 | 452 | ||
@@ -421,8 +455,9 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
421 | struct fb_info *info) | 455 | struct fb_info *info) |
422 | { | 456 | { |
423 | struct da8xx_fb_par *par = info->par; | 457 | struct da8xx_fb_par *par = info->par; |
424 | unsigned short *palette = (unsigned short *)par->v_palette_base; | 458 | unsigned short *palette = (unsigned short *) par->v_palette_base; |
425 | u_short pal; | 459 | u_short pal; |
460 | int update_hw = 0; | ||
426 | 461 | ||
427 | if (regno > 255) | 462 | if (regno > 255) |
428 | return 1; | 463 | return 1; |
@@ -439,8 +474,10 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
439 | pal |= (green & 0x00f0); | 474 | pal |= (green & 0x00f0); |
440 | pal |= (blue & 0x000f); | 475 | pal |= (blue & 0x000f); |
441 | 476 | ||
442 | palette[regno] = pal; | 477 | if (palette[regno] != pal) { |
443 | 478 | update_hw = 1; | |
479 | palette[regno] = pal; | ||
480 | } | ||
444 | } else if ((info->var.bits_per_pixel == 16) && regno < 16) { | 481 | } else if ((info->var.bits_per_pixel == 16) && regno < 16) { |
445 | red >>= (16 - info->var.red.length); | 482 | red >>= (16 - info->var.red.length); |
446 | red <<= info->var.red.offset; | 483 | red <<= info->var.red.offset; |
@@ -453,9 +490,16 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
453 | 490 | ||
454 | par->pseudo_palette[regno] = red | green | blue; | 491 | par->pseudo_palette[regno] = red | green | blue; |
455 | 492 | ||
456 | palette[0] = 0x4000; | 493 | if (palette[0] != 0x4000) { |
494 | update_hw = 1; | ||
495 | palette[0] = 0x4000; | ||
496 | } | ||
457 | } | 497 | } |
458 | 498 | ||
499 | /* Update the palette in the h/w as needed. */ | ||
500 | if (update_hw) | ||
501 | lcd_blit(LOAD_PALETTE, par); | ||
502 | |||
459 | return 0; | 503 | return 0; |
460 | } | 504 | } |
461 | 505 | ||
@@ -541,15 +585,54 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
541 | 585 | ||
542 | static irqreturn_t lcdc_irq_handler(int irq, void *arg) | 586 | static irqreturn_t lcdc_irq_handler(int irq, void *arg) |
543 | { | 587 | { |
588 | struct da8xx_fb_par *par = arg; | ||
544 | u32 stat = lcdc_read(LCD_STAT_REG); | 589 | u32 stat = lcdc_read(LCD_STAT_REG); |
590 | u32 reg_ras; | ||
545 | 591 | ||
546 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | 592 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { |
547 | lcd_disable_raster(); | 593 | lcd_disable_raster(); |
548 | lcdc_write(stat, LCD_STAT_REG); | 594 | lcdc_write(stat, LCD_STAT_REG); |
549 | lcd_enable_raster(); | 595 | lcd_enable_raster(); |
550 | } else | 596 | } else if (stat & LCD_PL_LOAD_DONE) { |
597 | /* | ||
598 | * Must disable raster before changing state of any control bit. | ||
599 | * And also must be disabled before clearing the PL loading | ||
600 | * interrupt via the following write to the status register. If | ||
601 | * this is done after then one gets multiple PL done interrupts. | ||
602 | */ | ||
603 | lcd_disable_raster(); | ||
604 | |||
551 | lcdc_write(stat, LCD_STAT_REG); | 605 | lcdc_write(stat, LCD_STAT_REG); |
552 | 606 | ||
607 | /* Disable PL completion inerrupt */ | ||
608 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | ||
609 | reg_ras &= ~LCD_PL_ENABLE; | ||
610 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | ||
611 | |||
612 | /* Setup and start data loading mode */ | ||
613 | lcd_blit(LOAD_DATA, par); | ||
614 | } else { | ||
615 | lcdc_write(stat, LCD_STAT_REG); | ||
616 | |||
617 | if (stat & LCD_END_OF_FRAME0) { | ||
618 | lcdc_write(par->dma_start, | ||
619 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
620 | lcdc_write(par->dma_end, | ||
621 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
622 | par->vsync_flag = 1; | ||
623 | wake_up_interruptible(&par->vsync_wait); | ||
624 | } | ||
625 | |||
626 | if (stat & LCD_END_OF_FRAME1) { | ||
627 | lcdc_write(par->dma_start, | ||
628 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
629 | lcdc_write(par->dma_end, | ||
630 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
631 | par->vsync_flag = 1; | ||
632 | wake_up_interruptible(&par->vsync_wait); | ||
633 | } | ||
634 | } | ||
635 | |||
553 | return IRQ_HANDLED; | 636 | return IRQ_HANDLED; |
554 | } | 637 | } |
555 | 638 | ||
@@ -654,9 +737,10 @@ static int __devexit fb_remove(struct platform_device *dev) | |||
654 | 737 | ||
655 | unregister_framebuffer(info); | 738 | unregister_framebuffer(info); |
656 | fb_dealloc_cmap(&info->cmap); | 739 | fb_dealloc_cmap(&info->cmap); |
657 | dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, | 740 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, |
658 | info->screen_base - PAGE_SIZE, | 741 | par->p_palette_base); |
659 | info->fix.smem_start); | 742 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, |
743 | par->vram_phys); | ||
660 | free_irq(par->irq, par); | 744 | free_irq(par->irq, par); |
661 | clk_disable(par->lcdc_clk); | 745 | clk_disable(par->lcdc_clk); |
662 | clk_put(par->lcdc_clk); | 746 | clk_put(par->lcdc_clk); |
@@ -668,6 +752,39 @@ static int __devexit fb_remove(struct platform_device *dev) | |||
668 | return 0; | 752 | return 0; |
669 | } | 753 | } |
670 | 754 | ||
755 | /* | ||
756 | * Function to wait for vertical sync which for this LCD peripheral | ||
757 | * translates into waiting for the current raster frame to complete. | ||
758 | */ | ||
759 | static int fb_wait_for_vsync(struct fb_info *info) | ||
760 | { | ||
761 | struct da8xx_fb_par *par = info->par; | ||
762 | int ret; | ||
763 | |||
764 | /* | ||
765 | * Set flag to 0 and wait for isr to set to 1. It would seem there is a | ||
766 | * race condition here where the ISR could have occured just before or | ||
767 | * just after this set. But since we are just coarsely waiting for | ||
768 | * a frame to complete then that's OK. i.e. if the frame completed | ||
769 | * just before this code executed then we have to wait another full | ||
770 | * frame time but there is no way to avoid such a situation. On the | ||
771 | * other hand if the frame completed just after then we don't need | ||
772 | * to wait long at all. Either way we are guaranteed to return to the | ||
773 | * user immediately after a frame completion which is all that is | ||
774 | * required. | ||
775 | */ | ||
776 | par->vsync_flag = 0; | ||
777 | ret = wait_event_interruptible_timeout(par->vsync_wait, | ||
778 | par->vsync_flag != 0, | ||
779 | par->vsync_timeout); | ||
780 | if (ret < 0) | ||
781 | return ret; | ||
782 | if (ret == 0) | ||
783 | return -ETIMEDOUT; | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
671 | static int fb_ioctl(struct fb_info *info, unsigned int cmd, | 788 | static int fb_ioctl(struct fb_info *info, unsigned int cmd, |
672 | unsigned long arg) | 789 | unsigned long arg) |
673 | { | 790 | { |
@@ -697,6 +814,8 @@ static int fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
697 | sync_arg.pulse_width, | 814 | sync_arg.pulse_width, |
698 | sync_arg.front_porch); | 815 | sync_arg.front_porch); |
699 | break; | 816 | break; |
817 | case FBIO_WAITFORVSYNC: | ||
818 | return fb_wait_for_vsync(info); | ||
700 | default: | 819 | default: |
701 | return -EINVAL; | 820 | return -EINVAL; |
702 | } | 821 | } |
@@ -732,10 +851,47 @@ static int cfb_blank(int blank, struct fb_info *info) | |||
732 | return ret; | 851 | return ret; |
733 | } | 852 | } |
734 | 853 | ||
854 | /* | ||
855 | * Set new x,y offsets in the virtual display for the visible area and switch | ||
856 | * to the new mode. | ||
857 | */ | ||
858 | static int da8xx_pan_display(struct fb_var_screeninfo *var, | ||
859 | struct fb_info *fbi) | ||
860 | { | ||
861 | int ret = 0; | ||
862 | struct fb_var_screeninfo new_var; | ||
863 | struct da8xx_fb_par *par = fbi->par; | ||
864 | struct fb_fix_screeninfo *fix = &fbi->fix; | ||
865 | unsigned int end; | ||
866 | unsigned int start; | ||
867 | |||
868 | if (var->xoffset != fbi->var.xoffset || | ||
869 | var->yoffset != fbi->var.yoffset) { | ||
870 | memcpy(&new_var, &fbi->var, sizeof(new_var)); | ||
871 | new_var.xoffset = var->xoffset; | ||
872 | new_var.yoffset = var->yoffset; | ||
873 | if (fb_check_var(&new_var, fbi)) | ||
874 | ret = -EINVAL; | ||
875 | else { | ||
876 | memcpy(&fbi->var, &new_var, sizeof(new_var)); | ||
877 | |||
878 | start = fix->smem_start + | ||
879 | new_var.yoffset * fix->line_length + | ||
880 | new_var.xoffset * var->bits_per_pixel / 8; | ||
881 | end = start + var->yres * fix->line_length - 1; | ||
882 | par->dma_start = start; | ||
883 | par->dma_end = end; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | return ret; | ||
888 | } | ||
889 | |||
735 | static struct fb_ops da8xx_fb_ops = { | 890 | static struct fb_ops da8xx_fb_ops = { |
736 | .owner = THIS_MODULE, | 891 | .owner = THIS_MODULE, |
737 | .fb_check_var = fb_check_var, | 892 | .fb_check_var = fb_check_var, |
738 | .fb_setcolreg = fb_setcolreg, | 893 | .fb_setcolreg = fb_setcolreg, |
894 | .fb_pan_display = da8xx_pan_display, | ||
739 | .fb_ioctl = fb_ioctl, | 895 | .fb_ioctl = fb_ioctl, |
740 | .fb_fillrect = cfb_fillrect, | 896 | .fb_fillrect = cfb_fillrect, |
741 | .fb_copyarea = cfb_copyarea, | 897 | .fb_copyarea = cfb_copyarea, |
@@ -829,40 +985,53 @@ static int __init fb_probe(struct platform_device *device) | |||
829 | } | 985 | } |
830 | 986 | ||
831 | /* allocate frame buffer */ | 987 | /* allocate frame buffer */ |
832 | da8xx_fb_info->screen_base = dma_alloc_coherent(NULL, | 988 | par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp; |
833 | par->databuf_sz + PAGE_SIZE, | 989 | par->vram_size = PAGE_ALIGN(par->vram_size/8); |
834 | (resource_size_t *) | 990 | par->vram_size = par->vram_size * LCD_NUM_BUFFERS; |
835 | &da8xx_fb_info->fix.smem_start, | 991 | |
836 | GFP_KERNEL | GFP_DMA); | 992 | par->vram_virt = dma_alloc_coherent(NULL, |
837 | 993 | par->vram_size, | |
838 | if (!da8xx_fb_info->screen_base) { | 994 | (resource_size_t *) &par->vram_phys, |
995 | GFP_KERNEL | GFP_DMA); | ||
996 | if (!par->vram_virt) { | ||
839 | dev_err(&device->dev, | 997 | dev_err(&device->dev, |
840 | "GLCD: kmalloc for frame buffer failed\n"); | 998 | "GLCD: kmalloc for frame buffer failed\n"); |
841 | ret = -EINVAL; | 999 | ret = -EINVAL; |
842 | goto err_release_fb; | 1000 | goto err_release_fb; |
843 | } | 1001 | } |
844 | 1002 | ||
845 | /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */ | 1003 | da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; |
846 | par->v_palette_base = da8xx_fb_info->screen_base + | 1004 | da8xx_fb_fix.smem_start = par->vram_phys; |
847 | (PAGE_SIZE - par->palette_sz); | 1005 | da8xx_fb_fix.smem_len = par->vram_size; |
848 | par->p_palette_base = da8xx_fb_info->fix.smem_start + | 1006 | da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; |
849 | (PAGE_SIZE - par->palette_sz); | 1007 | |
850 | 1008 | par->dma_start = par->vram_phys; | |
851 | /* the rest of the frame buffer is pixel data */ | 1009 | par->dma_end = par->dma_start + lcdc_info->height * |
852 | da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz; | 1010 | da8xx_fb_fix.line_length - 1; |
853 | da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz; | 1011 | |
854 | da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; | 1012 | /* allocate palette buffer */ |
855 | da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; | 1013 | par->v_palette_base = dma_alloc_coherent(NULL, |
1014 | PALETTE_SIZE, | ||
1015 | (resource_size_t *) | ||
1016 | &par->p_palette_base, | ||
1017 | GFP_KERNEL | GFP_DMA); | ||
1018 | if (!par->v_palette_base) { | ||
1019 | dev_err(&device->dev, | ||
1020 | "GLCD: kmalloc for palette buffer failed\n"); | ||
1021 | ret = -EINVAL; | ||
1022 | goto err_release_fb_mem; | ||
1023 | } | ||
1024 | memset(par->v_palette_base, 0, PALETTE_SIZE); | ||
856 | 1025 | ||
857 | par->irq = platform_get_irq(device, 0); | 1026 | par->irq = platform_get_irq(device, 0); |
858 | if (par->irq < 0) { | 1027 | if (par->irq < 0) { |
859 | ret = -ENOENT; | 1028 | ret = -ENOENT; |
860 | goto err_release_fb_mem; | 1029 | goto err_release_pl_mem; |
861 | } | 1030 | } |
862 | 1031 | ||
863 | ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); | 1032 | ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); |
864 | if (ret) | 1033 | if (ret) |
865 | goto err_release_fb_mem; | 1034 | goto err_release_pl_mem; |
866 | 1035 | ||
867 | /* Initialize par */ | 1036 | /* Initialize par */ |
868 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; | 1037 | da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; |
@@ -870,8 +1039,8 @@ static int __init fb_probe(struct platform_device *device) | |||
870 | da8xx_fb_var.xres = lcdc_info->width; | 1039 | da8xx_fb_var.xres = lcdc_info->width; |
871 | da8xx_fb_var.xres_virtual = lcdc_info->width; | 1040 | da8xx_fb_var.xres_virtual = lcdc_info->width; |
872 | 1041 | ||
873 | da8xx_fb_var.yres = lcdc_info->height; | 1042 | da8xx_fb_var.yres = lcdc_info->height; |
874 | da8xx_fb_var.yres_virtual = lcdc_info->height; | 1043 | da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS; |
875 | 1044 | ||
876 | da8xx_fb_var.grayscale = | 1045 | da8xx_fb_var.grayscale = |
877 | lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; | 1046 | lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; |
@@ -892,18 +1061,18 @@ static int __init fb_probe(struct platform_device *device) | |||
892 | ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); | 1061 | ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); |
893 | if (ret) | 1062 | if (ret) |
894 | goto err_free_irq; | 1063 | goto err_free_irq; |
895 | |||
896 | /* First palette_sz byte of the frame buffer is the palette */ | ||
897 | da8xx_fb_info->cmap.len = par->palette_sz; | 1064 | da8xx_fb_info->cmap.len = par->palette_sz; |
898 | 1065 | ||
899 | /* Flush the buffer to the screen. */ | ||
900 | lcd_blit(LOAD_DATA, par); | ||
901 | |||
902 | /* initialize var_screeninfo */ | 1066 | /* initialize var_screeninfo */ |
903 | da8xx_fb_var.activate = FB_ACTIVATE_FORCE; | 1067 | da8xx_fb_var.activate = FB_ACTIVATE_FORCE; |
904 | fb_set_var(da8xx_fb_info, &da8xx_fb_var); | 1068 | fb_set_var(da8xx_fb_info, &da8xx_fb_var); |
905 | 1069 | ||
906 | dev_set_drvdata(&device->dev, da8xx_fb_info); | 1070 | dev_set_drvdata(&device->dev, da8xx_fb_info); |
1071 | |||
1072 | /* initialize the vsync wait queue */ | ||
1073 | init_waitqueue_head(&par->vsync_wait); | ||
1074 | par->vsync_timeout = HZ / 5; | ||
1075 | |||
907 | /* Register the Frame Buffer */ | 1076 | /* Register the Frame Buffer */ |
908 | if (register_framebuffer(da8xx_fb_info) < 0) { | 1077 | if (register_framebuffer(da8xx_fb_info) < 0) { |
909 | dev_err(&device->dev, | 1078 | dev_err(&device->dev, |
@@ -919,10 +1088,6 @@ static int __init fb_probe(struct platform_device *device) | |||
919 | goto err_cpu_freq; | 1088 | goto err_cpu_freq; |
920 | } | 1089 | } |
921 | #endif | 1090 | #endif |
922 | |||
923 | /* enable raster engine */ | ||
924 | lcd_enable_raster(); | ||
925 | |||
926 | return 0; | 1091 | return 0; |
927 | 1092 | ||
928 | #ifdef CONFIG_CPU_FREQ | 1093 | #ifdef CONFIG_CPU_FREQ |
@@ -936,10 +1101,12 @@ err_dealloc_cmap: | |||
936 | err_free_irq: | 1101 | err_free_irq: |
937 | free_irq(par->irq, par); | 1102 | free_irq(par->irq, par); |
938 | 1103 | ||
1104 | err_release_pl_mem: | ||
1105 | dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, | ||
1106 | par->p_palette_base); | ||
1107 | |||
939 | err_release_fb_mem: | 1108 | err_release_fb_mem: |
940 | dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, | 1109 | dma_free_coherent(NULL, par->vram_size, par->vram_virt, par->vram_phys); |
941 | da8xx_fb_info->screen_base - PAGE_SIZE, | ||
942 | da8xx_fb_info->fix.smem_start); | ||
943 | 1110 | ||
944 | err_release_fb: | 1111 | err_release_fb: |
945 | framebuffer_release(da8xx_fb_info); | 1112 | framebuffer_release(da8xx_fb_info); |
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h index 89d43b3d4cb9..6316cdabf73f 100644 --- a/include/video/da8xx-fb.h +++ b/include/video/da8xx-fb.h | |||
@@ -99,6 +99,7 @@ struct lcd_sync_arg { | |||
99 | #define FBIPUT_COLOR _IOW('F', 6, int) | 99 | #define FBIPUT_COLOR _IOW('F', 6, int) |
100 | #define FBIPUT_HSYNC _IOW('F', 9, int) | 100 | #define FBIPUT_HSYNC _IOW('F', 9, int) |
101 | #define FBIPUT_VSYNC _IOW('F', 10, int) | 101 | #define FBIPUT_VSYNC _IOW('F', 10, int) |
102 | #define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) | ||
102 | 103 | ||
103 | #endif /* ifndef DA8XX_FB_H */ | 104 | #endif /* ifndef DA8XX_FB_H */ |
104 | 105 | ||