rk fb: add support phy address config
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / rk_fb.c
index f5d9cd08c731cb349b9517ffe7ba1ff65beef187..5ae5a4c113a383c550a9c07fc91daa899920d876 100755 (executable)
@@ -99,6 +99,8 @@ int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
        case SCREEN_RGB:
        case SCREEN_LVDS:
        case SCREEN_DUAL_LVDS:
+       case SCREEN_LVDS_10BIT:
+       case SCREEN_DUAL_LVDS_10BIT:
                trsm_lvds_ops = ops;
                break;
        case SCREEN_EDP:
@@ -123,6 +125,8 @@ struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
        case SCREEN_RGB:
        case SCREEN_LVDS:
        case SCREEN_DUAL_LVDS:
+       case SCREEN_LVDS_10BIT:
+       case SCREEN_DUAL_LVDS_10BIT:
                ops = trsm_lvds_ops;
                break;
        case SCREEN_EDP:
@@ -148,12 +152,16 @@ int rk_fb_pixel_width(int data_format)
        case XBGR888:
        case ABGR888:
        case ARGB888:
+       case FBDC_ARGB_888:
+       case FBDC_ABGR_888:
+       case FBDC_RGBX_888:
                pixel_width = 4 * 8;
                break;
        case RGB888:
                pixel_width = 3 * 8;
                break;
        case RGB565:
+       case FBDC_RGB_565:
                pixel_width = 2 * 8;
                break;
        case YUV422:
@@ -216,6 +224,18 @@ static int rk_fb_data_fmt(int data_format, int bits_per_pixel)
                case HAL_PIXEL_FORMAT_YCrCb_420_SP_10:  /* yuv444 */
                        fb_data_fmt = YUV444_A;
                        break;
+               case HAL_PIXEL_FORMAT_FBDC_RGB565:      /* fbdc rgb565*/
+                       fb_data_fmt = FBDC_RGB_565;
+                       break;
+               case HAL_PIXEL_FORMAT_FBDC_U8U8U8U8:    /* fbdc argb888 */
+                       fb_data_fmt = FBDC_ARGB_888;
+                       break;
+               case HAL_PIXEL_FORMAT_FBDC_RGBA888:     /* fbdc abgr888 */
+                       fb_data_fmt = FBDC_ABGR_888;
+                       break;
+               case HAL_PIXEL_FORMAT_FBDC_U8U8U8:      /* fbdc rgb888 */
+                       fb_data_fmt = FBDC_RGBX_888;
+                       break;
                default:
                        printk(KERN_WARNING "%s:un supported format:0x%x\n",
                               __func__, data_format);
@@ -534,6 +554,16 @@ char *get_format_string(enum data_format format, char *fmt)
        case ABGR888:
                strcpy(fmt, "ABGR888");
                break;
+       case FBDC_RGB_565:
+               strcpy(fmt, "FBDC_RGB_565");
+               break;
+       case FBDC_ARGB_888:
+       case FBDC_ABGR_888:
+               strcpy(fmt, "FBDC_ARGB_888");
+               break;
+       case FBDC_RGBX_888:
+               strcpy(fmt, "FBDC_RGBX_888");
+               break;
        default:
                strcpy(fmt, "invalid");
                break;
@@ -1460,7 +1490,8 @@ void rk_fb_free_dma_buf(struct rk_lcdc_driver *dev_drv,
                index_buf = area_data->index_buf;
 #if defined(CONFIG_ROCKCHIP_IOMMU)
                if (dev_drv->iommu_enabled) {
-                       if (rk_fb->disp_policy != DISPLAY_POLICY_BOX)
+                       if ((rk_fb->disp_policy != DISPLAY_POLICY_BOX) &&
+                            (area_data->ion_handle != NULL))
                                ion_unmap_iommu(dev_drv->dev, rk_fb->ion_client,
                                                area_data->ion_handle);
                        freed_addr[freed_index++] = area_data->smem_start;
@@ -1820,6 +1851,7 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
        u8 ppixel_a = 0, global_a = 0;
        ion_phys_addr_t phy_addr;
        int ret = 0;
+       int buff_len;
 
        reg_win_data->reg_area_data[0].smem_start = -1;
        reg_win_data->area_num = 0;
@@ -1861,12 +1893,14 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
                                reg_win_data->reg_area_data[i].smem_start = phy_addr;
                                reg_win_data->area_buf_num++;
                                reg_win_data->reg_area_data[i].index_buf = 1;
+                               reg_win_data->reg_area_data[i].buff_len = len;
                        }
                }
        } else {
                reg_win_data->reg_area_data[0].smem_start =
                    win_par->area_par[0].phy_addr;
                reg_win_data->area_num = 1;
+               reg_win_data->area_buf_num++;
                fbi->screen_base = phys_to_virt(win_par->area_par[0].phy_addr);
        }
 
@@ -1890,19 +1924,23 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
        }
 
        reg_win_data->mirror_en = win_par->mirror_en;
