2 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
4 * Freescale DIU Frame Buffer device driver
6 * Authors: Hongjun Chen <hong-jun.chen@freescale.com>
7 * Paul Widmer <paul.widmer@freescale.com>
8 * Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
9 * York Sun <yorksun@freescale.com>
11 * Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/string.h>
24 #include <linux/slab.h>
26 #include <linux/init.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/platform_device.h>
29 #include <linux/interrupt.h>
30 #include <linux/clk.h>
31 #include <linux/uaccess.h>
32 #include <linux/vmalloc.h>
34 #include <sysdev/fsl_soc.h>
35 #include <linux/fsl-diu-fb.h>
39 * List of supported video modes
41 * The first entry is the default video mode
43 static struct fb_videomode __devinitdata fsl_diu_mode_db
[] = {
45 .name
= "1024x768-60",
56 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
57 .vmode
= FB_VMODE_NONINTERLACED
60 .name
= "1024x768-70",
71 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
72 .vmode
= FB_VMODE_NONINTERLACED
75 .name
= "1024x768-75",
86 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
87 .vmode
= FB_VMODE_NONINTERLACED
90 .name
= "1280x1024-60",
101 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
102 .vmode
= FB_VMODE_NONINTERLACED
105 .name
= "1280x1024-70",
116 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
117 .vmode
= FB_VMODE_NONINTERLACED
120 .name
= "1280x1024-75",
131 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
132 .vmode
= FB_VMODE_NONINTERLACED
135 .name
= "320x240", /* for AOI only */
146 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
147 .vmode
= FB_VMODE_NONINTERLACED
150 .name
= "1280x480-60",
161 .sync
= FB_SYNC_COMP_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
162 .vmode
= FB_VMODE_NONINTERLACED
166 static char *fb_mode
= "1024x768-32@60";
167 static unsigned long default_bpp
= 32;
168 static enum fsl_diu_monitor_port monitor_port
;
169 static char *monitor_string
;
171 #if defined(CONFIG_NOT_COHERENT_CACHE)
172 static u8
*coherence_data
;
173 static size_t coherence_data_size
;
174 static unsigned int d_cache_line_size
;
177 static DEFINE_SPINLOCK(diu_lock
);
179 struct fsl_diu_data
{
180 struct fb_info
*fsl_diu_info
[FSL_AOI_NUM
- 1];
181 /*FSL_AOI_NUM has one dummy AOI */
182 struct device_attribute dev_attr
;
183 struct diu_ad
*dummy_ad
;
184 void *dummy_aoi_virt
;
187 enum fsl_diu_monitor_port monitor_port
;
196 unsigned long pseudo_palette
[16];
199 unsigned char g_alpha
;
201 int x_aoi_d
; /* aoi display x offset to physical screen */
202 int y_aoi_d
; /* aoi display y offset to physical screen */
203 struct fsl_diu_data
*parent
;
208 static struct mfb_info mfb_template
[] = {
209 { /* AOI 0 for plane 0 */
211 .type
= MFB_TYPE_OUTPUT
,
218 { /* AOI 0 for plane 1 */
220 .type
= MFB_TYPE_OUTPUT
,
228 { /* AOI 1 for plane 1 */
230 .type
= MFB_TYPE_OUTPUT
,
238 { /* AOI 0 for plane 2 */
240 .type
= MFB_TYPE_OUTPUT
,
248 { /* AOI 1 for plane 2 */
250 .type
= MFB_TYPE_OUTPUT
,
260 static struct diu_hw dr
= {
262 .reg_lock
= __SPIN_LOCK_UNLOCKED(diu_hw
.reg_lock
),
265 static struct diu_pool pool
;
268 * fsl_diu_name_to_port - convert a port name to a monitor port enum
270 * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
271 * the enum fsl_diu_monitor_port that corresponds to that string.
273 * For compatibility with older versions, a number ("0", "1", or "2") is also
276 * If the string is unknown, DVI is assumed.
278 * If the particular port is not supported by the platform, another port
279 * (platform-specific) is chosen instead.
281 static enum fsl_diu_monitor_port
fsl_diu_name_to_port(const char *s
)
283 enum fsl_diu_monitor_port port
= FSL_DIU_PORT_DVI
;
287 if (!strict_strtoul(s
, 10, &val
) && (val
<= 2))
288 port
= (enum fsl_diu_monitor_port
) val
;
289 else if (strncmp(s
, "lvds", 4) == 0)
290 port
= FSL_DIU_PORT_LVDS
;
291 else if (strncmp(s
, "dlvds", 5) == 0)
292 port
= FSL_DIU_PORT_DLVDS
;
295 return diu_ops
.valid_monitor_port(port
);
299 * fsl_diu_alloc - allocate memory for the DIU
300 * @size: number of bytes to allocate
301 * @param: returned physical address of memory
303 * This function allocates a physically-contiguous block of memory.
305 static void *fsl_diu_alloc(size_t size
, phys_addr_t
*phys
)
309 virt
= alloc_pages_exact(size
, GFP_DMA
| __GFP_ZERO
);
311 *phys
= virt_to_phys(virt
);
317 * fsl_diu_free - release DIU memory
318 * @virt: pointer returned by fsl_diu_alloc()
319 * @size: number of bytes allocated by fsl_diu_alloc()
321 * This function releases memory allocated by fsl_diu_alloc().
323 static void fsl_diu_free(void *virt
, size_t size
)
326 free_pages_exact(virt
, size
);
330 * Workaround for failed writing desc register of planes.
331 * Needed with MPC5121 DIU rev 2.0 silicon.
333 void wr_reg_wa(u32
*reg
, u32 val
)
337 } while (in_be32(reg
) != val
);
340 static int fsl_diu_enable_panel(struct fb_info
*info
)
342 struct mfb_info
*pmfbi
, *cmfbi
, *mfbi
= info
->par
;
343 struct diu
*hw
= dr
.diu_reg
;
344 struct diu_ad
*ad
= mfbi
->ad
;
345 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
348 if (mfbi
->type
!= MFB_TYPE_OFF
) {
349 switch (mfbi
->index
) {
350 case 0: /* plane 0 */
351 if (hw
->desc
[0] != ad
->paddr
)
352 wr_reg_wa(&hw
->desc
[0], ad
->paddr
);
354 case 1: /* plane 1 AOI 0 */
355 cmfbi
= machine_data
->fsl_diu_info
[2]->par
;
356 if (hw
->desc
[1] != ad
->paddr
) { /* AOI0 closed */
357 if (cmfbi
->count
> 0) /* AOI1 open */
359 cpu_to_le32(cmfbi
->ad
->paddr
);
362 wr_reg_wa(&hw
->desc
[1], ad
->paddr
);
365 case 3: /* plane 2 AOI 0 */
366 cmfbi
= machine_data
->fsl_diu_info
[4]->par
;
367 if (hw
->desc
[2] != ad
->paddr
) { /* AOI0 closed */
368 if (cmfbi
->count
> 0) /* AOI1 open */
370 cpu_to_le32(cmfbi
->ad
->paddr
);
373 wr_reg_wa(&hw
->desc
[2], ad
->paddr
);
376 case 2: /* plane 1 AOI 1 */
377 pmfbi
= machine_data
->fsl_diu_info
[1]->par
;
379 if (hw
->desc
[1] == machine_data
->dummy_ad
->paddr
)
380 wr_reg_wa(&hw
->desc
[1], ad
->paddr
);
382 pmfbi
->ad
->next_ad
= cpu_to_le32(ad
->paddr
);
384 case 4: /* plane 2 AOI 1 */
385 pmfbi
= machine_data
->fsl_diu_info
[3]->par
;
387 if (hw
->desc
[2] == machine_data
->dummy_ad
->paddr
)
388 wr_reg_wa(&hw
->desc
[2], ad
->paddr
);
389 else /* AOI0 was open */
390 pmfbi
->ad
->next_ad
= cpu_to_le32(ad
->paddr
);
401 static int fsl_diu_disable_panel(struct fb_info
*info
)
403 struct mfb_info
*pmfbi
, *cmfbi
, *mfbi
= info
->par
;
404 struct diu
*hw
= dr
.diu_reg
;
405 struct diu_ad
*ad
= mfbi
->ad
;
406 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
409 switch (mfbi
->index
) {
410 case 0: /* plane 0 */
411 if (hw
->desc
[0] != machine_data
->dummy_ad
->paddr
)
412 wr_reg_wa(&hw
->desc
[0], machine_data
->dummy_ad
->paddr
);
414 case 1: /* plane 1 AOI 0 */
415 cmfbi
= machine_data
->fsl_diu_info
[2]->par
;
416 if (cmfbi
->count
> 0) /* AOI1 is open */
417 wr_reg_wa(&hw
->desc
[1], cmfbi
->ad
->paddr
);
418 /* move AOI1 to the first */
419 else /* AOI1 was closed */
420 wr_reg_wa(&hw
->desc
[1], machine_data
->dummy_ad
->paddr
);
423 case 3: /* plane 2 AOI 0 */
424 cmfbi
= machine_data
->fsl_diu_info
[4]->par
;
425 if (cmfbi
->count
> 0) /* AOI1 is open */
426 wr_reg_wa(&hw
->desc
[2], cmfbi
->ad
->paddr
);
427 /* move AOI1 to the first */
428 else /* AOI1 was closed */
429 wr_reg_wa(&hw
->desc
[2], machine_data
->dummy_ad
->paddr
);
432 case 2: /* plane 1 AOI 1 */
433 pmfbi
= machine_data
->fsl_diu_info
[1]->par
;
434 if (hw
->desc
[1] != ad
->paddr
) {
435 /* AOI1 is not the first in the chain */
436 if (pmfbi
->count
> 0)
437 /* AOI0 is open, must be the first */
438 pmfbi
->ad
->next_ad
= 0;
439 } else /* AOI1 is the first in the chain */
440 wr_reg_wa(&hw
->desc
[1], machine_data
->dummy_ad
->paddr
);
443 case 4: /* plane 2 AOI 1 */
444 pmfbi
= machine_data
->fsl_diu_info
[3]->par
;
445 if (hw
->desc
[2] != ad
->paddr
) {
446 /* AOI1 is not the first in the chain */
447 if (pmfbi
->count
> 0)
448 /* AOI0 is open, must be the first */
449 pmfbi
->ad
->next_ad
= 0;
450 } else /* AOI1 is the first in the chain */
451 wr_reg_wa(&hw
->desc
[2], machine_data
->dummy_ad
->paddr
);
462 static void enable_lcdc(struct fb_info
*info
)
464 struct diu
*hw
= dr
.diu_reg
;
465 struct mfb_info
*mfbi
= info
->par
;
466 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
468 if (!machine_data
->fb_enabled
) {
469 out_be32(&hw
->diu_mode
, dr
.mode
);
470 machine_data
->fb_enabled
++;
474 static void disable_lcdc(struct fb_info
*info
)
476 struct diu
*hw
= dr
.diu_reg
;
477 struct mfb_info
*mfbi
= info
->par
;
478 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
480 if (machine_data
->fb_enabled
) {
481 out_be32(&hw
->diu_mode
, 0);
482 machine_data
->fb_enabled
= 0;
486 static void adjust_aoi_size_position(struct fb_var_screeninfo
*var
,
487 struct fb_info
*info
)
489 struct mfb_info
*lower_aoi_mfbi
, *upper_aoi_mfbi
, *mfbi
= info
->par
;
490 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
491 int available_height
, upper_aoi_bottom
, index
= mfbi
->index
;
492 int lower_aoi_is_open
, upper_aoi_is_open
;
493 __u32 base_plane_width
, base_plane_height
, upper_aoi_height
;
495 base_plane_width
= machine_data
->fsl_diu_info
[0]->var
.xres
;
496 base_plane_height
= machine_data
->fsl_diu_info
[0]->var
.yres
;
498 if (mfbi
->x_aoi_d
< 0)
500 if (mfbi
->y_aoi_d
< 0)
504 if (mfbi
->x_aoi_d
!= 0)
506 if (mfbi
->y_aoi_d
!= 0)
511 lower_aoi_mfbi
= machine_data
->fsl_diu_info
[index
+1]->par
;
512 lower_aoi_is_open
= lower_aoi_mfbi
->count
> 0 ? 1 : 0;
513 if (var
->xres
> base_plane_width
)
514 var
->xres
= base_plane_width
;
515 if ((mfbi
->x_aoi_d
+ var
->xres
) > base_plane_width
)
516 mfbi
->x_aoi_d
= base_plane_width
- var
->xres
;
518 if (lower_aoi_is_open
)
519 available_height
= lower_aoi_mfbi
->y_aoi_d
;
521 available_height
= base_plane_height
;
522 if (var
->yres
> available_height
)
523 var
->yres
= available_height
;
524 if ((mfbi
->y_aoi_d
+ var
->yres
) > available_height
)
525 mfbi
->y_aoi_d
= available_height
- var
->yres
;
529 upper_aoi_mfbi
= machine_data
->fsl_diu_info
[index
-1]->par
;
531 machine_data
->fsl_diu_info
[index
-1]->var
.yres
;
532 upper_aoi_bottom
= upper_aoi_mfbi
->y_aoi_d
+ upper_aoi_height
;
533 upper_aoi_is_open
= upper_aoi_mfbi
->count
> 0 ? 1 : 0;
534 if (var
->xres
> base_plane_width
)
535 var
->xres
= base_plane_width
;
536 if ((mfbi
->x_aoi_d
+ var
->xres
) > base_plane_width
)
537 mfbi
->x_aoi_d
= base_plane_width
- var
->xres
;
538 if (mfbi
->y_aoi_d
< 0)
540 if (upper_aoi_is_open
) {
541 if (mfbi
->y_aoi_d
< upper_aoi_bottom
)
542 mfbi
->y_aoi_d
= upper_aoi_bottom
;
543 available_height
= base_plane_height
546 available_height
= base_plane_height
;
547 if (var
->yres
> available_height
)
548 var
->yres
= available_height
;
549 if ((mfbi
->y_aoi_d
+ var
->yres
) > base_plane_height
)
550 mfbi
->y_aoi_d
= base_plane_height
- var
->yres
;
555 * Checks to see if the hardware supports the state requested by var passed
556 * in. This function does not alter the hardware state! If the var passed in
557 * is slightly off by what the hardware can support then we alter the var
558 * PASSED in to what we can do. If the hardware doesn't support mode change
559 * a -EINVAL will be returned by the upper layers.
561 static int fsl_diu_check_var(struct fb_var_screeninfo
*var
,
562 struct fb_info
*info
)
564 if (var
->xres_virtual
< var
->xres
)
565 var
->xres_virtual
= var
->xres
;
566 if (var
->yres_virtual
< var
->yres
)
567 var
->yres_virtual
= var
->yres
;
569 if (var
->xoffset
< 0)
572 if (var
->yoffset
< 0)
575 if (var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
)
576 var
->xoffset
= info
->var
.xres_virtual
- info
->var
.xres
;
578 if (var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
579 var
->yoffset
= info
->var
.yres_virtual
- info
->var
.yres
;
581 if ((var
->bits_per_pixel
!= 32) && (var
->bits_per_pixel
!= 24) &&
582 (var
->bits_per_pixel
!= 16))
583 var
->bits_per_pixel
= default_bpp
;
585 switch (var
->bits_per_pixel
) {
588 var
->red
.offset
= 11;
589 var
->red
.msb_right
= 0;
591 var
->green
.length
= 6;
592 var
->green
.offset
= 5;
593 var
->green
.msb_right
= 0;
595 var
->blue
.length
= 5;
596 var
->blue
.offset
= 0;
597 var
->blue
.msb_right
= 0;
599 var
->transp
.length
= 0;
600 var
->transp
.offset
= 0;
601 var
->transp
.msb_right
= 0;
606 var
->red
.msb_right
= 0;
608 var
->green
.length
= 8;
609 var
->green
.offset
= 8;
610 var
->green
.msb_right
= 0;
612 var
->blue
.length
= 8;
613 var
->blue
.offset
= 16;
614 var
->blue
.msb_right
= 0;
616 var
->transp
.length
= 0;
617 var
->transp
.offset
= 0;
618 var
->transp
.msb_right
= 0;
622 var
->red
.offset
= 16;
623 var
->red
.msb_right
= 0;
625 var
->green
.length
= 8;
626 var
->green
.offset
= 8;
627 var
->green
.msb_right
= 0;
629 var
->blue
.length
= 8;
630 var
->blue
.offset
= 0;
631 var
->blue
.msb_right
= 0;
633 var
->transp
.length
= 8;
634 var
->transp
.offset
= 24;
635 var
->transp
.msb_right
= 0;
644 /* Copy nonstd field to/from sync for fbset usage */
645 var
->sync
|= var
->nonstd
;
646 var
->nonstd
|= var
->sync
;
648 adjust_aoi_size_position(var
, info
);
652 static void set_fix(struct fb_info
*info
)
654 struct fb_fix_screeninfo
*fix
= &info
->fix
;
655 struct fb_var_screeninfo
*var
= &info
->var
;
656 struct mfb_info
*mfbi
= info
->par
;
658 strncpy(fix
->id
, mfbi
->id
, strlen(mfbi
->id
));
659 fix
->line_length
= var
->xres_virtual
* var
->bits_per_pixel
/ 8;
660 fix
->type
= FB_TYPE_PACKED_PIXELS
;
661 fix
->accel
= FB_ACCEL_NONE
;
662 fix
->visual
= FB_VISUAL_TRUECOLOR
;
667 static void update_lcdc(struct fb_info
*info
)
669 struct fb_var_screeninfo
*var
= &info
->var
;
670 struct mfb_info
*mfbi
= info
->par
;
671 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
674 char __iomem
*cursor_base
, *gamma_table_base
;
680 if (mfbi
->type
== MFB_TYPE_OFF
) {
681 fsl_diu_disable_panel(info
);
685 diu_ops
.set_monitor_port(machine_data
->monitor_port
);
686 gamma_table_base
= pool
.gamma
.vaddr
;
687 cursor_base
= pool
.cursor
.vaddr
;
688 /* Prep for DIU init - gamma table, cursor table */
690 for (i
= 0; i
<= 2; i
++)
691 for (j
= 0; j
<= 255; j
++)
692 *gamma_table_base
++ = j
;
694 diu_ops
.set_gamma_table(machine_data
->monitor_port
, pool
.gamma
.vaddr
);
698 /* Program DIU registers */
700 out_be32(&hw
->gamma
, pool
.gamma
.paddr
);
701 out_be32(&hw
->cursor
, pool
.cursor
.paddr
);
703 out_be32(&hw
->bgnd
, 0x007F7F7F); /* BGND */
704 out_be32(&hw
->bgnd_wb
, 0); /* BGND_WB */
705 out_be32(&hw
->disp_size
, (var
->yres
<< 16 | var
->xres
));
707 out_be32(&hw
->wb_size
, 0); /* WB SIZE */
708 out_be32(&hw
->wb_mem_addr
, 0); /* WB MEM ADDR */
710 /* Horizontal and vertical configuration register */
711 temp
= var
->left_margin
<< 22 | /* BP_H */
712 var
->hsync_len
<< 11 | /* PW_H */
713 var
->right_margin
; /* FP_H */
715 out_be32(&hw
->hsyn_para
, temp
);
717 temp
= var
->upper_margin
<< 22 | /* BP_V */
718 var
->vsync_len
<< 11 | /* PW_V */
719 var
->lower_margin
; /* FP_V */
721 out_be32(&hw
->vsyn_para
, temp
);
723 diu_ops
.set_pixel_clock(var
->pixclock
);
725 out_be32(&hw
->syn_pol
, 0); /* SYNC SIGNALS POLARITY */
726 out_be32(&hw
->thresholds
, 0x00037800); /* The Thresholds */
727 out_be32(&hw
->int_status
, 0); /* INTERRUPT STATUS */
728 out_be32(&hw
->plut
, 0x01F5F666);
734 static int map_video_memory(struct fb_info
*info
)
737 u32 smem_len
= info
->fix
.line_length
* info
->var
.yres_virtual
;
739 info
->screen_base
= fsl_diu_alloc(smem_len
, &phys
);
740 if (info
->screen_base
== NULL
) {
741 dev_err(info
->dev
, "unable to allocate fb memory\n");
744 mutex_lock(&info
->mm_lock
);
745 info
->fix
.smem_start
= (unsigned long) phys
;
746 info
->fix
.smem_len
= smem_len
;
747 mutex_unlock(&info
->mm_lock
);
748 info
->screen_size
= info
->fix
.smem_len
;
753 static void unmap_video_memory(struct fb_info
*info
)
755 fsl_diu_free(info
->screen_base
, info
->fix
.smem_len
);
756 mutex_lock(&info
->mm_lock
);
757 info
->screen_base
= NULL
;
758 info
->fix
.smem_start
= 0;
759 info
->fix
.smem_len
= 0;
760 mutex_unlock(&info
->mm_lock
);
764 * Using the fb_var_screeninfo in fb_info we set the aoi of this
765 * particular framebuffer. It is a light version of fsl_diu_set_par.
767 static int fsl_diu_set_aoi(struct fb_info
*info
)
769 struct fb_var_screeninfo
*var
= &info
->var
;
770 struct mfb_info
*mfbi
= info
->par
;
771 struct diu_ad
*ad
= mfbi
->ad
;
773 /* AOI should not be greater than display size */
774 ad
->offset_xyi
= cpu_to_le32((var
->yoffset
<< 16) | var
->xoffset
);
775 ad
->offset_xyd
= cpu_to_le32((mfbi
->y_aoi_d
<< 16) | mfbi
->x_aoi_d
);
780 * Using the fb_var_screeninfo in fb_info we set the resolution of this
781 * particular framebuffer. This function alters the fb_fix_screeninfo stored
782 * in fb_info. It does not alter var in fb_info since we are using that
783 * data. This means we depend on the data in var inside fb_info to be
784 * supported by the hardware. fsl_diu_check_var is always called before
785 * fsl_diu_set_par to ensure this.
787 static int fsl_diu_set_par(struct fb_info
*info
)
790 struct fb_var_screeninfo
*var
= &info
->var
;
791 struct mfb_info
*mfbi
= info
->par
;
792 struct fsl_diu_data
*machine_data
= mfbi
->parent
;
793 struct diu_ad
*ad
= mfbi
->ad
;
799 mfbi
->cursor_reset
= 1;
801 len
= info
->var
.yres_virtual
* info
->fix
.line_length
;
802 /* Alloc & dealloc each time resolution/bpp change */
803 if (len
!= info
->fix
.smem_len
) {
804 if (info
->fix
.smem_start
)
805 unmap_video_memory(info
);
807 /* Memory allocation for framebuffer */
808 if (map_video_memory(info
)) {
809 dev_err(info
->dev
, "unable to allocate fb memory 1\n");
814 ad
->pix_fmt
= diu_ops
.get_pixel_format(machine_data
->monitor_port
,
815 var
->bits_per_pixel
);
816 ad
->addr
= cpu_to_le32(info
->fix
.smem_start
);
817 ad
->src_size_g_alpha
= cpu_to_le32((var
->yres_virtual
<< 12) |
818 var
->xres_virtual
) | mfbi
->g_alpha
;
819 /* AOI should not be greater than display size */
820 ad
->aoi_size
= cpu_to_le32((var
->yres
<< 16) | var
->xres
);
821 ad
->offset_xyi
= cpu_to_le32((var
->yoffset
<< 16) | var
->xoffset
);
822 ad
->offset_xyd
= cpu_to_le32((mfbi
->y_aoi_d
<< 16) | mfbi
->x_aoi_d
);
824 /* Disable chroma keying function */
833 if (mfbi
->index
== 0)
838 static inline __u32
CNVT_TOHW(__u32 val
, __u32 width
)
840 return ((val
<< width
) + 0x7FFF - val
) >> 16;
844 * Set a single color register. The values supplied have a 16 bit magnitude
845 * which needs to be scaled in this function for the hardware. Things to take
846 * into consideration are how many color registers, if any, are supported with
847 * the current color visual. With truecolor mode no color palettes are
848 * supported. Here a pseudo palette is created which we store the value in
849 * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited
852 static int fsl_diu_setcolreg(unsigned int regno
, unsigned int red
,
853 unsigned int green
, unsigned int blue
,
854 unsigned int transp
, struct fb_info
*info
)
859 * If greyscale is true, then we convert the RGB value
860 * to greyscale no matter what visual we are using.
862 if (info
->var
.grayscale
)
863 red
= green
= blue
= (19595 * red
+ 38470 * green
+
865 switch (info
->fix
.visual
) {
866 case FB_VISUAL_TRUECOLOR
:
868 * 16-bit True Colour. We encode the RGB value
869 * according to the RGB bitfield information.
872 u32
*pal
= info
->pseudo_palette
;
875 red
= CNVT_TOHW(red
, info
->var
.red
.length
);
876 green
= CNVT_TOHW(green
, info
->var
.green
.length
);
877 blue
= CNVT_TOHW(blue
, info
->var
.blue
.length
);
878 transp
= CNVT_TOHW(transp
, info
->var
.transp
.length
);
880 v
= (red
<< info
->var
.red
.offset
) |
881 (green
<< info
->var
.green
.offset
) |
882 (blue
<< info
->var
.blue
.offset
) |
883 (transp
<< info
->var
.transp
.offset
);
895 * Pan (or wrap, depending on the `vmode' field) the display using the
896 * 'xoffset' and 'yoffset' fields of the 'var' structure. If the values
897 * don't fit, return -EINVAL.
899 static int fsl_diu_pan_display(struct fb_var_screeninfo
*var
,
900 struct fb_info
*info
)
902 if ((info
->var
.xoffset
== var
->xoffset
) &&
903 (info
->var
.yoffset
== var
->yoffset
))
904 return 0; /* No change, do nothing */
906 if (var
->xoffset
< 0 || var
->yoffset
< 0
907 || var
->xoffset
+ info
->var
.xres
> info
->var
.xres_virtual
908 || var
->yoffset
+ info
->var
.yres
> info
->var
.yres_virtual
)
911 info
->var
.xoffset
= var
->xoffset
;
912 info
->var
.yoffset
= var
->yoffset
;
914 if (var
->vmode
& FB_VMODE_YWRAP
)
915 info
->var
.vmode
|= FB_VMODE_YWRAP
;
917 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
919 fsl_diu_set_aoi(info
);
925 * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking
926 * succeeded, != 0 if un-/blanking failed.
927 * blank_mode == 2: suspend vsync
928 * blank_mode == 3: suspend hsync
929 * blank_mode == 4: powerdown
931 static int fsl_diu_blank(int blank_mode
, struct fb_info
*info
)
933 struct mfb_info
*mfbi
= info
->par
;
935 mfbi
->blank
= blank_mode
;
937 switch (blank_mode
) {
938 case FB_BLANK_VSYNC_SUSPEND
:
939 case FB_BLANK_HSYNC_SUSPEND
:
940 /* FIXME: fixes to enable_panel and enable lcdc needed */
941 case FB_BLANK_NORMAL
:
942 /* fsl_diu_disable_panel(info);*/
944 case FB_BLANK_POWERDOWN
:
945 /* disable_lcdc(info); */
947 case FB_BLANK_UNBLANK
:
948 /* fsl_diu_enable_panel(info);*/
955 static int fsl_diu_ioctl(struct fb_info
*info
, unsigned int cmd
,
958 struct mfb_info
*mfbi
= info
->par
;
959 struct diu_ad
*ad
= mfbi
->ad
;
960 struct mfb_chroma_key ck
;
961 unsigned char global_alpha
;
962 struct aoi_display_offset aoi_d
;
964 void __user
*buf
= (void __user
*)arg
;
970 if (copy_from_user(&pix_fmt
, buf
, sizeof(pix_fmt
)))
972 ad
->pix_fmt
= pix_fmt
;
975 pix_fmt
= ad
->pix_fmt
;
976 if (copy_to_user(buf
, &pix_fmt
, sizeof(pix_fmt
)))
980 if (copy_from_user(&aoi_d
, buf
, sizeof(aoi_d
)))
982 mfbi
->x_aoi_d
= aoi_d
.x_aoi_d
;
983 mfbi
->y_aoi_d
= aoi_d
.y_aoi_d
;
984 fsl_diu_check_var(&info
->var
, info
);
985 fsl_diu_set_aoi(info
);
988 aoi_d
.x_aoi_d
= mfbi
->x_aoi_d
;
989 aoi_d
.y_aoi_d
= mfbi
->y_aoi_d
;
990 if (copy_to_user(buf
, &aoi_d
, sizeof(aoi_d
)))
994 global_alpha
= mfbi
->g_alpha
;
995 if (copy_to_user(buf
, &global_alpha
, sizeof(global_alpha
)))
999 /* set panel information */
1000 if (copy_from_user(&global_alpha
, buf
, sizeof(global_alpha
)))
1002 ad
->src_size_g_alpha
= (ad
->src_size_g_alpha
& (~0xff)) |
1003 (global_alpha
& 0xff);
1004 mfbi
->g_alpha
= global_alpha
;
1006 case MFB_SET_CHROMA_KEY
:
1007 /* set panel winformation */
1008 if (copy_from_user(&ck
, buf
, sizeof(ck
)))
1012 (ck
.red_max
< ck
.red_min
||
1013 ck
.green_max
< ck
.green_min
||
1014 ck
.blue_max
< ck
.blue_min
))
1025 ad
->ckmax_r
= ck
.red_max
;
1026 ad
->ckmax_g
= ck
.green_max
;
1027 ad
->ckmax_b
= ck
.blue_max
;
1028 ad
->ckmin_r
= ck
.red_min
;
1029 ad
->ckmin_g
= ck
.green_min
;
1030 ad
->ckmin_b
= ck
.blue_min
;
1033 case FBIOGET_GWINFO
:
1034 if (mfbi
->type
== MFB_TYPE_OFF
)
1036 /* get graphic window information */
1037 if (copy_to_user(buf
, ad
, sizeof(*ad
)))
1042 dev_err(info
->dev
, "unknown ioctl command (0x%08X)\n", cmd
);
1043 return -ENOIOCTLCMD
;
1049 /* turn on fb if count == 1
1051 static int fsl_diu_open(struct fb_info
*info
, int user
)
1053 struct mfb_info
*mfbi
= info
->par
;
1056 /* free boot splash memory on first /dev/fb0 open */
1057 if (!mfbi
->index
&& diu_ops
.release_bootmem
)
1058 diu_ops
.release_bootmem();
1060 spin_lock(&diu_lock
);
1062 if (mfbi
->count
== 1) {
1063 fsl_diu_check_var(&info
->var
, info
);
1064 res
= fsl_diu_set_par(info
);
1068 res
= fsl_diu_enable_panel(info
);
1074 spin_unlock(&diu_lock
);
1078 /* turn off fb if count == 0
1080 static int fsl_diu_release(struct fb_info
*info
, int user
)
1082 struct mfb_info
*mfbi
= info
->par
;
1085 spin_lock(&diu_lock
);
1087 if (mfbi
->count
== 0) {
1088 res
= fsl_diu_disable_panel(info
);
1092 spin_unlock(&diu_lock
);
1096 static struct fb_ops fsl_diu_ops
= {
1097 .owner
= THIS_MODULE
,
1098 .fb_check_var
= fsl_diu_check_var
,
1099 .fb_set_par
= fsl_diu_set_par
,
1100 .fb_setcolreg
= fsl_diu_setcolreg
,
1101 .fb_blank
= fsl_diu_blank
,
1102 .fb_pan_display
= fsl_diu_pan_display
,
1103 .fb_fillrect
= cfb_fillrect
,
1104 .fb_copyarea
= cfb_copyarea
,
1105 .fb_imageblit
= cfb_imageblit
,
1106 .fb_ioctl
= fsl_diu_ioctl
,
1107 .fb_open
= fsl_diu_open
,
1108 .fb_release
= fsl_diu_release
,
1111 static int init_fbinfo(struct fb_info
*info
)
1113 struct mfb_info
*mfbi
= info
->par
;
1115 info
->device
= NULL
;
1116 info
->var
.activate
= FB_ACTIVATE_NOW
;
1117 info
->fbops
= &fsl_diu_ops
;
1118 info
->flags
= FBINFO_FLAG_DEFAULT
;
1119 info
->pseudo_palette
= &mfbi
->pseudo_palette
;
1121 /* Allocate colormap */
1122 fb_alloc_cmap(&info
->cmap
, 16, 0);
1126 static int __devinit
install_fb(struct fb_info
*info
)
1129 struct mfb_info
*mfbi
= info
->par
;
1130 const char *aoi_mode
, *init_aoi_mode
= "320x240";
1131 struct fb_videomode
*db
= fsl_diu_mode_db
;
1132 unsigned int dbsize
= ARRAY_SIZE(fsl_diu_mode_db
);
1133 int has_default_mode
= 1;
1135 if (init_fbinfo(info
))
1138 if (mfbi
->index
== 0) { /* plane 0 */
1139 if (mfbi
->edid_data
) {
1140 /* Now build modedb from EDID */
1141 fb_edid_to_monspecs(mfbi
->edid_data
, &info
->monspecs
);
1142 fb_videomode_to_modelist(info
->monspecs
.modedb
,
1143 info
->monspecs
.modedb_len
,
1145 db
= info
->monspecs
.modedb
;
1146 dbsize
= info
->monspecs
.modedb_len
;
1150 aoi_mode
= init_aoi_mode
;
1152 rc
= fb_find_mode(&info
->var
, info
, aoi_mode
, db
, dbsize
, NULL
,
1156 * For plane 0 we continue and look into
1157 * driver's internal modedb.
1159 if (mfbi
->index
== 0 && mfbi
->edid_data
)
1160 has_default_mode
= 0;
1165 if (!has_default_mode
) {
1166 rc
= fb_find_mode(&info
->var
, info
, aoi_mode
, fsl_diu_mode_db
,
1167 ARRAY_SIZE(fsl_diu_mode_db
), NULL
, default_bpp
);
1169 has_default_mode
= 1;
1172 /* Still not found, use preferred mode from database if any */
1173 if (!has_default_mode
&& info
->monspecs
.modedb
) {
1174 struct fb_monspecs
*specs
= &info
->monspecs
;
1175 struct fb_videomode
*modedb
= &specs
->modedb
[0];
1178 * Get preferred timing. If not found,
1179 * first mode in database will be used.
1181 if (specs
->misc
& FB_MISC_1ST_DETAIL
) {
1184 for (i
= 0; i
< specs
->modedb_len
; i
++) {
1185 if (specs
->modedb
[i
].flag
& FB_MODE_IS_FIRST
) {
1186 modedb
= &specs
->modedb
[i
];
1192 info
->var
.bits_per_pixel
= default_bpp
;
1193 fb_videomode_to_var(&info
->var
, modedb
);
1196 if (mfbi
->type
== MFB_TYPE_OFF
)
1197 mfbi
->blank
= FB_BLANK_NORMAL
;
1199 mfbi
->blank
= FB_BLANK_UNBLANK
;
1201 if (fsl_diu_check_var(&info
->var
, info
)) {
1202 dev_err(info
->dev
, "fsl_diu_check_var failed\n");
1203 fb_dealloc_cmap(&info
->cmap
);
1207 if (register_framebuffer(info
) < 0) {
1208 dev_err(info
->dev
, "register_framebuffer failed\n");
1209 unmap_video_memory(info
);
1210 fb_dealloc_cmap(&info
->cmap
);
1214 mfbi
->registered
= 1;
1215 dev_info(info
->dev
, "%s registered successfully\n", mfbi
->id
);
1220 static void uninstall_fb(struct fb_info
*info
)
1222 struct mfb_info
*mfbi
= info
->par
;
1224 if (!mfbi
->registered
)
1227 if (mfbi
->index
== 0)
1228 kfree(mfbi
->edid_data
);
1230 unregister_framebuffer(info
);
1231 unmap_video_memory(info
);
1233 fb_dealloc_cmap(&info
->cmap
);
1235 mfbi
->registered
= 0;
1238 static irqreturn_t
fsl_diu_isr(int irq
, void *dev_id
)
1240 struct diu
*hw
= dr
.diu_reg
;
1241 unsigned int status
= in_be32(&hw
->int_status
);
1244 /* This is the workaround for underrun */
1245 if (status
& INT_UNDRUN
) {
1246 out_be32(&hw
->diu_mode
, 0);
1248 out_be32(&hw
->diu_mode
, 1);
1250 #if defined(CONFIG_NOT_COHERENT_CACHE)
1251 else if (status
& INT_VSYNC
) {
1254 for (i
= 0; i
< coherence_data_size
;
1255 i
+= d_cache_line_size
)
1256 __asm__
__volatile__ (
1258 ::[input
]"r"(&coherence_data
[i
]));
1266 static int request_irq_local(int irq
)
1268 unsigned long status
, ints
;
1274 /* Read to clear the status */
1275 status
= in_be32(&hw
->int_status
);
1277 ret
= request_irq(irq
, fsl_diu_isr
, 0, "diu", NULL
);
1279 ints
= INT_PARERR
| INT_LS_BF_VS
;
1280 #if !defined(CONFIG_NOT_COHERENT_CACHE)
1284 if (dr
.mode
== MFB_MODE2
|| dr
.mode
== MFB_MODE3
)
1285 ints
|= INT_VSYNC_WB
;
1287 /* Read to clear the status */
1288 status
= in_be32(&hw
->int_status
);
1289 out_be32(&hw
->int_mask
, ints
);
1295 static void free_irq_local(int irq
)
1297 struct diu
*hw
= dr
.diu_reg
;
1299 /* Disable all LCDC interrupt */
1300 out_be32(&hw
->int_mask
, 0x1f);
1302 free_irq(irq
, NULL
);
1307 * Power management hooks. Note that we won't be called from IRQ context,
1308 * unlike the blank functions above, so we may sleep.
1310 static int fsl_diu_suspend(struct platform_device
*ofdev
, pm_message_t state
)
1312 struct fsl_diu_data
*machine_data
;
1314 machine_data
= dev_get_drvdata(&ofdev
->dev
);
1315 disable_lcdc(machine_data
->fsl_diu_info
[0]);
1320 static int fsl_diu_resume(struct platform_device
*ofdev
)
1322 struct fsl_diu_data
*machine_data
;
1324 machine_data
= dev_get_drvdata(&ofdev
->dev
);
1325 enable_lcdc(machine_data
->fsl_diu_info
[0]);
1331 #define fsl_diu_suspend NULL
1332 #define fsl_diu_resume NULL
1333 #endif /* CONFIG_PM */
1335 /* Align to 64-bit(8-byte), 32-byte, etc. */
1336 static int allocate_buf(struct device
*dev
, struct diu_addr
*buf
, u32 size
,
1341 dma_addr_t paddr
= 0;
1343 ssize
= size
+ bytes_align
;
1344 buf
->vaddr
= dma_alloc_coherent(dev
, ssize
, &paddr
, GFP_DMA
|
1349 buf
->paddr
= (__u32
) paddr
;
1351 mask
= bytes_align
- 1;
1352 offset
= (u32
)buf
->paddr
& mask
;
1354 buf
->offset
= bytes_align
- offset
;
1355 buf
->paddr
= (u32
)buf
->paddr
+ offset
;
1362 static void free_buf(struct device
*dev
, struct diu_addr
*buf
, u32 size
,
1365 dma_free_coherent(dev
, size
+ bytes_align
, buf
->vaddr
,
1366 buf
->paddr
- buf
->offset
);
1369 static ssize_t
store_monitor(struct device
*device
,
1370 struct device_attribute
*attr
, const char *buf
, size_t count
)
1372 enum fsl_diu_monitor_port old_monitor_port
;
1373 struct fsl_diu_data
*machine_data
=
1374 container_of(attr
, struct fsl_diu_data
, dev_attr
);
1376 old_monitor_port
= machine_data
->monitor_port
;
1377 machine_data
->monitor_port
= fsl_diu_name_to_port(buf
);
1379 if (old_monitor_port
!= machine_data
->monitor_port
) {
1380 /* All AOIs need adjust pixel format
1381 * fsl_diu_set_par only change the pixsel format here
1382 * unlikely to fail. */
1383 fsl_diu_set_par(machine_data
->fsl_diu_info
[0]);
1384 fsl_diu_set_par(machine_data
->fsl_diu_info
[1]);
1385 fsl_diu_set_par(machine_data
->fsl_diu_info
[2]);
1386 fsl_diu_set_par(machine_data
->fsl_diu_info
[3]);
1387 fsl_diu_set_par(machine_data
->fsl_diu_info
[4]);
1392 static ssize_t
show_monitor(struct device
*device
,
1393 struct device_attribute
*attr
, char *buf
)
1395 struct fsl_diu_data
*machine_data
=
1396 container_of(attr
, struct fsl_diu_data
, dev_attr
);
1398 switch (machine_data
->monitor_port
) {
1399 case FSL_DIU_PORT_DVI
:
1400 return sprintf(buf
, "DVI\n");
1401 case FSL_DIU_PORT_LVDS
:
1402 return sprintf(buf
, "Single-link LVDS\n");
1403 case FSL_DIU_PORT_DLVDS
:
1404 return sprintf(buf
, "Dual-link LVDS\n");
1410 static int __devinit
fsl_diu_probe(struct platform_device
*pdev
)
1412 struct device_node
*np
= pdev
->dev
.of_node
;
1413 struct mfb_info
*mfbi
;
1414 phys_addr_t dummy_ad_addr
= 0;
1415 int ret
, i
, error
= 0;
1416 struct fsl_diu_data
*machine_data
;
1419 machine_data
= kzalloc(sizeof(struct fsl_diu_data
), GFP_KERNEL
);
1423 for (i
= 0; i
< ARRAY_SIZE(machine_data
->fsl_diu_info
); i
++) {
1424 machine_data
->fsl_diu_info
[i
] =
1425 framebuffer_alloc(sizeof(struct mfb_info
), &pdev
->dev
);
1426 if (!machine_data
->fsl_diu_info
[i
]) {
1427 dev_err(&pdev
->dev
, "cannot allocate memory\n");
1431 mfbi
= machine_data
->fsl_diu_info
[i
]->par
;
1432 memcpy(mfbi
, &mfb_template
[i
], sizeof(struct mfb_info
));
1433 mfbi
->parent
= machine_data
;
1435 if (mfbi
->index
== 0) {
1440 prop
= of_get_property(np
, "edid", &len
);
1441 if (prop
&& len
== EDID_LENGTH
)
1442 mfbi
->edid_data
= kmemdup(prop
, EDID_LENGTH
,
1447 dr
.diu_reg
= of_iomap(np
, 0);
1449 dev_err(&pdev
->dev
, "cannot map DIU registers\n");
1454 diu_mode
= in_be32(&dr
.diu_reg
->diu_mode
);
1455 if (diu_mode
!= MFB_MODE1
)
1456 out_be32(&dr
.diu_reg
->diu_mode
, 0); /* disable DIU */
1458 /* Get the IRQ of the DIU */
1459 machine_data
->irq
= irq_of_parse_and_map(np
, 0);
1461 if (!machine_data
->irq
) {
1462 dev_err(&pdev
->dev
, "could not get DIU IRQ\n");
1466 machine_data
->monitor_port
= monitor_port
;
1468 /* Area descriptor memory pool aligns to 64-bit boundary */
1469 if (allocate_buf(&pdev
->dev
, &pool
.ad
,
1470 sizeof(struct diu_ad
) * FSL_AOI_NUM
, 8))
1473 /* Get memory for Gamma Table - 32-byte aligned memory */
1474 if (allocate_buf(&pdev
->dev
, &pool
.gamma
, 768, 32)) {
1479 /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
1480 if (allocate_buf(&pdev
->dev
, &pool
.cursor
, MAX_CURS
* MAX_CURS
* 2,
1486 i
= ARRAY_SIZE(machine_data
->fsl_diu_info
);
1487 machine_data
->dummy_ad
= (struct diu_ad
*)
1488 ((u32
)pool
.ad
.vaddr
+ pool
.ad
.offset
) + i
;
1489 machine_data
->dummy_ad
->paddr
= pool
.ad
.paddr
+
1490 i
* sizeof(struct diu_ad
);
1491 machine_data
->dummy_aoi_virt
= fsl_diu_alloc(64, &dummy_ad_addr
);
1492 if (!machine_data
->dummy_aoi_virt
) {
1496 machine_data
->dummy_ad
->addr
= cpu_to_le32(dummy_ad_addr
);
1497 machine_data
->dummy_ad
->pix_fmt
= 0x88882317;
1498 machine_data
->dummy_ad
->src_size_g_alpha
= cpu_to_le32((4 << 12) | 4);
1499 machine_data
->dummy_ad
->aoi_size
= cpu_to_le32((4 << 16) | 2);
1500 machine_data
->dummy_ad
->offset_xyi
= 0;
1501 machine_data
->dummy_ad
->offset_xyd
= 0;
1502 machine_data
->dummy_ad
->next_ad
= 0;
1505 * Let DIU display splash screen if it was pre-initialized
1506 * by the bootloader, set dummy area descriptor otherwise.
1508 if (diu_mode
!= MFB_MODE1
)
1509 out_be32(&dr
.diu_reg
->desc
[0], machine_data
->dummy_ad
->paddr
);
1511 out_be32(&dr
.diu_reg
->desc
[1], machine_data
->dummy_ad
->paddr
);
1512 out_be32(&dr
.diu_reg
->desc
[2], machine_data
->dummy_ad
->paddr
);
1514 for (i
= 0; i
< ARRAY_SIZE(machine_data
->fsl_diu_info
); i
++) {
1515 machine_data
->fsl_diu_info
[i
]->fix
.smem_start
= 0;
1516 mfbi
= machine_data
->fsl_diu_info
[i
]->par
;
1517 mfbi
->ad
= (struct diu_ad
*)((u32
)pool
.ad
.vaddr
1518 + pool
.ad
.offset
) + i
;
1519 mfbi
->ad
->paddr
= pool
.ad
.paddr
+ i
* sizeof(struct diu_ad
);
1520 ret
= install_fb(machine_data
->fsl_diu_info
[i
]);
1522 dev_err(&pdev
->dev
, "could not register fb %d\n", i
);
1527 if (request_irq_local(machine_data
->irq
)) {
1528 dev_err(&pdev
->dev
, "could not claim irq\n");
1532 sysfs_attr_init(&machine_data
->dev_attr
.attr
);
1533 machine_data
->dev_attr
.attr
.name
= "monitor";
1534 machine_data
->dev_attr
.attr
.mode
= S_IRUGO
|S_IWUSR
;
1535 machine_data
->dev_attr
.show
= show_monitor
;
1536 machine_data
->dev_attr
.store
= store_monitor
;
1537 error
= device_create_file(machine_data
->fsl_diu_info
[0]->dev
,
1538 &machine_data
->dev_attr
);
1540 dev_err(&pdev
->dev
, "could not create sysfs file %s\n",
1541 machine_data
->dev_attr
.attr
.name
);
1544 dev_set_drvdata(&pdev
->dev
, machine_data
);
1548 for (i
= ARRAY_SIZE(machine_data
->fsl_diu_info
);
1550 uninstall_fb(machine_data
->fsl_diu_info
[i
- 1]);
1552 free_buf(&pdev
->dev
, &pool
.ad
,
1553 sizeof(struct diu_ad
) * FSL_AOI_NUM
, 8);
1554 if (pool
.gamma
.vaddr
)
1555 free_buf(&pdev
->dev
, &pool
.gamma
, 768, 32);
1556 if (pool
.cursor
.vaddr
)
1557 free_buf(&pdev
->dev
, &pool
.cursor
, MAX_CURS
* MAX_CURS
* 2,
1559 if (machine_data
->dummy_aoi_virt
)
1560 fsl_diu_free(machine_data
->dummy_aoi_virt
, 64);
1561 iounmap(dr
.diu_reg
);
1564 for (i
= 0; i
< ARRAY_SIZE(machine_data
->fsl_diu_info
); i
++)
1565 if (machine_data
->fsl_diu_info
[i
])
1566 framebuffer_release(machine_data
->fsl_diu_info
[i
]);
1567 kfree(machine_data
);
1572 static int fsl_diu_remove(struct platform_device
*pdev
)
1574 struct fsl_diu_data
*machine_data
;
1577 machine_data
= dev_get_drvdata(&pdev
->dev
);
1578 disable_lcdc(machine_data
->fsl_diu_info
[0]);
1579 free_irq_local(machine_data
->irq
);
1580 for (i
= ARRAY_SIZE(machine_data
->fsl_diu_info
); i
> 0; i
--)
1581 uninstall_fb(machine_data
->fsl_diu_info
[i
- 1]);
1583 free_buf(&pdev
->dev
, &pool
.ad
,
1584 sizeof(struct diu_ad
) * FSL_AOI_NUM
, 8);
1585 if (pool
.gamma
.vaddr
)
1586 free_buf(&pdev
->dev
, &pool
.gamma
, 768, 32);
1587 if (pool
.cursor
.vaddr
)
1588 free_buf(&pdev
->dev
, &pool
.cursor
, MAX_CURS
* MAX_CURS
* 2, 32);
1589 if (machine_data
->dummy_aoi_virt
)
1590 fsl_diu_free(machine_data
->dummy_aoi_virt
, 64);
1591 iounmap(dr
.diu_reg
);
1592 for (i
= 0; i
< ARRAY_SIZE(machine_data
->fsl_diu_info
); i
++)
1593 if (machine_data
->fsl_diu_info
[i
])
1594 framebuffer_release(machine_data
->fsl_diu_info
[i
]);
1595 kfree(machine_data
);
1601 static int __init
fsl_diu_setup(char *options
)
1606 if (!options
|| !*options
)
1609 while ((opt
= strsep(&options
, ",")) != NULL
) {
1612 if (!strncmp(opt
, "monitor=", 8)) {
1613 monitor_port
= fsl_diu_name_to_port(opt
+ 8);
1614 } else if (!strncmp(opt
, "bpp=", 4)) {
1615 if (!strict_strtoul(opt
+ 4, 10, &val
))
1625 static struct of_device_id fsl_diu_match
[] = {
1626 #ifdef CONFIG_PPC_MPC512x
1628 .compatible
= "fsl,mpc5121-diu",
1632 .compatible
= "fsl,diu",
1636 MODULE_DEVICE_TABLE(of
, fsl_diu_match
);
1638 static struct platform_driver fsl_diu_driver
= {
1641 .owner
= THIS_MODULE
,
1642 .of_match_table
= fsl_diu_match
,
1644 .probe
= fsl_diu_probe
,
1645 .remove
= fsl_diu_remove
,
1646 .suspend
= fsl_diu_suspend
,
1647 .resume
= fsl_diu_resume
,
1650 static int __init
fsl_diu_init(void)
1652 #ifdef CONFIG_NOT_COHERENT_CACHE
1653 struct device_node
*np
;
1661 * For kernel boot options (in 'video=xxxfb:<options>' format)
1663 if (fb_get_options("fslfb", &option
))
1665 fsl_diu_setup(option
);
1667 monitor_port
= fsl_diu_name_to_port(monitor_string
);
1669 pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
1671 #ifdef CONFIG_NOT_COHERENT_CACHE
1672 np
= of_find_node_by_type(NULL
, "cpu");
1674 pr_err("fsl-diu-fb: can't find 'cpu' device node\n");
1678 prop
= of_get_property(np
, "d-cache-size", NULL
);
1680 pr_err("fsl-diu-fb: missing 'd-cache-size' property' "
1687 * Freescale PLRU requires 13/8 times the cache size to do a proper
1688 * displacement flush
1690 coherence_data_size
= be32_to_cpup(prop
) * 13;
1691 coherence_data_size
/= 8;
1693 prop
= of_get_property(np
, "d-cache-line-size", NULL
);
1695 pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
1700 d_cache_line_size
= be32_to_cpup(prop
);
1703 coherence_data
= vmalloc(coherence_data_size
);
1704 if (!coherence_data
)
1708 ret
= platform_driver_register(&fsl_diu_driver
);
1710 pr_err("fsl-diu-fb: failed to register platform driver\n");
1711 #if defined(CONFIG_NOT_COHERENT_CACHE)
1712 vfree(coherence_data
);
1714 iounmap(dr
.diu_reg
);
1719 static void __exit
fsl_diu_exit(void)
1721 platform_driver_unregister(&fsl_diu_driver
);
1722 #if defined(CONFIG_NOT_COHERENT_CACHE)
1723 vfree(coherence_data
);
1727 module_init(fsl_diu_init
);
1728 module_exit(fsl_diu_exit
);
1730 MODULE_AUTHOR("York Sun <yorksun@freescale.com>");
1731 MODULE_DESCRIPTION("Freescale DIU framebuffer driver");
1732 MODULE_LICENSE("GPL");
1734 module_param_named(mode
, fb_mode
, charp
, 0);
1735 MODULE_PARM_DESC(mode
,
1736 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
1737 module_param_named(bpp
, default_bpp
, ulong
, 0);
1738 MODULE_PARM_DESC(bpp
, "Specify bit-per-pixel if not specified in 'mode'");
1739 module_param_named(monitor
, monitor_string
, charp
, 0);
1740 MODULE_PARM_DESC(monitor
, "Specify the monitor port "
1741 "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");