2 * drivers/video/rockchip/rk_fb.c
4 * Copyright (C) ROCKCHIP, Inc.
5 *Author:yxj<yxj@rock-chips.com>
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
21 #include <linux/slab.h>
22 #include <linux/delay.h>
23 #include <linux/device.h>
24 #include <linux/kthread.h>
26 #include <linux/init.h>
27 #include <asm/div64.h>
28 #include <linux/uaccess.h>
29 #include <linux/rk_fb.h>
30 #include <linux/linux_logo.h>
31 #include <linux/dma-mapping.h>
34 #if defined(CONFIG_RK_HDMI)
35 #include "hdmi/rk_hdmi.h"
40 #include <linux/of_gpio.h>
41 #include <video/of_display_timing.h>
42 #include <video/display_timing.h>
43 #include <dt-bindings/rkfb/rk_fb.h>
46 #if defined(CONFIG_ION_ROCKCHIP)
47 #include <linux/rockchip_ion.h>
51 static int hdmi_switch_complete;
52 static struct platform_device *fb_pdev;
55 #if defined(CONFIG_FB_MIRRORING)
56 int (*video_data_to_mirroring)(struct fb_info *info, u32 yuv_phy[2]);
57 EXPORT_SYMBOL(video_data_to_mirroring);
63 /* rk display power control parse from dts
66 int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
68 struct device_node *root = of_parse_phandle(dev_drv->dev->of_node,
70 struct device_node *child;
71 struct rk_disp_pwr_ctr_list *pwr_ctr;
72 struct list_head *pos;
73 enum of_gpio_flags flags;
78 INIT_LIST_HEAD(&dev_drv->pwrlist_head);
80 dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",dev_drv->id);
84 for_each_child_of_node(root, child) {
85 pwr_ctr = kmalloc(sizeof(struct rk_disp_pwr_ctr_list), GFP_KERNEL);
86 strcpy(pwr_ctr->pwr_ctr.name, child->name);
87 if (!of_property_read_u32(child, "rockchip,power_type", &val)) {
89 pwr_ctr->pwr_ctr.type = GPIO;
90 pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
91 if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
92 dev_err(dev_drv->dev, "%s ivalid gpio\n", child->name);
95 pwr_ctr->pwr_ctr.atv_val = !(flags & OF_GPIO_ACTIVE_LOW);
96 ret = gpio_request(pwr_ctr->pwr_ctr.gpio,child->name);
98 dev_err(dev_drv->dev, "request %s gpio fail:%d\n",
103 pwr_ctr->pwr_ctr.type = REGULATOR;
107 of_property_read_u32(child, "rockchip,delay", &val);
108 pwr_ctr->pwr_ctr.delay = val;
109 list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
112 of_property_read_u32(root, "rockchip,debug", &debug);
115 list_for_each(pos, &dev_drv->pwrlist_head) {
116 pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
117 printk(KERN_INFO "pwr_ctr_name:%s\n"
122 pwr_ctr->pwr_ctr.name,
123 (pwr_ctr->pwr_ctr.type == GPIO) ? "gpio" : "regulator",
124 pwr_ctr->pwr_ctr.gpio,
125 pwr_ctr->pwr_ctr.atv_val,
126 pwr_ctr->pwr_ctr.delay);
134 int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
136 struct list_head *pos;
137 struct rk_disp_pwr_ctr_list *pwr_ctr_list;
138 struct pwr_ctr *pwr_ctr;
139 if (list_empty(&dev_drv->pwrlist_head))
141 list_for_each(pos, &dev_drv->pwrlist_head) {
142 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
143 pwr_ctr = &pwr_ctr_list->pwr_ctr;
144 if (pwr_ctr->type == GPIO) {
145 gpio_direction_output(pwr_ctr->gpio,pwr_ctr->atv_val);
146 mdelay(pwr_ctr->delay);
153 int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv)
155 struct list_head *pos;
156 struct rk_disp_pwr_ctr_list *pwr_ctr_list;
157 struct pwr_ctr *pwr_ctr;
158 if (list_empty(&dev_drv->pwrlist_head))
160 list_for_each(pos, &dev_drv->pwrlist_head) {
161 pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list, list);
162 pwr_ctr = &pwr_ctr_list->pwr_ctr;
163 if (pwr_ctr->type == GPIO) {
164 gpio_set_value(pwr_ctr->gpio,pwr_ctr->atv_val);
171 int rk_fb_video_mode_from_timing(const struct display_timing *dt,
172 struct rk_screen *screen)
174 screen->mode.pixclock = dt->pixelclock.typ;
175 screen->mode.left_margin = dt->hback_porch.typ;
176 screen->mode.right_margin = dt->hfront_porch.typ;
177 screen->mode.xres = dt->hactive.typ;
178 screen->mode.hsync_len = dt->hsync_len.typ;
179 screen->mode.upper_margin = dt->vback_porch.typ;
180 screen->mode.lower_margin = dt->vfront_porch.typ;
181 screen->mode.yres = dt->vactive.typ;
182 screen->mode.vsync_len = dt->vsync_len.typ;
183 screen->type = dt->screen_type;
184 screen->lvds_format = dt->lvds_format;
185 screen->face = dt->face;
186 if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
187 screen->pin_dclk = 1;
189 screen->pin_dclk = 0;
190 if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
191 screen->pin_hsync = 1;
193 screen->pin_hsync = 0;
194 if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
195 screen->pin_vsync = 1;
197 screen->pin_vsync = 0;
198 if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
206 int rk_disp_prase_timing_dt(struct rk_lcdc_driver *dev_drv)
208 struct display_timings *disp_timing;
209 struct display_timing *dt;
210 struct rk_screen *screen = dev_drv->cur_screen;
211 disp_timing = of_get_display_timings(dev_drv->dev->of_node);
213 dev_err(dev_drv->dev, "parse display timing err\n");
216 dt = display_timings_get(disp_timing, 0);
217 rk_fb_video_mode_from_timing(dt, screen);
218 printk(KERN_DEBUG "dclk:%d\n"
230 dt->hfront_porch.typ,
234 dt->vfront_porch.typ,
240 int rk_fb_calc_fps(struct rk_screen * screen, u32 pixclock)
243 unsigned long long hz;
245 printk(KERN_ERR "%s:null screen!\n", __func__);
248 x = screen->mode.xres + screen->mode.left_margin + screen->mode.right_margin +
249 screen->mode.hsync_len;
250 y = screen->mode.yres + screen->mode.upper_margin + screen->mode.lower_margin +
251 screen->mode.vsync_len;
253 hz = 1000000000000ULL; /* 1e12 picoseconds per second */
256 do_div(hz, x * y); /* divide by x * y with rounding */
259 do_div(hz, pixclock); /* divide by pixclock with rounding */
264 char *get_format_string(enum data_format format, char *fmt)
270 strcpy(fmt, "ARGB888");
273 strcpy(fmt, "RGB888");
276 strcpy(fmt, "RGB565");
279 strcpy(fmt, "YUV420");
282 strcpy(fmt, "YUV422");
285 strcpy(fmt, "YUV444");
288 strcpy(fmt, "XRGB888");
291 strcpy(fmt, "XBGR888");
294 strcpy(fmt, "XBGR888");
297 strcpy(fmt, "invalid");
307 /**********************************************************************
309 name: lcdc device name ,lcdc0 , lcdc1
310 ***********************************************************************/
311 struct rk_lcdc_driver *rk_get_lcdc_drv(char *name)
313 struct rk_fb *inf = platform_get_drvdata(fb_pdev);
315 for (i = 0; i < inf->num_lcdc; i++) {
316 if (!strcmp(inf->lcdc_dev_drv[i]->name, name))
319 return inf->lcdc_dev_drv[i];
323 static struct rk_lcdc_driver *rk_get_prmry_lcdc_drv(void)
325 struct rk_fb *inf = NULL;
326 struct rk_lcdc_driver *dev_drv = NULL;
330 inf = platform_get_drvdata(fb_pdev);
334 for (i = 0; i < inf->num_lcdc; i++) {
335 if (inf->lcdc_dev_drv[i]->prop == PRMRY) {
336 dev_drv = inf->lcdc_dev_drv[i];
345 int rk_fb_get_prmry_screen_ft(void)
347 struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
348 uint32_t htotal, vtotal, pix_total, ft_us, dclk_mhz;
350 if (unlikely(!dev_drv))
353 dclk_mhz = dev_drv->pixclock/(1000*1000);
355 htotal = (dev_drv->cur_screen->mode.upper_margin + dev_drv->cur_screen->mode.lower_margin +
356 dev_drv->cur_screen->mode.yres + dev_drv->cur_screen->mode.vsync_len);
357 vtotal = (dev_drv->cur_screen->mode.left_margin + dev_drv->cur_screen->mode.right_margin +
358 dev_drv->cur_screen->mode.xres + dev_drv->cur_screen->mode.hsync_len);
359 pix_total = htotal*vtotal;
360 ft_us = pix_total / dclk_mhz;
365 static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
367 struct rk_fb *inf = NULL;
368 struct rk_lcdc_driver *dev_drv = NULL;
372 inf = platform_get_drvdata(fb_pdev);
376 for (i = 0; i < inf->num_lcdc; i++) {
377 if (inf->lcdc_dev_drv[i]->prop == EXTEND) {
378 dev_drv = inf->lcdc_dev_drv[i];
386 int rk_fb_get_prmry_screen(struct rk_screen *screen)
388 struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
389 memcpy(screen, dev_drv->screen0, sizeof(struct rk_screen));
395 u32 rk_fb_get_prmry_screen_pixclock(void)
397 struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
398 return dev_drv->pixclock;
401 int rk_fb_poll_prmry_screen_vblank(void)
403 struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
404 if (likely(dev_drv)) {
405 if (dev_drv->ops->poll_vblank)
406 return dev_drv->ops->poll_vblank(dev_drv);
408 return RK_LF_STATUS_NC;
410 return RK_LF_STATUS_NC;
413 bool rk_fb_poll_wait_frame_complete(void)
415 uint32_t timeout = RK_LF_MAX_TIMEOUT;
416 if (rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_NC)
419 while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FR) && --timeout);
420 while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FC) && --timeout);
424 static int rk_fb_open(struct fb_info *info, int user)
426 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
429 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
430 if (dev_drv->win[win_id]->state)
431 return 0; /* if this win aready opened ,no need to reopen*/
433 dev_drv->ops->open(dev_drv, win_id, 1);
437 static int get_extend_fb_id(struct fb_info *info)
440 char *id = info->fix.id;
441 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
442 if (!strcmp(id, "fb0"))
444 else if (!strcmp(id, "fb1"))
446 else if (!strcmp(id, "fb2") && (dev_drv->num_win > 2))
451 static int rk_fb_close(struct fb_info *info, int user)
453 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
454 struct rk_lcdc_win *win = NULL;
455 int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
457 win = dev_drv->win[win_id];
458 info->fix.smem_start = win->reserved;
460 info->var.xres = dev_drv->screen0->mode.xres;
461 info->var.yres = dev_drv->screen0->mode.yres;
462 info->var.grayscale |= (info->var.xres<<8) + (info->var.yres<<20);
463 #if defined(CONFIG_LOGO_LINUX_BMP)
464 info->var.bits_per_pixel = 32;
466 info->var.bits_per_pixel = 16;
468 info->fix.line_length = (info->var.xres)*(info->var.bits_per_pixel>>3);
469 info->var.xres_virtual = info->var.xres;
470 info->var.yres_virtual = info->var.yres;
471 info->var.width = dev_drv->screen0->width;
472 info->var.height = dev_drv->screen0->height;
473 info->var.pixclock = dev_drv->pixclock;
474 info->var.left_margin = dev_drv->screen0->mode.left_margin;
475 info->var.right_margin = dev_drv->screen0->mode.right_margin;
476 info->var.upper_margin = dev_drv->screen0->mode.upper_margin;
477 info->var.lower_margin = dev_drv->screen0->mode.lower_margin;
478 info->var.vsync_len = dev_drv->screen0->mode.vsync_len;
479 info->var.hsync_len = dev_drv->screen0->mode.hsync_len;
486 #if defined(CONFIG_RK29_IPP)
487 static int get_ipp_format(int fmt)
489 int ipp_fmt = IPP_XRGB_8888;
491 case HAL_PIXEL_FORMAT_RGBX_8888:
492 case HAL_PIXEL_FORMAT_RGBA_8888:
493 case HAL_PIXEL_FORMAT_BGRA_8888:
494 case HAL_PIXEL_FORMAT_RGB_888:
495 ipp_fmt = IPP_XRGB_8888;
497 case HAL_PIXEL_FORMAT_RGB_565:
498 ipp_fmt = IPP_RGB_565;
500 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
501 ipp_fmt = IPP_Y_CBCR_H2V1;
503 case HAL_PIXEL_FORMAT_YCrCb_NV12:
504 ipp_fmt = IPP_Y_CBCR_H2V2;
506 case HAL_PIXEL_FORMAT_YCrCb_444:
507 ipp_fmt = IPP_Y_CBCR_H1V1;
510 ipp_fmt = IPP_IMGTYPE_LIMIT;
517 static void ipp_win_check(int *dst_w, int *dst_h, int *dst_vir_w,
518 int rotation, int fmt)
524 if (fmt == IPP_XRGB_8888) {
527 } else if (fmt == IPP_RGB_565) {
534 align16 -= 1; /*for YUV, 1*/
535 align64 -= 1; /*for YUV, 7*/
537 if (rotation == IPP_ROT_0) {
538 if (fmt > IPP_RGB_565) {
539 if ((*dst_w & 1) != 0)
541 if ((*dst_h & 1) != 0)
543 if (*dst_vir_w < *dst_w)
548 if ((*dst_w & align64) != 0)
549 *dst_w = (*dst_w+align64)&(~align64);
550 if ((fmt > IPP_RGB_565) && ((*dst_h & 1) == 1))
552 if (*dst_vir_w < *dst_w)
558 static void fb_copy_by_ipp(struct fb_info *dst_info,
559 struct fb_info *src_info, int offset)
561 struct rk29_ipp_req ipp_req;
562 uint32_t rotation = 0;
563 int dst_w, dst_h, dst_vir_w;
565 u8 data_format = (dst_info->var.nonstd)&0xff;
567 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
568 #if defined(CONFIG_FB_ROTATE)
569 int orientation = 270 - CONFIG_ROTATE_ORIENTATION;
570 switch (orientation) {
572 rotation = IPP_ROT_0;
575 rotation = IPP_ROT_90;
578 rotation = IPP_ROT_180;
581 rotation = IPP_ROT_270;
584 rotation = IPP_ROT_270;
590 dst_w = dst_info->var.xres;
591 dst_h = dst_info->var.yres;
592 dst_vir_w = dst_info->var.xres_virtual;
593 ipp_fmt = get_ipp_format(data_format);
594 ipp_win_check(&dst_w, &dst_h, &dst_vir_w, rotation, ipp_fmt);
595 ipp_req.src0.YrgbMst = src_info->fix.smem_start + offset;
596 ipp_req.src0.w = src_info->var.xres;
597 ipp_req.src0.h = src_info->var.yres;
598 ipp_req.src_vir_w = src_info->var.xres_virtual;
599 ipp_req.src0.fmt = ipp_fmt;
601 ipp_req.dst0.YrgbMst = dst_info->fix.smem_start + offset;
602 ipp_req.dst0.w = dst_w;
603 ipp_req.dst0.h = dst_h;
604 ipp_req.dst_vir_w = dst_vir_w;
605 ipp_req.dst0.fmt = ipp_fmt;
608 ipp_req.timeout = 100;
609 ipp_req.flag = rotation;
610 ipp_blit_sync(&ipp_req);
617 static int rk_fb_rotate(struct fb_info *dst_info,
618 struct fb_info *src_info, int offset)
620 #if defined(CONFIG_RK29_IPP)
621 fb_copy_by_ipp(dst_info, src_info, offset);
627 static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
629 struct rk_fb *rk_fb = dev_get_drvdata(info->device);
630 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
631 struct fb_fix_screeninfo *fix = &info->fix;
632 struct fb_info *extend_info = NULL;
633 struct rk_lcdc_driver *extend_dev_drv = NULL;
634 int win_id = 0, extend_win_id = 0;
635 struct rk_lcdc_win *extend_win = NULL;
636 struct rk_lcdc_win *win = NULL;
640 u32 xoffset = var->xoffset;
641 u32 yoffset = var->yoffset;
642 u32 xvir = var->xres_virtual;
643 u8 data_format = var->nonstd&0xff;
645 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
649 win = dev_drv->win[win_id];
651 if (rk_fb->disp_mode == DUAL) {
652 fb_id = get_extend_fb_id(info);
653 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
654 extend_dev_drv = (struct rk_lcdc_driver *)extend_info->par;
655 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
656 extend_info->fix.id);
657 extend_win = extend_dev_drv->win[extend_win_id];
660 switch (win->format) {
664 win->y_offset = (yoffset*xvir + xoffset)*4;
667 win->y_offset = (yoffset*xvir + xoffset)*3;
670 win->y_offset = (yoffset*xvir + xoffset)*2;
673 win->y_offset = yoffset*xvir + xoffset;
674 win->c_offset = win->y_offset;
677 win->y_offset = yoffset*xvir + xoffset;
678 win->c_offset = (yoffset>>1)*xvir + xoffset;
681 win->y_offset = yoffset*xvir + xoffset;
682 win->c_offset = yoffset*2*xvir + (xoffset<<1);
685 printk(KERN_ERR "%s un supported format:0x%x\n",
686 __func__, data_format);
689 win->smem_start = fix->smem_start;
690 win->cbr_start = fix->mmio_start;
691 dev_drv->ops->pan_display(dev_drv, win_id);
692 if (rk_fb->disp_mode == DUAL) {
693 if (extend_win->state && (hdmi_switch_complete)) {
694 extend_win->y_offset = win->y_offset;
695 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
696 rk_fb_rotate(extend_info, info, win->y_offset);
698 extend_dev_drv->ops->pan_display(extend_dev_drv, extend_win_id);
702 #ifdef CONFIG_FB_MIRRORING
703 if (video_data_to_mirroring)
704 video_data_to_mirroring(info, NULL);
709 static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
711 struct rk_fb *rk_fb = dev_get_drvdata(info->device);
712 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
713 struct fb_fix_screeninfo *fix = &info->fix;
714 int fb_id = 0, extend_win_id = 0;
715 struct fb_info *extend_info = NULL;
716 struct rk_lcdc_driver *extend_dev_drv = NULL;
717 struct rk_lcdc_win *extend_win = NULL;
718 struct rk_lcdc_win *win;
719 int enable; /* enable fb:1 enable;0 disable*/
720 int ovl; /*overlay:0 win1 on the top of win0;1,win0 on the top of win1*/
721 int num_buf; /*buffer_number*/
724 int win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
726 void __user *argp = (void __user *)arg;
728 win = dev_drv->win[win_id];
729 if (rk_fb->disp_mode == DUAL) {
730 fb_id = get_extend_fb_id(info);
731 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
732 extend_dev_drv = (struct rk_lcdc_driver *)extend_info->par;
733 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
734 extend_info->fix.id);
735 extend_win = extend_dev_drv->win[extend_win_id];
739 case RK_FBIOSET_YUV_ADDR:
742 if (copy_from_user(yuv_phy, argp, 8))
744 fix->smem_start = yuv_phy[0];
745 fix->mmio_start = yuv_phy[1];
748 case RK_FBIOSET_ENABLE:
749 if (copy_from_user(&enable, argp, sizeof(enable)))
751 dev_drv->ops->open(dev_drv, win_id, enable);
753 case RK_FBIOGET_ENABLE:
754 enable = dev_drv->ops->get_win_state(dev_drv, win_id);
755 if (copy_to_user(argp, &enable, sizeof(enable)))
758 case RK_FBIOSET_OVERLAY_STATE:
759 if (copy_from_user(&ovl, argp, sizeof(ovl)))
761 dev_drv->ops->ovl_mgr(dev_drv, ovl, 1);
763 case RK_FBIOGET_OVERLAY_STATE:
764 ovl = dev_drv->ops->ovl_mgr(dev_drv, 0, 0);
765 if (copy_to_user(argp, &ovl, sizeof(ovl)))
768 case RK_FBIOPUT_NUM_BUFFERS:
769 if (copy_from_user(&num_buf, argp, sizeof(num_buf)))
771 dev_drv->num_buf = num_buf;
773 case RK_FBIOSET_VSYNC_ENABLE:
774 if (copy_from_user(&enable, argp, sizeof(enable)))
776 dev_drv->vsync_info.active = enable;
778 #if defined(CONFIG_ION_ROCKCHIP)
779 case RK_FBIOSET_DMABUF_FD:
782 struct ion_handle *hdl;
783 ion_phys_addr_t phy_addr;
785 if (copy_from_user(&usr_fd, argp, sizeof(usr_fd)))
787 hdl = ion_import_dma_buf(rk_fb->ion_client, usr_fd);
788 ion_phys(rk_fb->ion_client, hdl, &phy_addr, &len);
789 fix->smem_start = phy_addr;
792 case RK_FBIOGET_DMABUF_FD:
794 int fd = ion_share_dma_buf_fd(rk_fb->ion_client, win->ion_hdl);
796 dev_err(info->dev, "ion_share_dma_buf_fd failed\n");
800 if (copy_to_user(argp, &fd, sizeof(fd)))
805 case RK_FBIOSET_CONFIG_DONE:
806 ret = copy_from_user(&(dev_drv->wait_fs), argp, sizeof(dev_drv->wait_fs));
807 if (dev_drv->ops->lcdc_reg_update)
808 dev_drv->ops->lcdc_reg_update(dev_drv);
809 if (rk_fb->disp_mode == DUAL) {
810 if (extend_win->state && (hdmi_switch_complete)) {
811 if (rk_fb->num_fb >= 2) {
812 if (extend_dev_drv->ops->lcdc_reg_update)
813 extend_dev_drv->ops->lcdc_reg_update(extend_dev_drv);
819 dev_drv->ops->ioctl(dev_drv, cmd, arg, win_id);
826 static int rk_fb_blank(int blank_mode, struct fb_info *info)
828 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
829 struct fb_fix_screeninfo *fix = &info->fix;
832 win_id = dev_drv->ops->fb_get_win_id(dev_drv, fix->id);
835 #if defined(CONFIG_RK_HDMI)
836 struct rk_fb *rk_fb = dev_get_drvdata(info->device);
837 if ((rk_fb->disp_mode == ONE_DUAL) && (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)) {
838 printk(KERN_INFO "hdmi is connect , not blank lcdc\n");
842 dev_drv->ops->blank(dev_drv, win_id, blank_mode);
847 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
850 if ((0 == var->xres_virtual) || (0 == var->yres_virtual) ||
851 (0 == var->xres) || (0 == var->yres) || (var->xres < 16) ||
852 ((16 != var->bits_per_pixel) && (32 != var->bits_per_pixel))) {
853 dev_err(info->dev, "%s check var fail 1:\n"
854 "xres_vir:%d>>yres_vir:%d\n"
856 "bits_per_pixel:%d\n",
862 var->bits_per_pixel);
866 if (((var->xoffset+var->xres) > var->xres_virtual) ||
867 ((var->yoffset+var->yres) > (var->yres_virtual))) {
868 dev_err(info->dev, "%s check_var fail 2:\n"
869 "xoffset:%d>>xres:%d>>xres_vir:%d\n"
870 "yoffset:%d>>yres:%d>>yres_vir:%d\n",
884 static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
885 size_t count, loff_t *ppos)
887 unsigned long p = *ppos;
890 int c, cnt = 0, err = 0;
891 unsigned long total_size;
892 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
893 struct rk_lcdc_win *win = NULL;
896 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
900 win = dev_drv->win[win_id];
902 if (win->format == RGB565)
903 total_size = win->xact*win->yact<<1; /*only read the current frame buffer*/
905 total_size = win->xact*win->yact<<2;
911 if (count >= total_size)
914 if (count + p > total_size)
915 count = total_size - p;
917 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
922 src = (u8 __iomem *) (info->screen_base + p + win->y_offset);
925 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
927 fb_memcpy_fromfb(dst, src, c);
931 if (copy_to_user(buf, buffer, c)) {
943 return (err) ? err : cnt;
946 static ssize_t rk_fb_write(struct fb_info *info, const char __user *buf,
947 size_t count, loff_t *ppos)
949 unsigned long p = *ppos;
952 int c, cnt = 0, err = 0;
953 unsigned long total_size;
954 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
955 struct rk_lcdc_win *win = NULL;
958 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
962 win = dev_drv->win[win_id];
964 if (win->format == RGB565)
965 total_size = win->xact*win->yact<<1; /*write the current frame buffer*/
967 total_size = win->xact*win->yact<<2;
972 if (count > total_size) {
977 if (count + p > total_size) {
981 count = total_size - p;
984 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
989 dst = (u8 __iomem *) (info->screen_base + p + win->y_offset);
992 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
995 if (copy_from_user(src, buf, c)) {
1000 fb_memcpy_tofb(dst, src, c);
1011 return (cnt) ? cnt : err;
1015 static int rk_fb_set_par(struct fb_info *info)
1017 struct fb_var_screeninfo *var = &info->var;
1018 struct fb_fix_screeninfo *fix = &info->fix;
1019 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)info->par;
1020 struct rk_fb *rk_fb = dev_get_drvdata(info->device);
1021 int fb_id, extend_win_id = 0;
1022 struct fb_info *extend_info = NULL;
1023 struct rk_lcdc_driver *extend_dev_drv = NULL;
1024 struct rk_lcdc_win *extend_win = NULL;
1025 struct rk_lcdc_win *win = NULL;
1026 struct rk_screen *screen = dev_drv->cur_screen;
1028 u32 cblen = 0, crlen = 0;
1029 u16 xsize = 0, ysize = 0; /*winx display window height/width --->LCDC_WINx_DSP_INFO*/
1030 u32 xoffset = var->xoffset; /* offset from virtual to visible*/
1031 u32 yoffset = var->yoffset;
1032 u16 xpos = (var->nonstd>>8) & 0xfff; /*visiable pos in panel*/
1033 u16 ypos = (var->nonstd>>20) & 0xfff;
1034 u32 xvir = var->xres_virtual;
1035 u32 yvir = var->yres_virtual;
1036 u8 data_format = var->nonstd&0xff;
1040 var->pixclock = dev_drv->pixclock;
1041 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1045 win = dev_drv->win[win_id];
1047 if (rk_fb->disp_mode == DUAL) {
1048 fb_id = get_extend_fb_id(info);
1049 extend_info = rk_fb->fb[(rk_fb->num_fb>>1) + fb_id];
1050 extend_dev_drv = (struct rk_lcdc_driver *)extend_info->par;
1051 extend_win_id = dev_drv->ops->fb_get_win_id(extend_dev_drv,
1052 extend_info->fix.id);
1053 extend_win = extend_dev_drv->win[extend_win_id];
1055 if (var->grayscale>>8) { /*if the application has specific the horizontal and vertical display size*/
1056 xsize = (var->grayscale>>8) & 0xfff;
1057 ysize = (var->grayscale>>20) & 0xfff;
1058 } else { /*ohterwise full screen display*/
1059 xsize = screen->mode.xres;
1060 ysize = screen->mode.yres;
1063 /*this is for device like rk2928 ,whic have one lcdc but two display outputs*/
1064 /*save winameter set by android*/
1065 if (rk_fb->disp_mode != DUAL) {
1066 if (screen->screen_id == 0) {
1068 dev_drv->screen0->xsize = xsize;
1069 dev_drv->screen0->ysize = ysize;
1070 dev_drv->screen0->xpos = xpos;
1071 dev_drv->screen0->ypos = ypos;
1073 xsize = dev_drv->screen1->xsize;
1074 ysize = dev_drv->screen1->ysize;
1075 xpos = dev_drv->screen1->xpos;
1076 ypos = dev_drv->screen1->ypos;
1081 switch (data_format) {
1082 case HAL_PIXEL_FORMAT_RGBX_8888:
1083 win->format = XBGR888;
1084 fix->line_length = 4 * xvir;
1085 win->y_offset = (yoffset*xvir + xoffset)*4;
1087 case HAL_PIXEL_FORMAT_RGBA_8888:
1088 win->format = ABGR888;
1089 fix->line_length = 4 * xvir;
1090 win->y_offset = (yoffset*xvir + xoffset)*4;
1092 case HAL_PIXEL_FORMAT_BGRA_8888:
1093 win->format = ARGB888;
1094 fix->line_length = 4 * xvir;
1095 win->y_offset = (yoffset*xvir + xoffset)*4;
1097 case HAL_PIXEL_FORMAT_RGB_888:
1098 win->format = RGB888;
1099 fix->line_length = 3 * xvir;
1100 win->y_offset = (yoffset*xvir + xoffset)*3;
1102 case HAL_PIXEL_FORMAT_RGB_565:
1103 win->format = RGB565;
1104 fix->line_length = 2 * xvir;
1105 win->y_offset = (yoffset*xvir + xoffset)*2;
1107 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
1108 win->format = YUV422;
1109 fix->line_length = xvir;
1110 cblen = crlen = (xvir*yvir)>>1;
1111 win->y_offset = yoffset*xvir + xoffset;
1112 win->c_offset = win->y_offset;
1114 case HAL_PIXEL_FORMAT_YCrCb_NV12:
1115 win->format = YUV420;
1116 fix->line_length = xvir;
1117 cblen = crlen = (xvir*yvir)>>2;
1118 win->y_offset = yoffset*xvir + xoffset;
1119 win->c_offset = (yoffset>>1)*xvir + xoffset;
1121 case HAL_PIXEL_FORMAT_YCrCb_444:
1123 fix->line_length = xvir<<2;
1124 win->y_offset = yoffset*xvir + xoffset;
1125 win->c_offset = yoffset*2*xvir + (xoffset<<1);
1126 cblen = crlen = (xvir*yvir);
1129 printk(KERN_ERR "%s:un supported format:0x%x\n", __func__, data_format);
1133 switch (var->bits_per_pixel) {
1135 win->format = ARGB888;
1136 fix->line_length = 4 * xvir;
1137 win->y_offset = (yoffset*xvir + xoffset)*4;
1140 win->format = RGB565;
1141 fix->line_length = 2 * xvir;
1142 win->y_offset = (yoffset*xvir + xoffset)*2;
1153 win->smem_start = fix->smem_start;
1154 win->cbr_start = fix->mmio_start;
1155 win->xact = var->xres; /*winx active window height,is a wint of vir*/
1156 win->yact = var->yres;
1157 win->xvir = var->xres_virtual; /*virtual resolution stride --->LCDC_WINx_VIR*/
1158 win->yvir = var->yres_virtual;
1159 if (rk_fb->disp_mode == DUAL) {
1160 if (extend_win->state && (hdmi_switch_complete)) {
1161 if (info != extend_info) {
1162 if (win->xact < win->yact) {
1163 extend_win->xact = win->yact;
1164 extend_win->yact = win->xact;
1165 extend_win->xvir = win->yact;
1166 extend_info->var.xres = var->yres;
1167 extend_info->var.yres = var->xres;
1168 extend_info->var.xres_virtual = var->yres;
1170 extend_win->xact = win->xact;
1171 extend_win->yact = win->yact;
1172 extend_win->xvir = win->xvir;
1173 extend_info->var.xres = var->xres;
1174 extend_info->var.yres = var->yres;
1175 extend_info->var.xres_virtual = var->xres_virtual;
1177 extend_win->format = win->format;
1178 extend_info->var.nonstd &= 0xffffff00;
1179 extend_info->var.nonstd |= data_format;
1180 extend_dev_drv->ops->set_par(extend_dev_drv, extend_win_id);
1184 dev_drv->ops->set_par(dev_drv, win_id);
1189 static inline unsigned int chan_to_field(unsigned int chan,
1190 struct fb_bitfield *bf)
1193 chan >>= 16 - bf->length;
1194 return chan << bf->offset;
1197 static int fb_setcolreg(unsigned regno,
1198 unsigned red, unsigned green, unsigned blue,
1199 unsigned transp, struct fb_info *info)
1203 switch (info->fix.visual) {
1204 case FB_VISUAL_TRUECOLOR:
1205 /* true-colour, use pseudo-palette */
1207 u32 *pal = info->pseudo_palette;
1208 val = chan_to_field(red, &info->var.red);
1209 val |= chan_to_field(green, &info->var.green);
1210 val |= chan_to_field(blue, &info->var.blue);
1215 return -1; /* unknown type */
1221 static struct fb_ops fb_ops = {
1222 .owner = THIS_MODULE,
1223 .fb_open = rk_fb_open,
1224 .fb_release = rk_fb_close,
1225 .fb_check_var = rk_fb_check_var,
1226 .fb_set_par = rk_fb_set_par,
1227 .fb_blank = rk_fb_blank,
1228 .fb_ioctl = rk_fb_ioctl,
1229 .fb_pan_display = rk_pan_display,
1230 .fb_read = rk_fb_read,
1231 .fb_write = rk_fb_write,
1232 .fb_setcolreg = fb_setcolreg,
1233 .fb_fillrect = cfb_fillrect,
1234 .fb_copyarea = cfb_copyarea,
1235 .fb_imageblit = cfb_imageblit,
1240 static struct fb_var_screeninfo def_var = {
1241 #if defined(CONFIG_LOGO_LINUX_BMP)
1245 .transp = {0, 0, 0},
1246 .nonstd = HAL_PIXEL_FORMAT_BGRA_8888,
1251 .transp = {0, 0, 0},
1252 .nonstd = HAL_PIXEL_FORMAT_RGB_565, /*(ypos<<20+xpos<<8+format) format*/
1254 .grayscale = 0, /*(ysize<<20+xsize<<8)*/
1255 .activate = FB_ACTIVATE_NOW,
1257 .vmode = FB_VMODE_NONINTERLACED,
1260 static struct fb_fix_screeninfo def_fix = {
1261 .type = FB_TYPE_PACKED_PIXELS,
1266 .accel = FB_ACCEL_NONE,
1267 .visual = FB_VISUAL_TRUECOLOR,
1272 static int rk_fb_wait_for_vsync_thread(void *data)
1274 struct rk_lcdc_driver *dev_drv = data;
1275 struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1276 struct fb_info *fbi = rk_fb->fb[0];
1278 while (!kthread_should_stop()) {
1279 ktime_t timestamp = dev_drv->vsync_info.timestamp;
1280 int ret = wait_event_interruptible(dev_drv->vsync_info.wait,
1281 !ktime_equal(timestamp, dev_drv->vsync_info.timestamp) &&
1282 (dev_drv->vsync_info.active || dev_drv->vsync_info.irq_stop));
1285 sysfs_notify(&fbi->dev->kobj, NULL, "vsync");
1291 static ssize_t rk_fb_vsync_show(struct device *dev,
1292 struct device_attribute *attr, char *buf)
1294 struct fb_info *fbi = dev_get_drvdata(dev);
1295 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
1296 return scnprintf(buf, PAGE_SIZE, "%llu\n",
1297 ktime_to_ns(dev_drv->vsync_info.timestamp));
1300 static DEVICE_ATTR(vsync, S_IRUGO, rk_fb_vsync_show, NULL);
1303 /*****************************************************************
1304 this two function is for other module that in the kernel which
1305 need show image directly through fb
1306 fb_id:we have 4 fb here,default we use fb0 for ui display
1307 *******************************************************************/
1308 struct fb_info *rk_get_fb(int fb_id)
1310 struct rk_fb *inf = platform_get_drvdata(fb_pdev);
1311 struct fb_info *fb = inf->fb[fb_id];
1314 EXPORT_SYMBOL(rk_get_fb);
1316 void rk_direct_fb_show(struct fb_info *fbi)
1319 rk_pan_display(&fbi->var, fbi);
1321 EXPORT_SYMBOL(rk_direct_fb_show);
1324 static int set_xact_yact_for_hdmi(struct fb_var_screeninfo *pmy_var,
1325 struct fb_var_screeninfo *hdmi_var)
1327 if (pmy_var->xres < pmy_var->yres) { /*vertical lcd screen*/
1328 hdmi_var->xres = pmy_var->yres;
1329 hdmi_var->yres = pmy_var->xres;
1330 hdmi_var->xres_virtual = pmy_var->yres;
1332 hdmi_var->xres = pmy_var->xres;
1333 hdmi_var->yres = pmy_var->yres;
1334 hdmi_var->xres_virtual = pmy_var->xres_virtual;
1340 int rk_fb_dpi_open(bool open)
1342 struct rk_lcdc_driver *dev_drv = NULL;
1343 dev_drv = rk_get_prmry_lcdc_drv();
1344 dev_drv->ops->dpi_open(dev_drv, open);
1348 int rk_fb_dpi_win_sel(int win_id)
1350 struct rk_lcdc_driver *dev_drv = NULL;
1351 dev_drv = rk_get_prmry_lcdc_drv();
1352 dev_drv->ops->dpi_win_sel(dev_drv, win_id);
1356 int rk_fb_dpi_status(void)
1359 struct rk_lcdc_driver *dev_drv = NULL;
1360 dev_drv = rk_get_prmry_lcdc_drv();
1361 ret = dev_drv->ops->dpi_status(dev_drv);
1366 /******************************************
1367 *function:this function will be called by hdmi,when
1369 *screen: the screen attached to hdmi
1370 *enable: 1,hdmi plug in,0,hdmi plug out
1371 *lcdc_id: the lcdc id the hdmi attached ,0 or 1
1372 ******************************************/
1373 int rk_fb_switch_screen(struct rk_screen *screen , int enable, int lcdc_id)
1375 struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1376 struct fb_info *info = NULL;
1377 struct rk_lcdc_driver *dev_drv = NULL;
1378 struct fb_var_screeninfo *hdmi_var = NULL;
1379 struct fb_var_screeninfo *pmy_var = NULL; /*var for primary screen*/
1380 struct fb_info *pmy_info = NULL;
1381 struct fb_fix_screeninfo *pmy_fix = NULL;
1383 struct fb_fix_screeninfo *hdmi_fix = NULL;
1388 if (rk_fb->disp_mode != DUAL)
1389 rk29_backlight_set(0);
1391 sprintf(name, "lcdc%d", lcdc_id);
1393 if (rk_fb->disp_mode != DUAL) {
1394 dev_drv = rk_fb->lcdc_dev_drv[0];
1397 for (i = 0; i < rk_fb->num_lcdc; i++) {
1398 if (rk_fb->lcdc_dev_drv[i]->prop == EXTEND) {
1399 dev_drv = rk_fb->lcdc_dev_drv[i];
1404 if (i == rk_fb->num_lcdc) {
1405 printk(KERN_ERR "%s driver not found!", name);
1409 printk("hdmi %s lcdc%d\n", enable ? "connect to" : "remove from", dev_drv->id);
1411 if (rk_fb->num_lcdc == 1)
1412 info = rk_fb->fb[0];
1413 else if (rk_fb->num_lcdc == 2)
1414 info = rk_fb->fb[dev_drv->num_win]; /*the main fb of lcdc1*/
1416 if (dev_drv->screen1) { /*device like rk2928 ,have only one lcdc but two outputs*/
1418 memcpy(dev_drv->screen1, screen, sizeof(struct rk_screen));
1419 dev_drv->screen1->lcdc_id = 0; /*connect screen1 to output interface 0*/
1420 dev_drv->screen1->screen_id = 1;
1421 dev_drv->screen0->lcdc_id = 1; /*connect screen0 to output interface 1*/
1422 dev_drv->cur_screen = dev_drv->screen1;
1423 dev_drv->screen0->ext_screen = dev_drv->screen1;
1424 if (dev_drv->screen0->sscreen_get) {
1425 dev_drv->screen0->sscreen_get(dev_drv->screen0,
1426 dev_drv->cur_screen->hdmi_resolution);
1431 dev_drv->screen1->lcdc_id = 1; /*connect screen1 to output interface 1*/
1432 dev_drv->screen0->lcdc_id = 0; /*connect screen0 to output interface 0*/
1433 dev_drv->cur_screen = dev_drv->screen0;
1434 dev_drv->screen_ctr_info->set_screen_info(dev_drv->cur_screen,
1435 dev_drv->screen_ctr_info->lcd_info);
1439 memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
1443 win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
1445 if (!enable && !dev_drv->screen1) { /*only double lcdc device need to close*/
1446 if (dev_drv->win[win_id]->state)
1447 dev_drv->ops->open(dev_drv, win_id, enable); /*disable the win which attached to this fb*/
1448 hdmi_switch_complete = 0;
1453 hdmi_var = &info->var;
1454 hdmi_fix = &info->fix;
1455 if (rk_fb->disp_mode == DUAL) {
1456 if (likely(rk_fb->num_lcdc == 2)) {
1457 pmy_var = &rk_fb->fb[0]->var;
1458 pmy_fix = &rk_fb->fb[0]->fix;
1459 set_xact_yact_for_hdmi(pmy_var, hdmi_var);
1460 hdmi_var->nonstd &= 0xffffff00;
1461 hdmi_var->nonstd |= (pmy_var->nonstd & 0xff); /*use the same format as primary screen*/
1463 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!", __func__);
1466 hdmi_var->grayscale &= 0xff;
1467 hdmi_var->grayscale |= (dev_drv->cur_screen->mode.xres<<8) + (dev_drv->cur_screen->mode.yres<<20);
1468 if (dev_drv->screen1) { /*device like rk2928,whic have one lcdc but two outputs*/
1469 /* info->var.nonstd &= 0xff;
1470 info->var.nonstd |= (dev_drv->cur_screen->mode.xpos<<8) + (dev_drv->cur_screen->mode.ypos<<20);
1471 info->var.grayscale &= 0xff;
1472 info->var.grayscale |= (dev_drv->cur_screen->mode.x_res<<8) + (dev_drv->cur_screen->mode.y_res<<20);*/
1473 dev_drv->screen1->xsize = dev_drv->cur_screen->mode.xres;
1474 dev_drv->screen1->ysize = dev_drv->cur_screen->mode.yres;
1475 dev_drv->screen1->xpos = 0;
1476 dev_drv->screen1->ypos = 0;
1479 ret = info->fbops->fb_open(info, 1);
1480 dev_drv->ops->load_screen(dev_drv, 1);
1481 ret = info->fbops->fb_set_par(info);
1482 if (dev_drv->ops->lcdc_hdmi_process)
1483 dev_drv->ops->lcdc_hdmi_process(dev_drv, enable);
1485 if (rk_fb->disp_mode == DUAL) {
1486 if (likely(rk_fb->num_lcdc == 2)) {
1487 pmy_info = rk_fb->fb[0];
1488 pmy_info->fbops->fb_pan_display(pmy_var, pmy_info);
1490 printk(KERN_WARNING "%s>>only one lcdc,dual display no supported!", __func__);
1493 info->fbops->fb_pan_display(hdmi_var, info);
1495 info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0);
1496 if (dev_drv->screen1) {
1497 if (dev_drv->screen0->sscreen_set) {
1498 dev_drv->ops->blank(dev_drv, 0, FB_BLANK_NORMAL);
1500 dev_drv->screen0->sscreen_set(dev_drv->screen0, enable);
1501 dev_drv->ops->blank(dev_drv, 0, FB_BLANK_UNBLANK);
1505 if (rk_fb->disp_mode != DUAL)
1506 rk29_backlight_set(1);
1507 hdmi_switch_complete = enable;
1515 /******************************************
1516 function:this function current only called by hdmi for
1518 scale_x: scale rate of x resolution
1519 scale_y: scale rate of y resolution
1520 lcdc_id: the lcdc id the hdmi attached ,0 or 1
1521 ******************************************/
1523 int rk_fb_disp_scale(u8 scale_x, u8 scale_y, u8 lcdc_id)
1525 struct rk_fb *inf = platform_get_drvdata(fb_pdev);
1526 struct fb_info *info = NULL;
1527 struct fb_var_screeninfo *var = NULL;
1528 struct rk_lcdc_driver *dev_drv = NULL;
1529 u16 screen_x, screen_y;
1534 sprintf(name, "lcdc%d", lcdc_id);
1536 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
1537 dev_drv = inf->lcdc_dev_drv[0];
1539 for (i = 0; i < inf->num_lcdc; i++) {
1540 if (inf->lcdc_dev_drv[i]->prop == EXTEND) {
1541 dev_drv = inf->lcdc_dev_drv[i];
1546 if (i == inf->num_lcdc) {
1547 printk(KERN_ERR "%s driver not found!", name);
1552 if (inf->num_lcdc == 1)
1554 else if (inf->num_lcdc == 2)
1555 info = inf->fb[dev_drv->num_win];
1558 screen_x = dev_drv->cur_screen->mode.xres;
1559 screen_y = dev_drv->cur_screen->mode.yres;
1561 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF) || defined(CONFIG_NO_DUAL_DISP)
1562 if (dev_drv->cur_screen->screen_id == 1) {
1563 dev_drv->cur_screen->xpos = (screen_x-screen_x*scale_x/100)>>1;
1564 dev_drv->cur_screen->ypos = (screen_y-screen_y*scale_y/100)>>1;
1565 dev_drv->cur_screen->xsize = screen_x*scale_x/100;
1566 dev_drv->cur_screen->ysize = screen_y*scale_y/100;
1570 xpos = (screen_x-screen_x*scale_x/100)>>1;
1571 ypos = (screen_y-screen_y*scale_y/100)>>1;
1572 xsize = screen_x*scale_x/100;
1573 ysize = screen_y*scale_y/100;
1574 var->nonstd &= 0xff;
1575 var->nonstd |= (xpos<<8) + (ypos<<20);
1576 var->grayscale &= 0xff;
1577 var->grayscale |= (xsize<<8) + (ysize<<20);
1580 info->fbops->fb_set_par(info);
1581 info->fbops->fb_ioctl(info, RK_FBIOSET_CONFIG_DONE, 0);
1587 static int rk_fb_alloc_buffer(struct fb_info *fbi, int fb_id)
1589 struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1590 struct rk_lcdc_driver *dev_drv = (struct rk_lcdc_driver *)fbi->par;
1591 struct rk_lcdc_win *win = NULL;
1594 unsigned long fb_mem_size;
1595 #if defined(CONFIG_ION_ROCKCHIP)
1596 struct ion_handle *handle;
1597 ion_phys_addr_t phy_addr;
1600 dma_addr_t fb_mem_phys;
1603 win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
1607 win = dev_drv->win[win_id];
1609 if (!strcmp(fbi->fix.id, "fb0")) {
1610 fb_mem_size = 3 * (fbi->var.xres * fbi->var.yres) << 2;
1611 fb_mem_size = ALIGN(fb_mem_size, SZ_1M);
1612 #if defined(CONFIG_ION_ROCKCHIP)
1613 handle = ion_alloc(rk_fb->ion_client, (size_t)fb_mem_size, 0, ION_HEAP(ION_CMA_HEAP_ID), 0);
1614 if (IS_ERR(handle)) {
1615 dev_err(fbi->device, "failed to ion_alloc:%ld\n",PTR_ERR(handle));
1618 win->ion_hdl = handle;
1619 fbi->screen_base = ion_map_kernel(rk_fb->ion_client, handle);
1620 ion_phys(rk_fb->ion_client, handle, &phy_addr, &len);
1621 fbi->fix.smem_start = phy_addr;
1622 fbi->fix.smem_len = len;
1625 fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size, &fb_mem_phys,
1628 pr_err("%s: Failed to allocate framebuffer\n", __func__);
1631 fbi->fix.smem_len = fb_mem_size;
1632 fbi->fix.smem_start = fb_mem_phys;
1633 fbi->screen_base = fb_mem_virt;
1635 memset(fbi->screen_base, 0, fbi->fix.smem_len);
1636 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
1637 fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
1639 #if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
1640 res = platform_get_resource_byname(fb_pdev,
1641 IORESOURCE_MEM, "fb2 buf");
1643 dev_err(&fb_pdev->dev, "failed to get win0 memory \n");
1646 fbi->fix.smem_start = res->start;
1647 fbi->fix.smem_len = res->end - res->start + 1;
1648 mem = request_mem_region(res->start, resource_size(res),
1650 fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
1651 memset(fbi->screen_base, 0, fbi->fix.smem_len);
1652 #else /*three buffer no need to copy*/
1653 fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start;
1654 fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len;
1655 fbi->screen_base = rk_fb->fb[0]->screen_base;
1657 printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
1658 fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
1661 fbi->screen_size = fbi->fix.smem_len;
1662 win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
1664 win = dev_drv->win[win_id];
1665 win->reserved = fbi->fix.smem_start;
1671 static int rk_release_fb_buffer(struct fb_info *fbi)
1673 if (!strcmp(fbi->fix.id, "fb1") || !strcmp(fbi->fix.id, "fb3")) /*buffer for fb1 and fb3 are alloc by android*/
1675 iounmap(fbi->screen_base);
1676 release_mem_region(fbi->fix.smem_start, fbi->fix.smem_len);
1680 static int init_lcdc_win(struct rk_lcdc_driver *dev_drv, struct rk_lcdc_win *def_win)
1683 int num_win = dev_drv->num_win;
1684 for (i = 0; i < num_win; i++) {
1685 struct rk_lcdc_win *win = NULL;
1686 win = kzalloc(sizeof(struct rk_lcdc_win), GFP_KERNEL);
1688 dev_err(dev_drv->dev, "kzmalloc for win fail!");
1692 strcpy(win->name, def_win->name);
1693 win->id = def_win->id;
1694 win->support_3d = def_win->support_3d;
1695 dev_drv->win[i] = win;
1702 static int init_lcdc_device_driver(struct rk_fb *rk_fb,
1703 struct rk_lcdc_win *def_win, int index)
1705 struct rk_lcdc_driver *dev_drv = rk_fb->lcdc_dev_drv[index];
1706 struct rk_screen *screen = devm_kzalloc(dev_drv->dev,
1707 sizeof(struct rk_screen), GFP_KERNEL);
1709 dev_err(dev_drv->dev, "malloc screen for lcdc%d fail!",
1714 screen->screen_id = 0;
1715 screen->lcdc_id = dev_drv->id;
1716 dev_drv->screen0 = screen;
1717 dev_drv->cur_screen = screen;
1718 /* devie use one lcdc + rk61x scaler for dual display*/
1719 if (rk_fb->disp_mode == ONE_DUAL) {
1720 struct rk_screen *screen1 = devm_kzalloc(dev_drv->dev,
1721 sizeof(struct rk_screen), GFP_KERNEL);
1723 dev_err(dev_drv->dev, "malloc screen1 for lcdc%d fail!",
1727 screen1->screen_id = 1;
1728 screen1->lcdc_id = 1;
1729 dev_drv->screen1 = screen1;
1731 sprintf(dev_drv->name, "lcdc%d", dev_drv->id);
1732 init_lcdc_win(dev_drv, def_win);
1733 init_completion(&dev_drv->frame_done);
1734 spin_lock_init(&dev_drv->cpl_lock);
1735 mutex_init(&dev_drv->fb_win_id_mutex);
1736 dev_drv->ops->fb_win_remap(dev_drv, FB_DEFAULT_ORDER);
1737 dev_drv->first_frame = 1;
1738 rk_disp_pwr_ctr_parse_dt(dev_drv);
1739 rk_disp_prase_timing_dt(dev_drv);
1744 #ifdef CONFIG_LOGO_LINUX_BMP
1745 static struct linux_logo *bmp_logo;
1746 static int fb_prewine_bmp_logo(struct fb_info *info, int rotate)
1748 bmp_logo = fb_find_logo(24);
1749 if (bmp_logo == NULL) {
1750 printk(KERN_INFO "%s error\n", __func__);
1756 static void fb_show_bmp_logo(struct fb_info *info, int rotate)
1758 unsigned char *src = bmp_logo->data;
1759 unsigned char *dst = info->screen_base;
1761 unsigned int Needwidth = (*(src-24)<<8) | (*(src-23));
1762 unsigned int Needheight = (*(src-22)<<8) | (*(src-21));
1764 for (i = 0; i < Needheight; i++)
1765 memcpy(dst+info->var.xres*i*4,
1766 src+bmp_logo->width*i*4, Needwidth*4);
1771 /********************************
1772 *check if the primary lcdc has registerd,
1773 the primary lcdc mas register first
1774 *********************************/
1775 bool is_prmry_rk_lcdc_registered(void)
1777 struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1778 if (rk_fb->lcdc_dev_drv[0])
1785 int rk_fb_register(struct rk_lcdc_driver *dev_drv,
1786 struct rk_lcdc_win *win, int id)
1788 struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
1789 struct fb_info *fbi;
1790 int i = 0, ret = 0, index = 0;
1792 if (rk_fb->num_lcdc == RK30_MAX_LCDC_SUPPORT)
1795 for (i = 0; i < RK30_MAX_LCDC_SUPPORT; i++) {
1796 if (!rk_fb->lcdc_dev_drv[i]) {
1797 rk_fb->lcdc_dev_drv[i] = dev_drv;
1798 rk_fb->lcdc_dev_drv[i]->id = id;
1805 init_lcdc_device_driver(rk_fb, win, index);
1806 dev_drv->fb_index_base = rk_fb->num_fb;
1807 for (i = 0; i < dev_drv->num_win; i++) {
1808 fbi = framebuffer_alloc(0, &fb_pdev->dev);
1810 dev_err(&fb_pdev->dev, "fb framebuffer_alloc fail!");
1816 sprintf(fbi->fix.id, "fb%d", rk_fb->num_fb);
1817 fb_videomode_to_var(&fbi->var, &dev_drv->cur_screen->mode);
1818 fbi->var.grayscale |= (fbi->var.xres<<8) + (fbi->var.yres<<20);
1819 #if defined(CONFIG_LOGO_LINUX_BMP)
1820 fbi->var.bits_per_pixel = 32;
1822 fbi->var.bits_per_pixel = 16;
1824 fbi->fix.line_length = (fbi->var.xres)*(fbi->var.bits_per_pixel>>3);
1825 fbi->var.width = dev_drv->cur_screen->width;
1826 fbi->var.height = dev_drv->cur_screen->height;
1827 fbi->var.pixclock = dev_drv->pixclock;
1828 fbi->fbops = &fb_ops;
1829 fbi->flags = FBINFO_FLAG_DEFAULT;
1830 fbi->pseudo_palette = dev_drv->win[i]->pseudo_pal;
1831 if (i == 0) /* only alloc memory for main fb*/
1832 rk_fb_alloc_buffer(fbi, rk_fb->num_fb);
1833 ret = register_framebuffer(fbi);
1835 dev_err(&fb_pdev->dev, "%s fb%d register_framebuffer fail!\n",
1836 __func__, rk_fb->num_fb);
1839 rkfb_create_sysfs(fbi);
1840 rk_fb->fb[rk_fb->num_fb] = fbi;
1841 dev_info(&fb_pdev->dev, "rockchip framebuffer registerd:%s\n",
1846 init_waitqueue_head(&dev_drv->vsync_info.wait);
1847 ret = device_create_file(fbi->dev, &dev_attr_vsync);
1849 dev_err(fbi->dev, "failed to create vsync file\n");
1850 dev_drv->vsync_info.thread = kthread_run(rk_fb_wait_for_vsync_thread,
1851 dev_drv, "fb-vsync");
1852 if (dev_drv->vsync_info.thread == ERR_PTR(-ENOMEM)) {
1853 dev_err(fbi->dev, "failed to run vsync thread\n");
1854 dev_drv->vsync_info.thread = NULL;
1856 dev_drv->vsync_info.active = 1;
1861 /*show logo for primary display device*/
1862 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
1863 if (dev_drv->prop == PRMRY) {
1864 struct fb_info *main_fbi = rk_fb->fb[0];
1865 main_fbi->fbops->fb_open(main_fbi, 1);
1866 main_fbi->fbops->fb_set_par(main_fbi);
1867 #if defined(CONFIG_LOGO_LINUX_BMP)
1868 if (fb_prewine_bmp_logo(main_fbi, FB_ROTATE_UR)) {
1869 fb_set_cmap(&main_fbi->cmap, main_fbi);
1870 fb_show_bmp_logo(main_fbi, FB_ROTATE_UR);
1871 main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
1874 if (fb_prepare_logo(main_fbi, FB_ROTATE_UR)) {
1875 fb_set_cmap(&main_fbi->cmap, main_fbi);
1876 fb_show_logo(main_fbi, FB_ROTATE_UR);
1877 main_fbi->fbops->fb_pan_display(&main_fbi->var, main_fbi);
1880 main_fbi->fbops->fb_ioctl(main_fbi, RK_FBIOSET_CONFIG_DONE, 0);
1888 int rk_fb_unregister(struct rk_lcdc_driver *dev_drv)
1891 struct rk_fb *fb_inf = platform_get_drvdata(fb_pdev);
1892 struct fb_info *fbi;
1893 int fb_index_base = dev_drv->fb_index_base;
1894 int fb_num = dev_drv->num_win;
1897 if (fb_inf->lcdc_dev_drv[i]->vsync_info.thread) {
1898 fb_inf->lcdc_dev_drv[i]->vsync_info.irq_stop = 1;
1899 kthread_stop(fb_inf->lcdc_dev_drv[i]->vsync_info.thread);
1902 for (i = 0; i < fb_num; i++)
1903 kfree(dev_drv->win[i]);
1905 for (i = fb_index_base; i < (fb_index_base+fb_num); i++) {
1906 fbi = fb_inf->fb[i];
1907 unregister_framebuffer(fbi);
1908 /*rk_release_fb_buffer(fbi);*/
1909 framebuffer_release(fbi);
1911 fb_inf->lcdc_dev_drv[dev_drv->id] = NULL;
1919 #if defined(CONFIG_HAS_EARLYSUSPEND)
1920 struct suspend_info {
1921 struct early_suspend early_suspend;
1925 static void rkfb_early_suspend(struct early_suspend *h)
1927 struct suspend_info *info = container_of(h, struct suspend_info,
1929 struct rk_fb *inf = info->inf;
1931 for (i = 0; i < inf->num_lcdc; i++) {
1932 if (!inf->lcdc_dev_drv[i])
1934 inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
1937 static void rkfb_early_resume(struct early_suspend *h)
1939 struct suspend_info *info = container_of(h, struct suspend_info,
1941 struct rk_fb *inf = info->inf;
1943 for (i = 0; i < inf->num_lcdc; i++) {
1944 if (!inf->lcdc_dev_drv[i])
1946 inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
1953 static struct suspend_info suspend_info = {
1954 .early_suspend.suspend = rkfb_early_suspend,
1955 .early_suspend.resume = rkfb_early_resume,
1956 .early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB,
1960 static int rk_fb_probe(struct platform_device *pdev)
1962 struct rk_fb *rk_fb = NULL;
1963 struct device_node *np = pdev->dev.of_node;
1967 dev_err(&pdev->dev, "Missing device tree node.\n");
1971 rk_fb = devm_kzalloc(&pdev->dev, sizeof(struct rk_fb), GFP_KERNEL);
1973 dev_err(&pdev->dev, "kmalloc for rk fb fail!");
1976 platform_set_drvdata(pdev, rk_fb);
1978 if (!of_property_read_u32(np, "rockchip,disp-mode", &mode)) {
1979 rk_fb->disp_mode = mode;
1982 dev_err(&pdev->dev, "no disp-mode node found!");
1985 dev_set_name(&pdev->dev, "rockchip-fb");
1986 #if defined(CONFIG_ION_ROCKCHIP)
1987 rk_fb->ion_client = rockchip_ion_client_create("rk_fb");
1988 if (IS_ERR(rk_fb->ion_client)) {
1989 dev_err(&pdev->dev, "failed to create ion client for rk fb");
1990 return PTR_ERR(rk_fb->ion_client);
1992 dev_info(&pdev->dev, "rk fb ion client create success!\n");
1996 #if defined(CONFIG_HAS_EARLYSUSPEND)
1997 suspend_info.inf = rk_fb;
1998 register_early_suspend(&suspend_info.early_suspend);
2001 dev_info(&pdev->dev, "rockchip framebuffer driver probe\n");
2005 static int rk_fb_remove(struct platform_device *pdev)
2007 struct rk_fb *rk_fb = platform_get_drvdata(pdev);
2009 platform_set_drvdata(pdev, NULL);
2013 static void rk_fb_shutdown(struct platform_device *pdev)
2015 struct rk_fb *rk_fb = platform_get_drvdata(pdev);
2017 for (i = 0; i < rk_fb->num_lcdc; i++) {
2018 if (!rk_fb->lcdc_dev_drv[i])
2023 #if defined(CONFIG_HAS_EARLYSUSPEND)
2024 unregister_early_suspend(&suspend_info.early_suspend);
2029 static const struct of_device_id rkfb_dt_ids[] = {
2030 { .compatible = "rockchip,rk-fb", },
2034 static struct platform_driver rk_fb_driver = {
2035 .probe = rk_fb_probe,
2036 .remove = rk_fb_remove,
2039 .owner = THIS_MODULE,
2040 .of_match_table = of_match_ptr(rkfb_dt_ids),
2042 .shutdown = rk_fb_shutdown,
2045 static int __init rk_fb_init(void)
2047 return platform_driver_register(&rk_fb_driver);
2050 static void __exit rk_fb_exit(void)
2052 platform_driver_unregister(&rk_fb_driver);
2055 subsys_initcall_sync(rk_fb_init);
2056 module_exit(rk_fb_exit);