-       reg_win_data->reg_area_data[0].fbdc_en = win_par->area_par[0].fbdc_en;
-       reg_win_data->reg_area_data[0].fbdc_cor_en =
-               win_par->area_par[0].fbdc_cor_en;
-       reg_win_data->reg_area_data[0].fbdc_data_format =
-               win_par->area_par[0].fbdc_data_format;
        for (i = 0; i < reg_win_data->area_num; i++) {
                rk_fb_check_config_var(&win_par->area_par[i], screen);
 
                fb_data_fmt = rk_fb_data_fmt(win_par->area_par[i].data_format, 0);
                reg_win_data->reg_area_data[i].data_format = fb_data_fmt;
+               if (fb_data_fmt >= FBDC_RGB_565) {
+                       reg_win_data->reg_area_data[i].fbdc_en = 1;
+                       reg_win_data->reg_area_data[i].fbdc_cor_en = 1;
+               } else {
+                       reg_win_data->reg_area_data[i].fbdc_en = 0;
+                       reg_win_data->reg_area_data[i].fbdc_cor_en = 0;
+               }
                pixel_width = rk_fb_pixel_width(fb_data_fmt);
 
                ppixel_a |= ((fb_data_fmt == ARGB888) ||
+                            (fb_data_fmt == FBDC_ARGB_888) ||
+                            (fb_data_fmt == FBDC_ABGR_888) ||
                             (fb_data_fmt == ABGR888)) ? 1 : 0;
                /* visiable pos in panel */
                reg_win_data->reg_area_data[i].xpos = win_par->area_par[i].xpos;
@@ -1962,6 +2000,26 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
                                    xoffset * pixel_width / 8;
                        }
                }
+               if ((fb_data_fmt != YUV420) &&
+                   (fb_data_fmt != YUV420_NV21) &&
+                   (fb_data_fmt != YUV422) &&
+                    (fb_data_fmt != YUV444)) {
+                        buff_len = reg_win_data->reg_area_data[i].y_offset +
+                                reg_win_data->reg_area_data[i].xvir *
+                                reg_win_data->reg_area_data[i].yact *
+                                pixel_width / 8 -
+                                reg_win_data->reg_area_data[i].xoff*
+                                pixel_width / 8;
+                        if (buff_len > reg_win_data->reg_area_data[i].buff_len)
+                                pr_err("\n!!!!!!error: fmt=%d,xvir[%d]*"
+                                       "yact[%d]*bpp[%d]"
+                                       "=buff_len[0x%x]>>mmu len=0x%x\n",
+                                       fb_data_fmt,
+                                       reg_win_data->reg_area_data[i].xvir,
+                                       reg_win_data->reg_area_data[i].yact,
+                                       pixel_width, buff_len,
+                                       reg_win_data->reg_area_data[i].buff_len);
+               }
        }
 
        global_a = (win_par->g_alpha_val == 0) ? 0 : 1;
@@ -2031,6 +2089,23 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
                                    uv_x_off * pixel_width / 8;
                        }
                }
+               buff_len = reg_win_data->reg_area_data[0].cbr_start +
+                       reg_win_data->reg_area_data[0].c_offset +
+                       reg_win_data->reg_area_data[0].xvir *
+                       reg_win_data->reg_area_data[0].yact *
+                       pixel_width / 16 -
+                       reg_win_data->reg_area_data[0].smem_start -
+                       reg_win_data->reg_area_data[0].xoff*
+                       pixel_width / 16 ;
+               if (buff_len > reg_win_data->reg_area_data[0].buff_len)
+                       pr_err("\n!!!!!!error: fmt=%d,xvir[%d]*"
+                              "yact[%d]*bpp[%d]"
+                              "=buff_len[0x%x]>>mmu len=0x%x\n",
+                              fb_data_fmt,
+                              reg_win_data->reg_area_data[0].xvir,
+                              reg_win_data->reg_area_data[0].yact,
+                              pixel_width, buff_len,
+                              reg_win_data->reg_area_data[0].buff_len);
        }
 
        /* record buffer information for rk_fb_disp_scale to prevent fence timeout
@@ -2745,6 +2820,13 @@ static int rk_fb_set_par(struct fb_info *info)
        }
 
        fb_data_fmt = rk_fb_data_fmt(data_format, var->bits_per_pixel);
+       if (fb_data_fmt >= FBDC_RGB_565) {
+               win->area[0].fbdc_en = 1;
+               win->area[0].fbdc_cor_en = 1;
+       } else {
+               win->area[0].fbdc_en = 0;
+               win->area[0].fbdc_cor_en = 0;
+       }
        pixel_width = rk_fb_pixel_width(fb_data_fmt);
        vir_width_bit = pixel_width * xvir;
        /* pixel_width = byte_num * 8 */
@@ -2854,6 +2936,8 @@ static int rk_fb_set_par(struct fb_info *info)
        win->area_num = 1;
        win->alpha_mode = 4;    /* AB_SRC_OVER; */
        win->alpha_en = ((win->area[0].format == ARGB888) ||
+                        (win->area[0].format == FBDC_ARGB_888) ||
+                        (win->area[0].format == FBDC_ABGR_888) ||
                         (win->area[0].format == ABGR888)) ? 1 : 0;
        win->g_alpha_val = 0;