2 * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
15 * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
21 * @brief MXC Frame buffer driver for SDC
23 * @ingroup Framebuffer
29 #include <linux/clk.h>
30 #include <linux/console.h>
31 #include <linux/delay.h>
32 #include <linux/dma-mapping.h>
33 #include <linux/errno.h>
35 #include <linux/fsl_devices.h>
36 #include <linux/init.h>
37 #include <linux/interrupt.h>
39 #include <linux/ioport.h>
40 #include <linux/ipu.h>
41 #include <linux/ipu-v3.h>
42 #include <linux/kernel.h>
43 #include <linux/module.h>
44 #include <linux/mxcfb.h>
45 #include <linux/of_device.h>
46 #include <linux/platform_device.h>
47 #include <linux/sched.h>
48 #include <linux/slab.h>
49 #include <linux/string.h>
50 #include <linux/uaccess.h>
51 #include <video/of_display_timing.h>
52 #include <video/of_videomode.h>
53 #include <video/videomode.h>
54 #include "mxc_dispdrv.h"
59 #define MXCFB_NAME "mxc_sdc_fb"
61 /* Display port number */
62 #define MXCFB_PORT_NUM 2
64 * Structure containing the MXC specific framebuffer information.
79 dma_addr_t alpha_phy_addr0;
80 dma_addr_t alpha_phy_addr1;
81 void *alpha_virt_addr0;
82 void *alpha_virt_addr1;
83 uint32_t alpha_mem_len;
85 uint32_t ipu_ch_nf_irq;
86 uint32_t ipu_alp_ch_irq;
88 uint32_t cur_ipu_alpha_buf;
90 u32 pseudo_palette[16];
92 enum display_flags disp_flags;
93 struct completion flip_complete;
94 struct completion alpha_flip_complete;
95 struct completion vsync_complete;
98 struct fb_info *ovfbi;
100 struct mxc_dispdrv_handle *dispdrv;
102 struct fb_var_screeninfo cur_var;
108 struct fb_bitfield red;
109 struct fb_bitfield green;
110 struct fb_bitfield blue;
111 struct fb_bitfield transp;
114 static const struct mxcfb_pfmt mxcfb_pfmts[] = {
115 /* pixel bpp red green blue transp */
116 {IPU_PIX_FMT_RGB565, 16, {11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, { 0, 0, 0} },
117 {IPU_PIX_FMT_RGB24, 24, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, { 0, 0, 0} },
118 {IPU_PIX_FMT_BGR24, 24, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0} },
119 {IPU_PIX_FMT_RGB32, 32, { 0, 8, 0}, { 8, 8, 0}, {16, 8, 0}, {24, 8, 0} },
120 {IPU_PIX_FMT_BGR32, 32, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {24, 8, 0} },
121 {IPU_PIX_FMT_ABGR32, 32, {24, 8, 0}, {16, 8, 0}, { 8, 8, 0}, { 0, 8, 0} },
124 struct mxcfb_alloc_list {
125 struct list_head list;
138 static bool g_dp_in_use[2];
139 LIST_HEAD(fb_alloc_list);
141 /* Return default standard(RGB) pixel format */
142 static uint32_t bpp_to_pixfmt(int bpp)
148 pixfmt = IPU_PIX_FMT_BGR24;
151 pixfmt = IPU_PIX_FMT_BGR32;
154 pixfmt = IPU_PIX_FMT_RGB565;
160 static inline int bitfield_is_equal(struct fb_bitfield f1,
161 struct fb_bitfield f2)
163 return !memcmp(&f1, &f2, sizeof(f1));
166 static int pixfmt_to_var(uint32_t pixfmt, struct fb_var_screeninfo *var)
170 for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
171 if (pixfmt == mxcfb_pfmts[i].fb_pix_fmt) {
172 var->red = mxcfb_pfmts[i].red;
173 var->green = mxcfb_pfmts[i].green;
174 var->blue = mxcfb_pfmts[i].blue;
175 var->transp = mxcfb_pfmts[i].transp;
176 var->bits_per_pixel = mxcfb_pfmts[i].bpp;
184 static int bpp_to_var(int bpp, struct fb_var_screeninfo *var)
188 pixfmt = bpp_to_pixfmt(bpp);
190 return pixfmt_to_var(pixfmt, var);
195 static int check_var_pixfmt(struct fb_var_screeninfo *var)
199 for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
200 if (bitfield_is_equal(var->red, mxcfb_pfmts[i].red) &&
201 bitfield_is_equal(var->green, mxcfb_pfmts[i].green) &&
202 bitfield_is_equal(var->blue, mxcfb_pfmts[i].blue) &&
203 bitfield_is_equal(var->transp, mxcfb_pfmts[i].transp) &&
204 var->bits_per_pixel == mxcfb_pfmts[i].bpp) {
212 static uint32_t fbi_to_pixfmt(struct fb_info *fbi)
218 return fbi->var.nonstd;
220 for (i = 0; i < ARRAY_SIZE(mxcfb_pfmts); i++) {
221 if (bitfield_is_equal(fbi->var.red, mxcfb_pfmts[i].red) &&
222 bitfield_is_equal(fbi->var.green, mxcfb_pfmts[i].green) &&
223 bitfield_is_equal(fbi->var.blue, mxcfb_pfmts[i].blue) &&
224 bitfield_is_equal(fbi->var.transp, mxcfb_pfmts[i].transp)) {
225 pixfmt = mxcfb_pfmts[i].fb_pix_fmt;
231 dev_err(fbi->device, "cannot get pixel format\n");
236 static struct fb_info *found_registered_fb(ipu_channel_t ipu_ch, int ipu_id)
239 struct mxcfb_info *mxc_fbi;
240 struct fb_info *fbi = NULL;
242 for (i = 0; i < num_registered_fb; i++) {
243 mxc_fbi = registered_fb[i]->par;
245 if ((mxc_fbi->ipu_ch == ipu_ch) &&
246 (mxc_fbi->ipu_id == ipu_id)) {
247 fbi = registered_fb[i];
254 static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id);
255 static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id);
256 static int mxcfb_blank(int blank, struct fb_info *info);
257 static int mxcfb_map_video_memory(struct fb_info *fbi);
258 static int mxcfb_unmap_video_memory(struct fb_info *fbi);
261 * Set fixed framebuffer parameters based on variable settings.
263 * @param info framebuffer information pointer
265 static int mxcfb_set_fix(struct fb_info *info)
267 struct fb_fix_screeninfo *fix = &info->fix;
268 struct fb_var_screeninfo *var = &info->var;
270 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
272 fix->type = FB_TYPE_PACKED_PIXELS;
273 fix->accel = FB_ACCEL_NONE;
274 fix->visual = FB_VISUAL_TRUECOLOR;
282 static int _setup_disp_channel1(struct fb_info *fbi)
284 ipu_channel_params_t params;
285 struct mxcfb_info *mxc_fbi = fbi->par;
287 memset(¶ms, 0, sizeof(params));
289 if (mxc_fbi->ipu_ch == MEM_DC_SYNC) {
290 params.mem_dc_sync.di = mxc_fbi->ipu_di;
291 if (fbi->var.vmode & FB_VMODE_INTERLACED)
292 params.mem_dc_sync.interlaced = true;
293 params.mem_dc_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
294 params.mem_dc_sync.in_pixel_fmt = fbi_to_pixfmt(fbi);
296 params.mem_dp_bg_sync.di = mxc_fbi->ipu_di;
297 if (fbi->var.vmode & FB_VMODE_INTERLACED)
298 params.mem_dp_bg_sync.interlaced = true;
299 params.mem_dp_bg_sync.out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
300 params.mem_dp_bg_sync.in_pixel_fmt = fbi_to_pixfmt(fbi);
301 if (mxc_fbi->alpha_chan_en)
302 params.mem_dp_bg_sync.alpha_chan_en = true;
304 ipu_init_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, ¶ms);
309 static int _setup_disp_channel2(struct fb_info *fbi)
312 struct mxcfb_info *mxc_fbi = fbi->par;
315 unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
317 switch (fbi_to_pixfmt(fbi)) {
318 case IPU_PIX_FMT_YUV420P2:
319 case IPU_PIX_FMT_YVU420P:
320 case IPU_PIX_FMT_NV12:
321 case IPU_PIX_FMT_YUV422P:
322 case IPU_PIX_FMT_YVU422P:
323 case IPU_PIX_FMT_YUV420P:
324 case IPU_PIX_FMT_YUV444P:
325 fb_stride = fbi->var.xres_virtual;
328 fb_stride = fbi->fix.line_length;
331 base = fbi->fix.smem_start;
332 fr_xoff = fbi->var.xoffset;
333 fr_w = fbi->var.xres_virtual;
334 if (!(fbi->var.vmode & FB_VMODE_YWRAP)) {
335 dev_dbg(fbi->device, "Y wrap disabled\n");
336 fr_yoff = fbi->var.yoffset % fbi->var.yres;
337 fr_h = fbi->var.yres;
338 base += fbi->fix.line_length * fbi->var.yres *
339 (fbi->var.yoffset / fbi->var.yres);
341 dev_dbg(fbi->device, "Y wrap enabled\n");
342 fr_yoff = fbi->var.yoffset;
343 fr_h = fbi->var.yres_virtual;
345 base += fr_yoff * fb_stride + fr_xoff;
347 mxc_fbi->cur_ipu_buf = 2;
348 init_completion(&mxc_fbi->flip_complete);
350 * We don't need to wait for vsync at the first time
351 * we do pan display after fb is initialized, as IPU will
352 * switch to the newly selected buffer automatically,
353 * so we call complete() for both mxc_fbi->flip_complete
354 * and mxc_fbi->alpha_flip_complete.
356 complete(&mxc_fbi->flip_complete);
357 if (mxc_fbi->alpha_chan_en) {
358 mxc_fbi->cur_ipu_alpha_buf = 1;
359 init_completion(&mxc_fbi->alpha_flip_complete);
360 complete(&mxc_fbi->alpha_flip_complete);
363 retval = ipu_init_channel_buffer(mxc_fbi->ipu,
364 mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
366 fbi->var.xres, fbi->var.yres,
371 fbi->var.accel_flags &
372 FB_ACCEL_DOUBLE_FLAG ? 0 : base,
376 "ipu_init_channel_buffer error %d\n", retval);
380 /* update u/v offset */
381 ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
391 if (mxc_fbi->alpha_chan_en) {
392 retval = ipu_init_channel_buffer(mxc_fbi->ipu,
396 fbi->var.xres, fbi->var.yres,
399 mxc_fbi->alpha_phy_addr1,
400 mxc_fbi->alpha_phy_addr0,
405 "ipu_init_channel_buffer error %d\n", retval);
413 static bool mxcfb_need_to_set_par(struct fb_info *fbi)
415 struct mxcfb_info *mxc_fbi = fbi->par;
417 if ((fbi->var.activate & FB_ACTIVATE_FORCE) &&
418 (fbi->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
422 * Ignore xoffset and yoffset update,
423 * because pan display handles this case.
425 mxc_fbi->cur_var.xoffset = fbi->var.xoffset;
426 mxc_fbi->cur_var.yoffset = fbi->var.yoffset;
428 return !!memcmp(&mxc_fbi->cur_var, &fbi->var,
429 sizeof(struct fb_var_screeninfo));
433 * Set framebuffer parameters and change the operating mode.
435 * @param info framebuffer information pointer
437 static int mxcfb_set_par(struct fb_info *fbi)
440 u32 mem_len, alpha_mem_len;
441 ipu_di_signal_cfg_t sig_cfg;
442 struct mxcfb_info *mxc_fbi = fbi->par;
444 int16_t ov_pos_x = 0, ov_pos_y = 0;
446 struct mxcfb_info *mxc_fbi_fg = NULL;
447 bool ovfbi_enable = false;
449 if (ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi)) &&
450 mxc_fbi->alpha_chan_en) {
452 "Bad pixel format for graphics plane fb\n");
457 mxc_fbi_fg = mxc_fbi->ovfbi->par;
459 if (mxc_fbi->ovfbi && mxc_fbi_fg)
460 if (mxc_fbi_fg->next_blank == FB_BLANK_UNBLANK)
463 if (!mxcfb_need_to_set_par(fbi))
466 dev_dbg(fbi->device, "Reconfiguring framebuffer\n");
468 if (fbi->var.xres == 0 || fbi->var.yres == 0)
472 ov_pos_ret = ipu_disp_get_window_pos(
473 mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
474 &ov_pos_x, &ov_pos_y);
476 dev_err(fbi->device, "Get overlay pos failed, dispdrv:%s.\n",
477 mxc_fbi->dispdrv->drv->name);
479 ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
480 ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_irq);
481 ipu_clear_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
482 ipu_disable_irq(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch_nf_irq);
483 ipu_disable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch, true);
484 ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
487 ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
488 ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
489 ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
490 ipu_disable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
491 ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
492 ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
495 * Disable IPU hsp clock if it is enabled for an
496 * additional time in ipu common driver.
498 if (mxc_fbi->first_set_par && mxc_fbi->late_init)
499 ipu_disable_hsp_clk(mxc_fbi->ipu);
503 mem_len = fbi->var.yres_virtual * fbi->fix.line_length;
504 if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) {
505 if (fbi->fix.smem_start)
506 mxcfb_unmap_video_memory(fbi);
508 if (mxcfb_map_video_memory(fbi) < 0)
512 if (mxc_fbi->first_set_par) {
514 * Clear the screen in case uboot fb pixel format is not
515 * the same to kernel fb pixel format.
517 if (mxc_fbi->late_init)
518 memset(fbi->screen_base, 0, fbi->fix.smem_len);
520 mxc_fbi->first_set_par = false;
523 if (mxc_fbi->alpha_chan_en) {
524 alpha_mem_len = fbi->var.xres * fbi->var.yres;
525 if ((!mxc_fbi->alpha_phy_addr0 && !mxc_fbi->alpha_phy_addr1) ||
526 (alpha_mem_len > mxc_fbi->alpha_mem_len)) {
527 if (mxc_fbi->alpha_phy_addr0)
528 dma_free_coherent(fbi->device,
529 mxc_fbi->alpha_mem_len,
530 mxc_fbi->alpha_virt_addr0,
531 mxc_fbi->alpha_phy_addr0);
532 if (mxc_fbi->alpha_phy_addr1)
533 dma_free_coherent(fbi->device,
534 mxc_fbi->alpha_mem_len,
535 mxc_fbi->alpha_virt_addr1,
536 mxc_fbi->alpha_phy_addr1);
538 mxc_fbi->alpha_virt_addr0 =
539 dma_alloc_coherent(fbi->device,
541 &mxc_fbi->alpha_phy_addr0,
542 GFP_DMA | GFP_KERNEL);
544 mxc_fbi->alpha_virt_addr1 =
545 dma_alloc_coherent(fbi->device,
547 &mxc_fbi->alpha_phy_addr1,
548 GFP_DMA | GFP_KERNEL);
549 if (mxc_fbi->alpha_virt_addr0 == NULL ||
550 mxc_fbi->alpha_virt_addr1 == NULL) {
551 dev_err(fbi->device, "mxcfb: dma alloc for"
552 " alpha buffer failed.\n");
553 if (mxc_fbi->alpha_virt_addr0)
554 dma_free_coherent(fbi->device,
555 mxc_fbi->alpha_mem_len,
556 mxc_fbi->alpha_virt_addr0,
557 mxc_fbi->alpha_phy_addr0);
558 if (mxc_fbi->alpha_virt_addr1)
559 dma_free_coherent(fbi->device,
560 mxc_fbi->alpha_mem_len,
561 mxc_fbi->alpha_virt_addr1,
562 mxc_fbi->alpha_phy_addr1);
565 mxc_fbi->alpha_mem_len = alpha_mem_len;
569 if (mxc_fbi->next_blank != FB_BLANK_UNBLANK)
572 if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->setup) {
573 retval = mxc_fbi->dispdrv->drv->setup(mxc_fbi->dispdrv, fbi);
575 dev_err(fbi->device, "setup error, dispdrv: %s (%d)\n",
576 mxc_fbi->dispdrv->drv->name, retval);
581 _setup_disp_channel1(fbi);
583 _setup_disp_channel1(mxc_fbi->ovfbi);
585 if (!mxc_fbi->overlay) {
586 uint32_t out_pixel_fmt;
588 memset(&sig_cfg, 0, sizeof(sig_cfg));
589 if (fbi->var.vmode & FB_VMODE_INTERLACED)
590 sig_cfg.interlaced = true;
591 out_pixel_fmt = mxc_fbi->ipu_di_pix_fmt;
592 if (fbi->var.vmode & FB_VMODE_ODD_FLD_FIRST) /* PAL */
593 sig_cfg.odd_field_first = true;
594 if (mxc_fbi->ipu_int_clk)
595 sig_cfg.int_clk = true;
596 if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT)
597 sig_cfg.Hsync_pol = true;
598 if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT)
599 sig_cfg.Vsync_pol = true;
600 if (mxc_fbi->disp_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
601 sig_cfg.clk_pol = true;
602 if (fbi->var.sync & FB_SYNC_DATA_INVERT)
603 sig_cfg.data_pol = true;
604 if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT))
605 sig_cfg.enable_pol = true;
606 if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
607 sig_cfg.clkidle_en = true;
609 dev_dbg(fbi->device, "pixclock = %ul Hz\n",
610 (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
612 if (ipu_init_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di,
613 (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
614 fbi->var.xres, fbi->var.yres,
616 fbi->var.left_margin,
618 fbi->var.right_margin,
619 fbi->var.upper_margin,
621 fbi->var.lower_margin,
624 "mxcfb: Error initializing panel.\n");
629 (struct fb_videomode *)fb_match_mode(&fbi->var,
632 ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, 0, 0);
635 retval = _setup_disp_channel2(fbi);
637 ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
643 ipu_disp_set_window_pos(
644 mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch,
646 retval = _setup_disp_channel2(mxc_fbi->ovfbi);
648 ipu_uninit_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
649 ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
654 ipu_enable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
656 ipu_enable_channel(mxc_fbi_fg->ipu, mxc_fbi_fg->ipu_ch);
658 if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->enable) {
659 retval = mxc_fbi->dispdrv->drv->enable(mxc_fbi->dispdrv);
661 dev_err(fbi->device, "enable error, dispdrv: %s (%d)\n",
662 mxc_fbi->dispdrv->drv->name, retval);
667 mxc_fbi->cur_var = fbi->var;
672 static int _swap_channels(struct fb_info *fbi_from,
673 struct fb_info *fbi_to, bool both_on)
676 ipu_channel_t old_ch;
677 struct fb_info *ovfbi;
678 struct mxcfb_info *mxc_fbi_from = fbi_from->par;
679 struct mxcfb_info *mxc_fbi_to = fbi_to->par;
682 ipu_disable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch, true);
683 ipu_uninit_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
686 /* switch the mxc fbi parameters */
687 old_ch = mxc_fbi_from->ipu_ch;
688 mxc_fbi_from->ipu_ch = mxc_fbi_to->ipu_ch;
689 mxc_fbi_to->ipu_ch = old_ch;
690 tmp = mxc_fbi_from->ipu_ch_irq;
691 mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
692 mxc_fbi_to->ipu_ch_irq = tmp;
693 tmp = mxc_fbi_from->ipu_ch_nf_irq;
694 mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
695 mxc_fbi_to->ipu_ch_nf_irq = tmp;
696 ovfbi = mxc_fbi_from->ovfbi;
697 mxc_fbi_from->ovfbi = mxc_fbi_to->ovfbi;
698 mxc_fbi_to->ovfbi = ovfbi;
700 _setup_disp_channel1(fbi_from);
701 retval = _setup_disp_channel2(fbi_from);
705 /* switch between dp and dc, disable old idmac, enable new idmac */
706 retval = ipu_swap_channel(mxc_fbi_from->ipu, old_ch, mxc_fbi_from->ipu_ch);
707 ipu_uninit_channel(mxc_fbi_from->ipu, old_ch);
710 _setup_disp_channel1(fbi_to);
711 retval = _setup_disp_channel2(fbi_to);
714 ipu_enable_channel(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch);
720 static int swap_channels(struct fb_info *fbi_from)
725 struct mxcfb_info *mxc_fbi_from = fbi_from->par;
726 struct fb_info *fbi_to = NULL;
727 struct mxcfb_info *mxc_fbi_to;
729 /* what's the target channel? */
730 if (mxc_fbi_from->ipu_ch == MEM_BG_SYNC)
735 fbi_to = found_registered_fb(ch_to, mxc_fbi_from->ipu_id);
738 mxc_fbi_to = fbi_to->par;
740 ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
741 ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
742 ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq, fbi_from);
743 ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq, fbi_to);
744 ipu_clear_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
745 ipu_clear_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
746 ipu_free_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq, fbi_from);
747 ipu_free_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq, fbi_to);
749 if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
750 if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
755 if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
758 swap_mode = BOTH_OFF;
763 /* disable target->switch src->enable target */
764 _swap_channels(fbi_from, fbi_to, true);
767 /* just switch src */
768 _swap_channels(fbi_from, fbi_to, false);
771 /* just switch target */
772 _swap_channels(fbi_to, fbi_from, false);
775 /* switch directly, no more need to do */
776 mxc_fbi_to->ipu_ch = mxc_fbi_from->ipu_ch;
777 mxc_fbi_from->ipu_ch = ch_to;
778 i = mxc_fbi_from->ipu_ch_irq;
779 mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
780 mxc_fbi_to->ipu_ch_irq = i;
781 i = mxc_fbi_from->ipu_ch_nf_irq;
782 mxc_fbi_from->ipu_ch_nf_irq = mxc_fbi_to->ipu_ch_nf_irq;
783 mxc_fbi_to->ipu_ch_nf_irq = i;
789 if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq,
790 mxcfb_irq_handler, IPU_IRQF_ONESHOT,
791 MXCFB_NAME, fbi_from) != 0) {
792 dev_err(fbi_from->device, "Error registering irq %d\n",
793 mxc_fbi_from->ipu_ch_irq);
796 ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_irq);
797 if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq,
798 mxcfb_irq_handler, IPU_IRQF_ONESHOT,
799 MXCFB_NAME, fbi_to) != 0) {
800 dev_err(fbi_to->device, "Error registering irq %d\n",
801 mxc_fbi_to->ipu_ch_irq);
804 ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_irq);
805 if (ipu_request_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq,
806 mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
807 MXCFB_NAME, fbi_from) != 0) {
808 dev_err(fbi_from->device, "Error registering irq %d\n",
809 mxc_fbi_from->ipu_ch_nf_irq);
812 ipu_disable_irq(mxc_fbi_from->ipu, mxc_fbi_from->ipu_ch_nf_irq);
813 if (ipu_request_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq,
814 mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT,
815 MXCFB_NAME, fbi_to) != 0) {
816 dev_err(fbi_to->device, "Error registering irq %d\n",
817 mxc_fbi_to->ipu_ch_nf_irq);
820 ipu_disable_irq(mxc_fbi_to->ipu, mxc_fbi_to->ipu_ch_nf_irq);
826 * Check framebuffer variable parameters and adjust to valid values.
828 * @param var framebuffer variable parameters
830 * @param info framebuffer information pointer
832 static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
836 struct mxcfb_info *mxc_fbi = info->par;
839 if (var->xres == 0 || var->yres == 0)
842 /* fg should not bigger than bg */
843 if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
844 struct fb_info *fbi_tmp;
845 int bg_xres = 0, bg_yres = 0;
846 int16_t pos_x, pos_y;
851 fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
853 bg_xres = fbi_tmp->var.xres;
854 bg_yres = fbi_tmp->var.yres;
857 ipu_disp_get_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch, &pos_x, &pos_y);
859 if ((var->xres + pos_x) > bg_xres)
860 var->xres = bg_xres - pos_x;
861 if ((var->yres + pos_y) > bg_yres)
862 var->yres = bg_yres - pos_y;
865 if (var->rotate > IPU_ROTATE_VERT_FLIP)
866 var->rotate = IPU_ROTATE_NONE;
868 if (var->xres_virtual < var->xres)
869 var->xres_virtual = var->xres;
871 if (var->yres_virtual < var->yres)
872 var->yres_virtual = var->yres * 3;
874 if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&
875 (var->bits_per_pixel != 16) && (var->bits_per_pixel != 12) &&
876 (var->bits_per_pixel != 8))
877 var->bits_per_pixel = 16;
879 if (check_var_pixfmt(var))
880 /* Fall back to default */
881 bpp_to_var(var->bits_per_pixel, var);
883 if (var->pixclock < 1000) {
884 htotal = var->xres + var->right_margin + var->hsync_len +
886 vtotal = var->yres + var->lower_margin + var->vsync_len +
888 var->pixclock = (vtotal * htotal * 6UL) / 100UL;
889 var->pixclock = KHZ2PICOS(var->pixclock);
890 dev_dbg(info->device,
891 "pixclock set for 60Hz refresh = %u ps\n",
902 static inline u_int _chan_to_field(u_int chan, struct fb_bitfield *bf)
905 chan >>= 16 - bf->length;
906 return chan << bf->offset;
909 static int mxcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
910 u_int trans, struct fb_info *fbi)
916 * If greyscale is true, then we convert the RGB value
917 * to greyscale no matter what visual we are using.
919 if (fbi->var.grayscale)
920 red = green = blue = (19595 * red + 38470 * green +
922 switch (fbi->fix.visual) {
923 case FB_VISUAL_TRUECOLOR:
925 * 16-bit True Colour. We encode the RGB value
926 * according to the RGB bitfield information.
929 u32 *pal = fbi->pseudo_palette;
931 val = _chan_to_field(red, &fbi->var.red);
932 val |= _chan_to_field(green, &fbi->var.green);
933 val |= _chan_to_field(blue, &fbi->var.blue);
940 case FB_VISUAL_STATIC_PSEUDOCOLOR:
941 case FB_VISUAL_PSEUDOCOLOR:
949 * Function to handle custom ioctls for MXC framebuffer.
951 * @param inode inode struct
953 * @param file file struct
955 * @param cmd Ioctl command to handle
957 * @param arg User pointer to command arguments
959 * @param fbi framebuffer information pointer
961 static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
964 int __user *argp = (void __user *)arg;
965 struct mxcfb_info *mxc_fbi = fbi->par;
968 case MXCFB_SET_GBL_ALPHA:
970 struct mxcfb_gbl_alpha ga;
972 if (copy_from_user(&ga, argp, sizeof(ga))) {
977 if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
986 mxc_fbi->alpha_chan_en = false;
990 "Set global alpha of %s to %d\n",
991 fbi->fix.id, ga.alpha);
994 case MXCFB_SET_LOC_ALPHA:
996 struct mxcfb_loc_alpha la;
998 ipu_ch_param_bad_alpha_pos(fbi_to_pixfmt(fbi));
1000 if (copy_from_user(&la, argp, sizeof(la))) {
1005 if (la.enable && !la.alpha_in_pixel) {
1006 struct fb_info *fbi_tmp;
1007 ipu_channel_t ipu_ch;
1010 dev_err(fbi->device, "Bad pixel format "
1011 "for graphics plane fb\n");
1016 mxc_fbi->alpha_chan_en = true;
1018 if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
1019 ipu_ch = MEM_BG_SYNC;
1020 else if (mxc_fbi->ipu_ch == MEM_BG_SYNC)
1021 ipu_ch = MEM_FG_SYNC;
1027 fbi_tmp = found_registered_fb(ipu_ch, mxc_fbi->ipu_id);
1029 ((struct mxcfb_info *)(fbi_tmp->par))->alpha_chan_en = false;
1031 mxc_fbi->alpha_chan_en = false;
1033 if (ipu_disp_set_global_alpha(mxc_fbi->ipu,
1035 !(bool)la.enable, 0)) {
1040 fbi->var.activate = (fbi->var.activate & ~FB_ACTIVATE_MASK) |
1041 FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
1044 la.alpha_phy_addr0 = mxc_fbi->alpha_phy_addr0;
1045 la.alpha_phy_addr1 = mxc_fbi->alpha_phy_addr1;
1046 if (copy_to_user(argp, &la, sizeof(la))) {
1052 dev_dbg(fbi->device,
1053 "Enable DP local alpha for %s\n",
1057 case MXCFB_SET_LOC_ALP_BUF:
1060 uint32_t ipu_alp_ch_irq;
1062 if (!(((mxc_fbi->ipu_ch == MEM_FG_SYNC) ||
1063 (mxc_fbi->ipu_ch == MEM_BG_SYNC)) &&
1064 (mxc_fbi->alpha_chan_en))) {
1065 dev_err(fbi->device,
1066 "Should use background or overlay "
1067 "framebuffer to set the alpha buffer "
1072 if (get_user(base, argp))
1075 if (base != mxc_fbi->alpha_phy_addr0 &&
1076 base != mxc_fbi->alpha_phy_addr1) {
1077 dev_err(fbi->device,
1078 "Wrong alpha buffer physical address "
1083 if (mxc_fbi->ipu_ch == MEM_FG_SYNC)
1084 ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
1086 ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
1088 retval = wait_for_completion_timeout(
1089 &mxc_fbi->alpha_flip_complete, HZ/2);
1091 dev_err(fbi->device, "timeout when waiting for alpha flip irq\n");
1092 retval = -ETIMEDOUT;
1096 mxc_fbi->cur_ipu_alpha_buf =
1097 !mxc_fbi->cur_ipu_alpha_buf;
1098 if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1099 IPU_ALPHA_IN_BUFFER,
1103 ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1104 IPU_ALPHA_IN_BUFFER,
1105 mxc_fbi->cur_ipu_alpha_buf);
1106 ipu_clear_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
1107 ipu_enable_irq(mxc_fbi->ipu, ipu_alp_ch_irq);
1109 dev_err(fbi->device,
1110 "Error updating %s SDC alpha buf %d "
1111 "to address=0x%08lX\n",
1113 mxc_fbi->cur_ipu_alpha_buf, base);
1117 case MXCFB_SET_CLR_KEY:
1119 struct mxcfb_color_key key;
1120 if (copy_from_user(&key, argp, sizeof(key))) {
1124 retval = ipu_disp_set_color_key(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1127 dev_dbg(fbi->device, "Set color key to 0x%08X\n",
1131 case MXCFB_SET_GAMMA:
1133 struct mxcfb_gamma gamma;
1134 if (copy_from_user(&gamma, argp, sizeof(gamma))) {
1138 retval = ipu_disp_set_gamma_correction(mxc_fbi->ipu,
1145 case MXCFB_WAIT_FOR_VSYNC:
1147 if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
1148 /* BG should poweron */
1149 struct mxcfb_info *bg_mxcfbi = NULL;
1150 struct fb_info *fbi_tmp;
1152 fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
1154 bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
1160 if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK) {
1165 if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK) {
1170 init_completion(&mxc_fbi->vsync_complete);
1171 ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
1172 ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_nf_irq);
1173 retval = wait_for_completion_interruptible_timeout(
1174 &mxc_fbi->vsync_complete, 1 * HZ);
1176 dev_err(fbi->device,
1177 "MXCFB_WAIT_FOR_VSYNC: timeout %d\n",
1180 } else if (retval > 0) {
1188 struct mxcfb_alloc_list *mem;
1190 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
1194 if (get_user(size, argp))
1197 mem->size = PAGE_ALIGN(size);
1199 mem->cpu_addr = dma_alloc_coherent(fbi->device, size,
1202 if (mem->cpu_addr == NULL) {
1207 list_add(&mem->list, &fb_alloc_list);
1209 dev_dbg(fbi->device, "allocated %d bytes @ 0x%08X\n",
1210 mem->size, mem->phy_addr);
1212 if (put_user(mem->phy_addr, argp))
1219 unsigned long offset;
1220 struct mxcfb_alloc_list *mem;
1222 if (get_user(offset, argp))
1226 list_for_each_entry(mem, &fb_alloc_list, list) {
1227 if (mem->phy_addr == offset) {
1228 list_del(&mem->list);
1229 dma_free_coherent(fbi->device,
1241 case MXCFB_SET_OVERLAY_POS:
1243 struct mxcfb_pos pos;
1244 struct fb_info *bg_fbi = NULL;
1245 struct mxcfb_info *bg_mxcfbi = NULL;
1247 if (mxc_fbi->ipu_ch != MEM_FG_SYNC) {
1248 dev_err(fbi->device, "Should use the overlay "
1249 "framebuffer to set the position of "
1250 "the overlay window\n");
1255 if (copy_from_user(&pos, argp, sizeof(pos))) {
1260 bg_fbi = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
1262 bg_mxcfbi = ((struct mxcfb_info *)(bg_fbi->par));
1264 if (bg_fbi == NULL) {
1265 dev_err(fbi->device, "Cannot find the "
1266 "background framebuffer\n");
1271 /* if fb is unblank, check if the pos fit the display */
1272 if (mxc_fbi->cur_blank == FB_BLANK_UNBLANK) {
1273 if (fbi->var.xres + pos.x > bg_fbi->var.xres) {
1274 if (bg_fbi->var.xres < fbi->var.xres)
1277 pos.x = bg_fbi->var.xres - fbi->var.xres;
1279 if (fbi->var.yres + pos.y > bg_fbi->var.yres) {
1280 if (bg_fbi->var.yres < fbi->var.yres)
1283 pos.y = bg_fbi->var.yres - fbi->var.yres;
1287 retval = ipu_disp_set_window_pos(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1290 if (copy_to_user(argp, &pos, sizeof(pos))) {
1296 case MXCFB_GET_FB_IPU_CHAN:
1298 struct mxcfb_info *mxc_fbi =
1299 (struct mxcfb_info *)fbi->par;
1301 if (put_user(mxc_fbi->ipu_ch, argp))
1305 case MXCFB_GET_DIFMT:
1307 struct mxcfb_info *mxc_fbi =
1308 (struct mxcfb_info *)fbi->par;
1310 if (put_user(mxc_fbi->ipu_di_pix_fmt, argp))
1314 case MXCFB_GET_FB_IPU_DI:
1316 struct mxcfb_info *mxc_fbi =
1317 (struct mxcfb_info *)fbi->par;
1319 if (put_user(mxc_fbi->ipu_di, argp))
1323 case MXCFB_GET_FB_BLANK:
1325 struct mxcfb_info *mxc_fbi =
1326 (struct mxcfb_info *)fbi->par;
1328 if (put_user(mxc_fbi->cur_blank, argp))
1332 case MXCFB_SET_DIFMT:
1334 struct mxcfb_info *mxc_fbi =
1335 (struct mxcfb_info *)fbi->par;
1337 if (get_user(mxc_fbi->ipu_di_pix_fmt, argp))
1342 case MXCFB_CSC_UPDATE:
1344 struct mxcfb_csc_matrix csc;
1346 if (copy_from_user(&csc, argp, sizeof(csc)))
1349 if ((mxc_fbi->ipu_ch != MEM_FG_SYNC) &&
1350 (mxc_fbi->ipu_ch != MEM_BG_SYNC) &&
1351 (mxc_fbi->ipu_ch != MEM_BG_ASYNC0))
1353 ipu_set_csc_coefficients(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1364 * Blank the display.
1366 static int mxcfb_blank(int blank, struct fb_info *info)
1368 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par;
1371 dev_dbg(info->device, "blank = %d\n", blank);
1373 if (mxc_fbi->cur_blank == blank)
1376 mxc_fbi->next_blank = blank;
1379 case FB_BLANK_POWERDOWN:
1380 case FB_BLANK_VSYNC_SUSPEND:
1381 case FB_BLANK_HSYNC_SUSPEND:
1382 case FB_BLANK_NORMAL:
1383 if (mxc_fbi->dispdrv && mxc_fbi->dispdrv->drv->disable)
1384 mxc_fbi->dispdrv->drv->disable(mxc_fbi->dispdrv);
1385 ipu_disable_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch, true);
1386 if (mxc_fbi->ipu_di >= 0)
1387 ipu_uninit_sync_panel(mxc_fbi->ipu, mxc_fbi->ipu_di);
1388 ipu_uninit_channel(mxc_fbi->ipu, mxc_fbi->ipu_ch);
1390 case FB_BLANK_UNBLANK:
1391 info->var.activate = (info->var.activate & ~FB_ACTIVATE_MASK) |
1392 FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
1393 ret = mxcfb_set_par(info);
1397 mxc_fbi->cur_blank = blank;
1402 * Pan or Wrap the Display
1404 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1406 * @param var Variable screen buffer information
1407 * @param info Framebuffer information pointer
1410 mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1412 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)info->par,
1413 *mxc_graphic_fbi = NULL;
1415 unsigned int fr_xoff, fr_yoff, fr_w, fr_h;
1416 unsigned long base, active_alpha_phy_addr = 0;
1417 bool loc_alpha_en = false;
1422 /* no pan display during fb blank */
1423 if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
1424 struct mxcfb_info *bg_mxcfbi = NULL;
1425 struct fb_info *fbi_tmp;
1427 fbi_tmp = found_registered_fb(MEM_BG_SYNC, mxc_fbi->ipu_id);
1429 bg_mxcfbi = ((struct mxcfb_info *)(fbi_tmp->par));
1432 if (bg_mxcfbi->cur_blank != FB_BLANK_UNBLANK)
1435 if (mxc_fbi->cur_blank != FB_BLANK_UNBLANK)
1438 y_bottom = var->yoffset;
1440 if (y_bottom > info->var.yres_virtual)
1443 switch (fbi_to_pixfmt(info)) {
1444 case IPU_PIX_FMT_YUV420P2:
1445 case IPU_PIX_FMT_YVU420P:
1446 case IPU_PIX_FMT_NV12:
1447 case IPU_PIX_FMT_YUV422P:
1448 case IPU_PIX_FMT_YVU422P:
1449 case IPU_PIX_FMT_YUV420P:
1450 case IPU_PIX_FMT_YUV444P:
1451 fb_stride = info->var.xres_virtual;
1454 fb_stride = info->fix.line_length;
1457 base = info->fix.smem_start;
1458 fr_xoff = var->xoffset;
1459 fr_w = info->var.xres_virtual;
1460 if (!(var->vmode & FB_VMODE_YWRAP)) {
1461 dev_dbg(info->device, "Y wrap disabled\n");
1462 fr_yoff = var->yoffset % info->var.yres;
1463 fr_h = info->var.yres;
1464 base += info->fix.line_length * info->var.yres *
1465 (var->yoffset / info->var.yres);
1467 dev_dbg(info->device, "Y wrap enabled\n");
1468 fr_yoff = var->yoffset;
1469 fr_h = info->var.yres_virtual;
1471 base += fr_yoff * fb_stride + fr_xoff;
1473 /* Check if DP local alpha is enabled and find the graphic fb */
1474 if (mxc_fbi->ipu_ch == MEM_BG_SYNC || mxc_fbi->ipu_ch == MEM_FG_SYNC) {
1475 for (i = 0; i < num_registered_fb; i++) {
1476 char bg_id[] = "DISP3 BG";
1477 char fg_id[] = "DISP3 FG";
1478 char *idstr = registered_fb[i]->fix.id;
1479 bg_id[4] += mxc_fbi->ipu_id;
1480 fg_id[4] += mxc_fbi->ipu_id;
1481 if ((strcmp(idstr, bg_id) == 0 ||
1482 strcmp(idstr, fg_id) == 0) &&
1483 ((struct mxcfb_info *)
1484 (registered_fb[i]->par))->alpha_chan_en) {
1485 loc_alpha_en = true;
1486 mxc_graphic_fbi = (struct mxcfb_info *)
1487 (registered_fb[i]->par);
1488 active_alpha_phy_addr =
1489 mxc_fbi->cur_ipu_alpha_buf ?
1490 mxc_graphic_fbi->alpha_phy_addr1 :
1491 mxc_graphic_fbi->alpha_phy_addr0;
1492 dev_dbg(info->device, "Updating SDC alpha "
1493 "buf %d address=0x%08lX\n",
1494 !mxc_fbi->cur_ipu_alpha_buf,
1495 active_alpha_phy_addr);
1501 ret = wait_for_completion_timeout(&mxc_fbi->flip_complete, HZ/2);
1503 dev_err(info->device, "timeout when waiting for flip irq\n");
1507 ++mxc_fbi->cur_ipu_buf;
1508 mxc_fbi->cur_ipu_buf %= 3;
1509 mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
1511 dev_dbg(info->device, "Updating SDC %s buf %d address=0x%08lX\n",
1512 info->fix.id, mxc_fbi->cur_ipu_buf, base);
1514 if (ipu_update_channel_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
1515 mxc_fbi->cur_ipu_buf, base) == 0) {
1516 /* Update the DP local alpha buffer only for graphic plane */
1517 if (loc_alpha_en && mxc_graphic_fbi == mxc_fbi &&
1518 ipu_update_channel_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
1519 IPU_ALPHA_IN_BUFFER,
1520 mxc_fbi->cur_ipu_alpha_buf,
1521 active_alpha_phy_addr) == 0) {
1522 ipu_select_buffer(mxc_graphic_fbi->ipu, mxc_graphic_fbi->ipu_ch,
1523 IPU_ALPHA_IN_BUFFER,
1524 mxc_fbi->cur_ipu_alpha_buf);
1527 /* update u/v offset */
1528 ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1530 fbi_to_pixfmt(info),
1538 ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER,
1539 mxc_fbi->cur_ipu_buf);
1540 ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
1541 ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
1543 dev_err(info->device,
1544 "Error updating SDC buf %d to address=0x%08lX, "
1545 "current buf %d, buf0 ready %d, buf1 ready %d, "
1546 "buf2 ready %d\n", mxc_fbi->cur_ipu_buf, base,
1547 ipu_get_cur_buffer_idx(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1549 ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1550 IPU_INPUT_BUFFER, 0),
1551 ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1552 IPU_INPUT_BUFFER, 1),
1553 ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
1554 IPU_INPUT_BUFFER, 2));
1555 ++mxc_fbi->cur_ipu_buf;
1556 mxc_fbi->cur_ipu_buf %= 3;
1557 ++mxc_fbi->cur_ipu_buf;
1558 mxc_fbi->cur_ipu_buf %= 3;
1559 mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
1560 ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
1561 ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
1565 dev_dbg(info->device, "Update complete\n");
1567 info->var.yoffset = var->yoffset;
1573 * Function to handle custom mmap for MXC framebuffer.
1575 * @param fbi framebuffer information pointer
1577 * @param vma Pointer to vm_area_struct
1579 static int mxcfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1583 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
1584 struct mxcfb_alloc_list *mem;
1585 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
1587 if (offset < fbi->fix.smem_len) {
1588 /* mapping framebuffer memory */
1589 len = fbi->fix.smem_len - offset;
1590 vma->vm_pgoff = (fbi->fix.smem_start + offset) >> PAGE_SHIFT;
1591 } else if ((vma->vm_pgoff ==
1592 (mxc_fbi->alpha_phy_addr0 >> PAGE_SHIFT)) ||
1594 (mxc_fbi->alpha_phy_addr1 >> PAGE_SHIFT))) {
1595 len = mxc_fbi->alpha_mem_len;
1597 list_for_each_entry(mem, &fb_alloc_list, list) {
1598 if (offset == mem->phy_addr) {
1608 len = PAGE_ALIGN(len);
1609 if (vma->vm_end - vma->vm_start > len)
1612 /* make buffers bufferable */
1613 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1615 vma->vm_flags |= VM_IO;
1617 if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
1618 vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
1619 dev_dbg(fbi->device, "mmap remap_pfn_range failed\n");
1627 * This structure contains the pointers to the control functions that are
1628 * invoked by the core framebuffer driver to perform operations like
1629 * blitting, rectangle filling, copy regions and cursor definition.
1631 static struct fb_ops mxcfb_ops = {
1632 .owner = THIS_MODULE,
1633 .fb_set_par = mxcfb_set_par,
1634 .fb_check_var = mxcfb_check_var,
1635 .fb_setcolreg = mxcfb_setcolreg,
1636 .fb_pan_display = mxcfb_pan_display,
1637 .fb_ioctl = mxcfb_ioctl,
1638 .fb_mmap = mxcfb_mmap,
1639 .fb_fillrect = cfb_fillrect,
1640 .fb_copyarea = cfb_copyarea,
1641 .fb_imageblit = cfb_imageblit,
1642 .fb_blank = mxcfb_blank,
1645 static irqreturn_t mxcfb_irq_handler(int irq, void *dev_id)
1647 struct fb_info *fbi = dev_id;
1648 struct mxcfb_info *mxc_fbi = fbi->par;
1650 complete(&mxc_fbi->flip_complete);
1654 static irqreturn_t mxcfb_nf_irq_handler(int irq, void *dev_id)
1656 struct fb_info *fbi = dev_id;
1657 struct mxcfb_info *mxc_fbi = fbi->par;
1659 complete(&mxc_fbi->vsync_complete);
1663 static irqreturn_t mxcfb_alpha_irq_handler(int irq, void *dev_id)
1665 struct fb_info *fbi = dev_id;
1666 struct mxcfb_info *mxc_fbi = fbi->par;
1668 complete(&mxc_fbi->alpha_flip_complete);
1673 * Suspends the framebuffer and blanks the screen. Power management support
1675 static int mxcfb_suspend(struct platform_device *pdev, pm_message_t state)
1677 struct fb_info *fbi = platform_get_drvdata(pdev);
1678 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
1680 #ifdef CONFIG_FB_MXC_LOW_PWR_DISPLAY
1684 if (mxc_fbi->ovfbi) {
1685 struct mxcfb_info *mxc_fbi_fg =
1686 (struct mxcfb_info *)mxc_fbi->ovfbi->par;
1689 fb_set_suspend(mxc_fbi->ovfbi, 1);
1690 saved_blank = mxc_fbi_fg->cur_blank;
1691 mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
1692 mxc_fbi_fg->next_blank = saved_blank;
1697 fb_set_suspend(fbi, 1);
1698 saved_blank = mxc_fbi->cur_blank;
1699 mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
1700 mxc_fbi->next_blank = saved_blank;
1707 * Resumes the framebuffer and unblanks the screen. Power management support
1709 static int mxcfb_resume(struct platform_device *pdev)
1711 struct fb_info *fbi = platform_get_drvdata(pdev);
1712 struct mxcfb_info *mxc_fbi = (struct mxcfb_info *)fbi->par;
1715 mxcfb_blank(mxc_fbi->next_blank, fbi);
1716 fb_set_suspend(fbi, 0);
1719 if (mxc_fbi->ovfbi) {
1720 struct mxcfb_info *mxc_fbi_fg =
1721 (struct mxcfb_info *)mxc_fbi->ovfbi->par;
1723 mxcfb_blank(mxc_fbi_fg->next_blank, mxc_fbi->ovfbi);
1724 fb_set_suspend(mxc_fbi->ovfbi, 0);
1732 * Main framebuffer functions
1736 * Allocates the DRAM memory for the frame buffer. This buffer is remapped
1737 * into a non-cached, non-buffered, memory region to allow palette and pixel
1738 * writes to occur without flushing the cache. Once this area is remapped,
1739 * all virtual memory access to the video memory should occur at the new region.
1741 * @param fbi framebuffer information pointer
1743 * @return Error code indicating success or failure
1745 static int mxcfb_map_video_memory(struct fb_info *fbi)
1747 if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
1748 fbi->fix.smem_len = fbi->var.yres_virtual *
1749 fbi->fix.line_length;
1751 fbi->screen_base = dma_alloc_writecombine(fbi->device,
1753 (dma_addr_t *)&fbi->fix.smem_start,
1754 GFP_DMA | GFP_KERNEL);
1755 if (fbi->screen_base == 0) {
1756 dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
1757 fbi->fix.smem_len = 0;
1758 fbi->fix.smem_start = 0;
1762 dev_dbg(fbi->device, "allocated fb @ paddr=0x%08X, size=%d.\n",
1763 (uint32_t) fbi->fix.smem_start, fbi->fix.smem_len);
1765 fbi->screen_size = fbi->fix.smem_len;
1767 /* Clear the screen */
1768 memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
1774 * De-allocates the DRAM memory for the frame buffer.
1776 * @param fbi framebuffer information pointer
1778 * @return Error code indicating success or failure
1780 static int mxcfb_unmap_video_memory(struct fb_info *fbi)
1782 dma_free_writecombine(fbi->device, fbi->fix.smem_len,
1783 fbi->screen_base, fbi->fix.smem_start);
1784 fbi->screen_base = 0;
1785 fbi->fix.smem_start = 0;
1786 fbi->fix.smem_len = 0;
1791 * Initializes the framebuffer information pointer. After allocating
1792 * sufficient memory for the framebuffer structure, the fields are
1793 * filled with custom information passed in from the configurable
1794 * structures. This includes information such as bits per pixel,
1795 * color maps, screen width/height and RGBA offsets.
1797 * @return Framebuffer structure initialized with our information
1799 static struct fb_info *mxcfb_init_fbinfo(struct device *dev, struct fb_ops *ops)
1801 struct fb_info *fbi;
1802 struct mxcfb_info *mxcfbi;
1805 * Allocate sufficient memory for the fb structure
1807 fbi = framebuffer_alloc(sizeof(struct mxcfb_info), dev);
1811 mxcfbi = (struct mxcfb_info *)fbi->par;
1813 fbi->var.activate = FB_ACTIVATE_NOW;
1816 fbi->flags = FBINFO_FLAG_DEFAULT;
1817 fbi->pseudo_palette = mxcfbi->pseudo_palette;
1822 fb_alloc_cmap(&fbi->cmap, 16, 0);
1827 static ssize_t show_disp_chan(struct device *dev,
1828 struct device_attribute *attr, char *buf)
1830 struct fb_info *info = dev_get_drvdata(dev);
1831 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
1833 if (mxcfbi->ipu_ch == MEM_BG_SYNC)
1834 return sprintf(buf, "2-layer-fb-bg\n");
1835 else if (mxcfbi->ipu_ch == MEM_FG_SYNC)
1836 return sprintf(buf, "2-layer-fb-fg\n");
1837 else if (mxcfbi->ipu_ch == MEM_DC_SYNC)
1838 return sprintf(buf, "1-layer-fb\n");
1840 return sprintf(buf, "err: no display chan\n");
1843 static ssize_t swap_disp_chan(struct device *dev,
1844 struct device_attribute *attr,
1845 const char *buf, size_t count)
1847 struct fb_info *info = dev_get_drvdata(dev);
1848 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
1849 struct mxcfb_info *fg_mxcfbi = NULL;
1852 /* swap only happen between DP-BG and DC, while DP-FG disable */
1853 if (((mxcfbi->ipu_ch == MEM_BG_SYNC) &&
1854 (strstr(buf, "1-layer-fb") != NULL)) ||
1855 ((mxcfbi->ipu_ch == MEM_DC_SYNC) &&
1856 (strstr(buf, "2-layer-fb-bg") != NULL))) {
1857 struct fb_info *fbi_fg;
1859 fbi_fg = found_registered_fb(MEM_FG_SYNC, mxcfbi->ipu_id);
1861 fg_mxcfbi = (struct mxcfb_info *)fbi_fg->par;
1864 fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
1866 "Can not switch while fb2(fb-fg) is on.\n");
1871 if (swap_channels(info) < 0)
1872 dev_err(dev, "Swap display channel failed.\n");
1878 static DEVICE_ATTR(fsl_disp_property, S_IWUSR | S_IRUGO,
1879 show_disp_chan, swap_disp_chan);
1881 static ssize_t show_disp_dev(struct device *dev,
1882 struct device_attribute *attr, char *buf)
1884 struct fb_info *info = dev_get_drvdata(dev);
1885 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
1887 if (mxcfbi->ipu_ch == MEM_FG_SYNC)
1888 return sprintf(buf, "overlay\n");
1890 return sprintf(buf, "%s\n", mxcfbi->dispdrv->drv->name);
1892 static DEVICE_ATTR(fsl_disp_dev_property, S_IRUGO, show_disp_dev, NULL);
1894 static int mxcfb_dispdrv_init(struct platform_device *pdev,
1895 struct fb_info *fbi)
1897 struct ipuv3_fb_platform_data *plat_data = pdev->dev.platform_data;
1898 struct device_node *np = pdev->dev.of_node;
1899 struct mxcfb_info *mxcfbi = fbi->par;
1900 struct mxc_dispdrv_setting setting = {};
1901 char disp_dev[32], *default_dev = "lcd";
1904 setting.if_fmt = plat_data->interface_pix_fmt;
1905 setting.dft_mode_str = plat_data->mode_str;
1906 setting.default_bpp = plat_data->default_bpp;
1907 if (!setting.default_bpp)
1908 setting.default_bpp = 16;
1910 if (!strlen(plat_data->disp_dev))
1911 strlcpy(disp_dev, default_dev, sizeof(disp_dev));
1913 strlcpy(disp_dev, plat_data->disp_dev, sizeof(disp_dev));
1915 if (of_display_timings_exist(np) == 1) {
1916 struct videomode vm = { };
1918 setting.fbmode = kzalloc(sizeof(*setting.fbmode), GFP_KERNEL);
1919 if (setting.fbmode == NULL)
1922 ret = of_get_videomode(np, &vm, OF_USE_NATIVE_MODE);
1926 fb_videomode_from_videomode(&vm, setting.fbmode);
1927 setting.disp_flags = vm.flags;
1928 dev_dbg(&pdev->dev, "using video mode from DTB\n");
1931 dev_info(&pdev->dev, "register mxc display driver %s\n", disp_dev);
1933 mxcfbi->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting);
1934 if (IS_ERR(mxcfbi->dispdrv)) {
1935 ret = PTR_ERR(mxcfbi->dispdrv);
1936 dev_err(&pdev->dev, "NO mxc display driver found!\n");
1940 mxcfbi->ipu_di_pix_fmt = setting.if_fmt;
1941 mxcfbi->default_bpp = setting.default_bpp;
1944 mxcfbi->ipu_id = setting.dev_id;
1945 mxcfbi->ipu_di = setting.disp_id;
1946 mxcfbi->disp_flags = setting.disp_flags;
1947 dev_dbg(&pdev->dev, "di_pixfmt:0x%x, bpp:0x%x, di:%d, ipu:%d\n",
1948 setting.if_fmt, setting.default_bpp,
1949 setting.disp_id, setting.dev_id);
1953 kfree(setting.fbmode);
1958 * Parse user specified options (`video=trident:')
1960 * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,bpp=16,noaccel
1961 * video=mxcfb0:dev=lcd,800x480M-16@55,if=RGB565,fbpix=RGB565
1963 static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi)
1965 struct ipuv3_fb_platform_data *pdata = pdev->dev.platform_data;
1966 char *options, *opt, *fb_mode_str = NULL;
1967 char name[] = "mxcfb0";
1968 uint32_t fb_pix_fmt = 0;
1970 name[5] += pdev->id;
1971 if (fb_get_options(name, &options)) {
1972 dev_err(&pdev->dev, "Can't get fb option for %s!\n", name);
1976 if (!options || !*options)
1979 while ((opt = strsep(&options, ",")) != NULL) {
1983 if (!strncmp(opt, "dev=", 4)) {
1984 strlcpy(pdata->disp_dev, opt + 4, sizeof(pdata->disp_dev));
1985 } else if (!strncmp(opt, "if=", 3)) {
1986 if (!strncmp(opt+3, "RGB24", 5))
1987 pdata->interface_pix_fmt = IPU_PIX_FMT_RGB24;
1988 else if (!strncmp(opt+3, "BGR24", 5))
1989 pdata->interface_pix_fmt = IPU_PIX_FMT_BGR24;
1990 else if (!strncmp(opt+3, "GBR24", 5))
1991 pdata->interface_pix_fmt = IPU_PIX_FMT_GBR24;
1992 else if (!strncmp(opt+3, "RGB565", 6))
1993 pdata->interface_pix_fmt = IPU_PIX_FMT_RGB565;
1994 else if (!strncmp(opt+3, "RGB666", 6))
1995 pdata->interface_pix_fmt = IPU_PIX_FMT_RGB666;
1996 else if (!strncmp(opt+3, "YUV444", 6))
1997 pdata->interface_pix_fmt = IPU_PIX_FMT_YUV444;
1998 else if (!strncmp(opt+3, "LVDS666", 7))
1999 pdata->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
2000 else if (!strncmp(opt+3, "YUYV16", 6))
2001 pdata->interface_pix_fmt = IPU_PIX_FMT_YUYV;
2002 else if (!strncmp(opt+3, "UYVY16", 6))
2003 pdata->interface_pix_fmt = IPU_PIX_FMT_UYVY;
2004 else if (!strncmp(opt+3, "YVYU16", 6))
2005 pdata->interface_pix_fmt = IPU_PIX_FMT_YVYU;
2006 else if (!strncmp(opt+3, "VYUY16", 6))
2007 pdata->interface_pix_fmt = IPU_PIX_FMT_VYUY;
2008 } else if (!strncmp(opt, "fbpix=", 6)) {
2009 if (!strncmp(opt+6, "RGB24", 5))
2010 fb_pix_fmt = IPU_PIX_FMT_RGB24;
2011 else if (!strncmp(opt+6, "BGR24", 5))
2012 fb_pix_fmt = IPU_PIX_FMT_BGR24;
2013 else if (!strncmp(opt+6, "RGB32", 5))
2014 fb_pix_fmt = IPU_PIX_FMT_RGB32;
2015 else if (!strncmp(opt+6, "BGR32", 5))
2016 fb_pix_fmt = IPU_PIX_FMT_BGR32;
2017 else if (!strncmp(opt+6, "ABGR32", 6))
2018 fb_pix_fmt = IPU_PIX_FMT_ABGR32;
2019 else if (!strncmp(opt+6, "RGB565", 6))
2020 fb_pix_fmt = IPU_PIX_FMT_RGB565;
2023 pixfmt_to_var(fb_pix_fmt, &fbi->var);
2024 pdata->default_bpp =
2025 fbi->var.bits_per_pixel;
2027 } else if (!strncmp(opt, "int_clk", 7)) {
2028 pdata->int_clk = true;
2030 } else if (!strncmp(opt, "bpp=", 4)) {
2031 /* bpp setting cannot overwrite fbpix setting */
2035 pdata->default_bpp =
2036 simple_strtoul(opt + 4, NULL, 0);
2038 fb_pix_fmt = bpp_to_pixfmt(pdata->default_bpp);
2040 pixfmt_to_var(fb_pix_fmt, &fbi->var);
2046 pdata->mode_str = fb_mode_str;
2051 static int mxcfb_register(struct fb_info *fbi)
2053 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
2054 struct fb_videomode m;
2056 char bg0_id[] = "DISP3 BG";
2057 char bg1_id[] = "DISP3 BG - DI1";
2058 char fg_id[] = "DISP3 FG";
2060 if (mxcfbi->ipu_di == 0) {
2061 bg0_id[4] += mxcfbi->ipu_id;
2062 strcpy(fbi->fix.id, bg0_id);
2063 } else if (mxcfbi->ipu_di == 1) {
2064 bg1_id[4] += mxcfbi->ipu_id;
2065 strcpy(fbi->fix.id, bg1_id);
2066 } else { /* Overlay */
2067 fg_id[4] += mxcfbi->ipu_id;
2068 strcpy(fbi->fix.id, fg_id);
2071 mxcfb_check_var(&fbi->var, fbi);
2075 /* Added first mode to fbi modelist. */
2076 if (!fbi->modelist.next || !fbi->modelist.prev)
2077 INIT_LIST_HEAD(&fbi->modelist);
2078 fb_var_to_videomode(&m, &fbi->var);
2079 fb_add_videomode(&m, &fbi->modelist);
2081 if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq,
2082 mxcfb_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
2083 dev_err(fbi->device, "Error registering EOF irq handler.\n");
2087 ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq);
2088 if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq,
2089 mxcfb_nf_irq_handler, IPU_IRQF_ONESHOT, MXCFB_NAME, fbi) != 0) {
2090 dev_err(fbi->device, "Error registering NFACK irq handler.\n");
2094 ipu_disable_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq);
2096 if (mxcfbi->ipu_alp_ch_irq != -1)
2097 if (ipu_request_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq,
2098 mxcfb_alpha_irq_handler, IPU_IRQF_ONESHOT,
2099 MXCFB_NAME, fbi) != 0) {
2100 dev_err(fbi->device, "Error registering alpha irq "
2106 if (!mxcfbi->late_init) {
2107 fbi->var.activate |= FB_ACTIVATE_FORCE;
2109 fbi->flags |= FBINFO_MISC_USEREVENT;
2110 ret = fb_set_var(fbi, &fbi->var);
2111 fbi->flags &= ~FBINFO_MISC_USEREVENT;
2114 dev_err(fbi->device, "Error fb_set_var ret:%d\n", ret);
2118 if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
2120 ret = fb_blank(fbi, FB_BLANK_UNBLANK);
2123 dev_err(fbi->device,
2124 "Error fb_blank ret:%d\n", ret);
2130 * Setup the channel again though bootloader
2131 * has done this, then set_par() can stop the
2132 * channel neatly and re-initialize it .
2134 if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
2136 _setup_disp_channel1(fbi);
2137 ipu_enable_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
2143 ret = register_framebuffer(fbi);
2149 if (mxcfbi->next_blank == FB_BLANK_UNBLANK) {
2151 if (!mxcfbi->late_init)
2152 fb_blank(fbi, FB_BLANK_POWERDOWN);
2154 ipu_disable_channel(mxcfbi->ipu, mxcfbi->ipu_ch,
2156 ipu_uninit_channel(mxcfbi->ipu, mxcfbi->ipu_ch);
2162 if (mxcfbi->ipu_alp_ch_irq != -1)
2163 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
2165 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
2167 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
2172 static void mxcfb_unregister(struct fb_info *fbi)
2174 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)fbi->par;
2176 if (mxcfbi->ipu_alp_ch_irq != -1)
2177 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_alp_ch_irq, fbi);
2178 if (mxcfbi->ipu_ch_irq)
2179 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_irq, fbi);
2180 if (mxcfbi->ipu_ch_nf_irq)
2181 ipu_free_irq(mxcfbi->ipu, mxcfbi->ipu_ch_nf_irq, fbi);
2183 unregister_framebuffer(fbi);
2186 static int mxcfb_setup_overlay(struct platform_device *pdev,
2187 struct fb_info *fbi_bg, struct resource *res)
2189 struct fb_info *ovfbi;
2190 struct mxcfb_info *mxcfbi_bg = (struct mxcfb_info *)fbi_bg->par;
2191 struct mxcfb_info *mxcfbi_fg;
2194 ovfbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
2197 goto init_ovfbinfo_failed;
2199 mxcfbi_fg = ovfbi->par;
2201 mxcfbi_fg->ipu = ipu_get_soc(mxcfbi_bg->ipu_id);
2202 if (IS_ERR(mxcfbi_fg->ipu)) {
2203 ret = PTR_ERR(mxcfbi_fg->ipu);
2204 goto get_ipu_failed;
2206 mxcfbi_fg->ipu_id = mxcfbi_bg->ipu_id;
2207 mxcfbi_fg->ipu_ch_irq = IPU_IRQ_FG_SYNC_EOF;
2208 mxcfbi_fg->ipu_ch_nf_irq = IPU_IRQ_FG_SYNC_NFACK;
2209 mxcfbi_fg->ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
2210 mxcfbi_fg->ipu_ch = MEM_FG_SYNC;
2211 mxcfbi_fg->ipu_di = -1;
2212 mxcfbi_fg->ipu_di_pix_fmt = mxcfbi_bg->ipu_di_pix_fmt;
2213 mxcfbi_fg->overlay = true;
2214 mxcfbi_fg->cur_blank = mxcfbi_fg->next_blank = FB_BLANK_POWERDOWN;
2216 /* Need dummy values until real panel is configured */
2217 ovfbi->var.xres = 240;
2218 ovfbi->var.yres = 320;
2220 if (res && res->start && res->end) {
2221 ovfbi->fix.smem_len = res->end - res->start + 1;
2222 ovfbi->fix.smem_start = res->start;
2223 ovfbi->screen_base = ioremap(
2224 ovfbi->fix.smem_start,
2225 ovfbi->fix.smem_len);
2228 ret = mxcfb_register(ovfbi);
2230 goto register_ov_failed;
2232 mxcfbi_bg->ovfbi = ovfbi;
2238 fb_dealloc_cmap(&ovfbi->cmap);
2239 framebuffer_release(ovfbi);
2240 init_ovfbinfo_failed:
2244 static void mxcfb_unsetup_overlay(struct fb_info *fbi_bg)
2246 struct mxcfb_info *mxcfbi_bg = fbi_bg->par;
2247 struct fb_info *ovfbi = mxcfbi_bg->ovfbi;
2249 mxcfb_unregister(ovfbi);
2252 fb_dealloc_cmap(&ovfbi->cmap);
2253 framebuffer_release(ovfbi);
2256 static bool ipu_usage[2][2];
2257 static int ipu_test_set_usage(int ipu, int di)
2259 if (ipu_usage[ipu][di])
2262 ipu_usage[ipu][di] = true;
2266 static void ipu_clear_usage(int ipu, int di)
2268 ipu_usage[ipu][di] = false;
2271 static int mxcfb_get_of_property(struct platform_device *pdev,
2272 struct ipuv3_fb_platform_data *plat_data)
2274 struct device_node *np = pdev->dev.of_node;
2275 const char *disp_dev;
2276 const char *mode_str;
2282 err = of_property_read_string(np, "disp_dev", &disp_dev);
2284 dev_err(&pdev->dev, "get of property disp_dev fail\n");
2287 err = of_property_read_string(np, "mode_str", &mode_str);
2289 dev_err(&pdev->dev, "get of property mode_str fail\n");
2292 err = of_property_read_string(np, "interface_pix_fmt", &pixfmt);
2294 dev_err(&pdev->dev, "get of property pix fmt fail\n");
2297 err = of_property_read_u32(np, "default_bpp", &bpp);
2299 dev_err(&pdev->dev, "get of property bpp fail\n");
2302 err = of_property_read_u32(np, "int_clk", &int_clk);
2304 dev_err(&pdev->dev, "get of property int_clk fail\n");
2307 err = of_property_read_u32(np, "late_init", &late_init);
2309 dev_err(&pdev->dev, "get of property late_init fail\n");
2313 if (!strncmp(pixfmt, "RGB24", 5))
2314 plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB24;
2315 else if (!strncmp(pixfmt, "BGR24", 5))
2316 plat_data->interface_pix_fmt = IPU_PIX_FMT_BGR24;
2317 else if (!strncmp(pixfmt, "GBR24", 5))
2318 plat_data->interface_pix_fmt = IPU_PIX_FMT_GBR24;
2319 else if (!strncmp(pixfmt, "RGB565", 6))
2320 plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB565;
2321 else if (!strncmp(pixfmt, "RGB666", 6))
2322 plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB666;
2323 else if (!strncmp(pixfmt, "YUV444", 6))
2324 plat_data->interface_pix_fmt = IPU_PIX_FMT_YUV444;
2325 else if (!strncmp(pixfmt, "LVDS666", 7))
2326 plat_data->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
2327 else if (!strncmp(pixfmt, "YUYV16", 6))
2328 plat_data->interface_pix_fmt = IPU_PIX_FMT_YUYV;
2329 else if (!strncmp(pixfmt, "UYVY16", 6))
2330 plat_data->interface_pix_fmt = IPU_PIX_FMT_UYVY;
2331 else if (!strncmp(pixfmt, "YVYU16", 6))
2332 plat_data->interface_pix_fmt = IPU_PIX_FMT_YVYU;
2333 else if (!strncmp(pixfmt, "VYUY16", 6))
2334 plat_data->interface_pix_fmt = IPU_PIX_FMT_VYUY;
2336 dev_err(&pdev->dev, "err interface_pix_fmt!\n");
2340 strlcpy(plat_data->disp_dev, disp_dev, sizeof(plat_data->disp_dev));
2341 plat_data->mode_str = (char *)mode_str;
2342 plat_data->default_bpp = bpp;
2343 plat_data->int_clk = (bool)int_clk;
2344 plat_data->late_init = (bool)late_init;
2349 * Probe routine for the framebuffer driver. It is called during the
2350 * driver binding process. The following functions are performed in
2351 * this routine: Framebuffer initialization, Memory allocation and
2352 * mapping, Framebuffer registration, IPU initialization.
2354 * @return Appropriate error code to the kernel common code
2356 static int mxcfb_probe(struct platform_device *pdev)
2358 struct ipuv3_fb_platform_data *plat_data;
2359 struct fb_info *fbi;
2360 struct mxcfb_info *mxcfbi;
2361 struct resource *res;
2364 dev_dbg(&pdev->dev, "%s enter\n", __func__);
2365 pdev->id = of_alias_get_id(pdev->dev.of_node, "mxcfb");
2367 dev_err(&pdev->dev, "can not get alias id\n");
2371 plat_data = devm_kzalloc(&pdev->dev, sizeof(struct
2372 ipuv3_fb_platform_data), GFP_KERNEL);
2375 pdev->dev.platform_data = plat_data;
2377 ret = mxcfb_get_of_property(pdev, plat_data);
2379 dev_err(&pdev->dev, "get mxcfb of property failed: %d\n", ret);
2383 /* Initialize FB structures */
2384 fbi = mxcfb_init_fbinfo(&pdev->dev, &mxcfb_ops);
2387 goto init_fbinfo_failed;
2390 ret = mxcfb_option_setup(pdev, fbi);
2392 goto get_fb_option_failed;
2395 mxcfbi->ipu_int_clk = plat_data->int_clk;
2396 mxcfbi->late_init = plat_data->late_init;
2397 mxcfbi->first_set_par = true;
2398 ret = mxcfb_dispdrv_init(pdev, fbi);
2400 goto init_dispdrv_failed;
2402 ret = ipu_test_set_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
2404 dev_err(&pdev->dev, "ipu%d-di%d already in use\n",
2405 mxcfbi->ipu_id, mxcfbi->ipu_di);
2409 if (mxcfbi->dispdrv->drv->post_init) {
2410 ret = mxcfbi->dispdrv->drv->post_init(mxcfbi->dispdrv,
2414 dev_err(&pdev->dev, "post init failed\n");
2415 goto post_init_failed;
2419 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2420 if (res && res->start && res->end) {
2421 fbi->fix.smem_len = res->end - res->start + 1;
2422 fbi->fix.smem_start = res->start;
2423 fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
2424 /* Do not clear the fb content drawn in bootloader. */
2425 if (!mxcfbi->late_init)
2426 memset(fbi->screen_base, 0, fbi->fix.smem_len);
2429 mxcfbi->ipu = ipu_get_soc(mxcfbi->ipu_id);
2430 if (IS_ERR(mxcfbi->ipu)) {
2431 dev_err(&pdev->dev, "Failed to get IPU %d\n", mxcfbi->ipu_id);
2432 ret = PTR_ERR(mxcfbi->ipu);
2433 goto get_ipu_failed;
2436 /* first user uses DP with alpha feature */
2437 if (!g_dp_in_use[mxcfbi->ipu_id]) {
2438 mxcfbi->ipu_ch_irq = IPU_IRQ_BG_SYNC_EOF;
2439 mxcfbi->ipu_ch_nf_irq = IPU_IRQ_BG_SYNC_NFACK;
2440 mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
2441 mxcfbi->ipu_ch = MEM_BG_SYNC;
2442 /* Unblank the primary fb only by default */
2444 mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_UNBLANK;
2446 mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
2448 ret = mxcfb_register(fbi);
2450 goto mxcfb_register_failed;
2452 ipu_disp_set_global_alpha(mxcfbi->ipu, mxcfbi->ipu_ch,
2454 ipu_disp_set_color_key(mxcfbi->ipu, mxcfbi->ipu_ch, false, 0);
2456 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
2457 ret = mxcfb_setup_overlay(pdev, fbi, res);
2460 mxcfb_unregister(fbi);
2461 goto mxcfb_setupoverlay_failed;
2464 g_dp_in_use[mxcfbi->ipu_id] = true;
2466 ret = device_create_file(mxcfbi->ovfbi->dev,
2467 &dev_attr_fsl_disp_property);
2469 dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
2470 "file for disp property\n",
2473 ret = device_create_file(mxcfbi->ovfbi->dev,
2474 &dev_attr_fsl_disp_dev_property);
2476 dev_err(mxcfbi->ovfbi->dev, "Error %d on creating "
2477 "file for disp device "
2480 mxcfbi->ipu_ch_irq = IPU_IRQ_DC_SYNC_EOF;
2481 mxcfbi->ipu_ch_nf_irq = IPU_IRQ_DC_SYNC_NFACK;
2482 mxcfbi->ipu_alp_ch_irq = -1;
2483 mxcfbi->ipu_ch = MEM_DC_SYNC;
2484 mxcfbi->cur_blank = mxcfbi->next_blank = FB_BLANK_POWERDOWN;
2486 ret = mxcfb_register(fbi);
2488 goto mxcfb_register_failed;
2491 platform_set_drvdata(pdev, fbi);
2493 ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_property);
2495 dev_err(&pdev->dev, "Error %d on creating file for disp "
2498 ret = device_create_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
2500 dev_err(&pdev->dev, "Error %d on creating file for disp "
2501 " device propety\n", ret);
2505 mxcfb_setupoverlay_failed:
2506 mxcfb_register_failed:
2509 ipu_clear_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
2511 init_dispdrv_failed:
2512 fb_dealloc_cmap(&fbi->cmap);
2513 framebuffer_release(fbi);
2514 get_fb_option_failed:
2519 static int mxcfb_remove(struct platform_device *pdev)
2521 struct fb_info *fbi = platform_get_drvdata(pdev);
2522 struct mxcfb_info *mxc_fbi = fbi->par;
2527 device_remove_file(fbi->dev, &dev_attr_fsl_disp_dev_property);
2528 device_remove_file(fbi->dev, &dev_attr_fsl_disp_property);
2529 mxcfb_blank(FB_BLANK_POWERDOWN, fbi);
2530 mxcfb_unregister(fbi);
2531 mxcfb_unmap_video_memory(fbi);
2533 if (mxc_fbi->ovfbi) {
2534 device_remove_file(mxc_fbi->ovfbi->dev,
2535 &dev_attr_fsl_disp_dev_property);
2536 device_remove_file(mxc_fbi->ovfbi->dev,
2537 &dev_attr_fsl_disp_property);
2538 mxcfb_blank(FB_BLANK_POWERDOWN, mxc_fbi->ovfbi);
2539 mxcfb_unsetup_overlay(fbi);
2540 mxcfb_unmap_video_memory(mxc_fbi->ovfbi);
2543 ipu_clear_usage(mxc_fbi->ipu_id, mxc_fbi->ipu_di);
2545 fb_dealloc_cmap(&fbi->cmap);
2546 framebuffer_release(fbi);
2550 static const struct of_device_id imx_mxcfb_dt_ids[] = {
2551 { .compatible = "fsl,mxc_sdc_fb"},
2556 * This structure contains pointers to the power management callback functions.
2558 static struct platform_driver mxcfb_driver = {
2561 .of_match_table = imx_mxcfb_dt_ids,
2563 .probe = mxcfb_probe,
2564 .remove = mxcfb_remove,
2565 .suspend = mxcfb_suspend,
2566 .resume = mxcfb_resume,
2570 * Main entry function for the framebuffer. The function registers the power
2571 * management callback functions with the kernel and also registers the MXCFB
2572 * callback functions with the core Linux framebuffer driver \b fbmem.c
2574 * @return Error code indicating success or failure
2576 int __init mxcfb_init(void)
2578 return platform_driver_register(&mxcfb_driver);
2581 void mxcfb_exit(void)
2583 platform_driver_unregister(&mxcfb_driver);
2586 module_init(mxcfb_init);
2587 module_exit(mxcfb_exit);
2589 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
2590 MODULE_DESCRIPTION("MXC framebuffer driver");
2591 MODULE_LICENSE("GPL");
2592 MODULE_SUPPORTED_DEVICE("fb");