rk fb: add support yuv420sp nv21 data format
authorhjc <hjc@rock-chips.com>
Mon, 9 Mar 2015 03:14:14 +0000 (11:14 +0800)
committerhjc <hjc@rock-chips.com>
Mon, 9 Mar 2015 04:30:37 +0000 (12:30 +0800)
Signed-off-by: hjc <hjc@rock-chips.com>
drivers/video/rockchip/lcdc/rk312x_lcdc.c
drivers/video/rockchip/lcdc/rk3288_lcdc.c
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_fb.h

index c6662d009cb6cf7ddb94e99a636b4a71fcac282a..e714c929a32bcc6c1698f4938fea195e40a7e4cd 100755 (executable)
@@ -416,10 +416,12 @@ static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev,
                        lcdc_layer_csc_mode(lcdc_dev, win);
 
                if (win->id == 0) {
-                       mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP;
+                       mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP |
+                               m_WIN0_UV_SWAP;
                        val = v_WIN0_EN(win->state) |
                                v_WIN0_FORMAT(win->area[0].fmt_cfg) |
-                               v_WIN0_RB_SWAP(win->area[0].swap_rb);
+                               v_WIN0_RB_SWAP(win->area[0].swap_rb) |
+                               v_WIN0_UV_SWAP(win->area[0].swap_uv);
                        lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
                        lcdc_writel(lcdc_dev, WIN0_SCL_FACTOR_YRGB,
                                    v_X_SCL_FACTOR(win->scale_yrgb_x) |
@@ -1531,18 +1533,22 @@ static int rk312x_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
        case ARGB888:
                win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
                win->area[0].swap_rb = 0;
+               win->area[0].swap_uv = 0;
                break;
        case XBGR888:
                win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
                win->area[0].swap_rb = 1;
+               win->area[0].swap_uv = 0;
                break;
        case ABGR888:
                win->area[0].fmt_cfg = VOP_FORMAT_ARGB888;
                win->area[0].swap_rb = 1;
+               win->area[0].swap_uv = 0;
                break;
        case RGB888:
                win->area[0].fmt_cfg = VOP_FORMAT_RGB888;
                win->area[0].swap_rb = 0;
+               win->area[0].swap_uv = 0;
                break;
        case RGB565:
                win->area[0].fmt_cfg = VOP_FORMAT_RGB565;
@@ -1556,6 +1562,7 @@ static int rk312x_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                        win->scale_cbcr_y =
                            CalScale(win->area[0].yact, win->area[0].ysize);
                        win->area[0].swap_rb = 0;
+                       win->area[0].swap_uv = 0;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n", __func__);
@@ -1569,6 +1576,7 @@ static int rk312x_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                        win->scale_cbcr_y =
                            CalScale(win->area[0].yact, win->area[0].ysize);
                        win->area[0].swap_rb = 0;
+                       win->area[0].swap_uv = 0;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n", __func__);
@@ -1582,6 +1590,21 @@ static int rk312x_lcdc_set_par(struct rk_lcdc_driver *dev_drv, int win_id)
                        win->scale_cbcr_y =
                            CalScale(win->area[0].yact / 2, win->area[0].ysize);
                        win->area[0].swap_rb = 0;
+                       win->area[0].swap_uv = 0;
+               } else {
+                       dev_err(lcdc_dev->driver.dev,
+                               "%s:un supported format!\n", __func__);
+               }
+               break;
+       case YUV420_NV21:
+               if (win_id == 0) {
+                       win->area[0].fmt_cfg = VOP_FORMAT_YCBCR420;
+                       win->scale_cbcr_x =
+                           CalScale(win->area[0].xact / 2, win->area[0].xsize);
+                       win->scale_cbcr_y =
+                           CalScale(win->area[0].yact / 2, win->area[0].ysize);
+                       win->area[0].swap_rb = 0;
+                       win->area[0].swap_uv = 1;
                } else {
                        dev_err(lcdc_dev->driver.dev,
                                "%s:un supported format!\n", __func__);
index 3b0bf195959c82b3b278f7b440c4685fca1ba7eb..3f5ced0dd7f814db2cb8e9581da3961e0a1e2500 100755 (executable)
@@ -767,12 +767,13 @@ static int rk3288_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv,int win_id)
 
        if(win->state == 1){
                mask =  m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
-                       m_WIN0_LB_MODE | m_WIN0_RB_SWAP;
+                       m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_UV_SWAP;
                val  =  v_WIN0_EN(win->state) |
                        v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
                        v_WIN0_FMT_10(win->fmt_10) | 
                        v_WIN0_LB_MODE(win->win_lb_mode) | 
-                       v_WIN0_RB_SWAP(win->area[0].swap_rb);
+                       v_WIN0_RB_SWAP(win->area[0].swap_rb) |
+                       v_WIN0_UV_SWAP(win->area[0].swap_uv);
                lcdc_msk_reg(lcdc_dev, WIN0_CTRL0+off, mask,val);       
        
                mask =  m_WIN0_BIC_COE_SEL |
@@ -2043,7 +2044,7 @@ static int win0_set_par(struct lcdc_device *lcdc_dev,
                        struct rk_screen *screen, struct rk_lcdc_win *win)
 {
        u32 xact,yact,xvir, yvir,xpos, ypos;
-       u8 fmt_cfg = 0, swap_rb;
+       u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
        char fmt[9] = "NULL";
 
        xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
@@ -2084,6 +2085,12 @@ static int win0_set_par(struct lcdc_device *lcdc_dev,
                        swap_rb = 0;
                        win->fmt_10 = 0;
                        break;
+               case YUV420_NV21:
+                       fmt_cfg = 4;
+                       swap_rb = 0;
+                       swap_uv = 1;
+                       win->fmt_10 = 0;
+                       break;  
                case YUV444:    
                        fmt_cfg = 6;
                        swap_rb = 0;
@@ -2112,6 +2119,7 @@ static int win0_set_par(struct lcdc_device *lcdc_dev,
                win->area[0].swap_rb = swap_rb;
                win->area[0].dsp_stx = xpos;
                win->area[0].dsp_sty = ypos;
+               win->area[0].swap_uv = swap_uv;
                xact = win->area[0].xact;
                yact = win->area[0].yact;
                xvir = win->area[0].xvir;
@@ -2132,7 +2140,7 @@ static int win1_set_par(struct lcdc_device *lcdc_dev,
                        struct rk_screen *screen, struct rk_lcdc_win *win)
 {
        u32 xact, yact, xvir, yvir, xpos, ypos;
-       u8 fmt_cfg = 0, swap_rb;
+       u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
        char fmt[9] = "NULL";
 
        xpos = win->area[0].xpos + screen->mode.left_margin + screen->mode.hsync_len;
@@ -2173,6 +2181,12 @@ static int win1_set_par(struct lcdc_device *lcdc_dev,
                        swap_rb = 0;
                        win->fmt_10 = 0;
                        break;
+               case YUV420_NV21:
+                       fmt_cfg = 4;
+                       swap_rb = 0;
+                       swap_uv = 1;
+                       win->fmt_10 = 0;
+                       break;
                case YUV444:
                        fmt_cfg = 6;
                        swap_rb = 0;
@@ -2202,6 +2216,7 @@ static int win1_set_par(struct lcdc_device *lcdc_dev,
                win->area[0].swap_rb = swap_rb;
                win->area[0].dsp_stx = xpos;
                win->area[0].dsp_sty = ypos;
+               win->area[0].swap_uv = swap_uv;
                xact = win->area[0].xact;
                yact = win->area[0].yact;
                xvir = win->area[0].xvir;
index 55177cc9d7116f8b5d3db0b2b8b1c5688b44c670..f5d9cd08c731cb349b9517ffe7ba1ff65beef187 100755 (executable)
@@ -158,6 +158,7 @@ int rk_fb_pixel_width(int data_format)
                break;
        case YUV422:
        case YUV420:
+       case YUV420_NV21:
        case YUV444:
                pixel_width = 1 * 8;
                break;
@@ -197,6 +198,9 @@ static int rk_fb_data_fmt(int data_format, int bits_per_pixel)
                case HAL_PIXEL_FORMAT_YCbCr_422_SP:     /* yuv422 */
                        fb_data_fmt = YUV422;
                        break;
+               case HAL_PIXEL_FORMAT_YCrCb_420_SP:     /* YUV420---vuvuvu */
+                       fb_data_fmt = YUV420_NV21;
+                       break;
                case HAL_PIXEL_FORMAT_YCrCb_NV12:       /* YUV420---uvuvuv */
                        fb_data_fmt = YUV420;
                        break;
@@ -503,6 +507,7 @@ char *get_format_string(enum data_format format, char *fmt)
                strcpy(fmt, "RGB565");
                break;
        case YUV420:
+       case YUV420_NV21:
                strcpy(fmt, "YUV420");
                break;
        case YUV422:
@@ -1257,7 +1262,8 @@ static int rk_fb_pan_display(struct fb_var_screeninfo *var,
                fix->line_length = stride;
                uv_y_act = win->area[0].yact >> 1;
                break;
-       case YUV420:            /* 420sp */
+       case YUV420:            /* nv12 */
+       case YUV420_NV21:       /* nv21 */
        case YUV420_A:
                is_pic_yuv = 1;
                stride = stride_32bit_1;
@@ -1640,6 +1646,7 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
                if (win_data) {
                        if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
                            (win_data->reg_area_data[0].data_format == YUV420 ||
+                            win_data->reg_area_data[0].data_format == YUV420_NV21 ||
                             win_data->reg_area_data[0].data_format == YUV420_A))
                                continue;
                        mutex_lock(&dev_drv->win_config);
@@ -1973,7 +1980,8 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
                fix->line_length = stride;
                uv_y_act = win_par->area_par[0].yact >> 1;
                break;
-       case YUV420:            /* 420sp */
+       case YUV420:            /* nv12 */
+       case YUV420_NV21:       /* nv21 */
        case YUV420_A:
                is_pic_yuv = 1;
                stride = stride_32bit_1;
@@ -2575,7 +2583,8 @@ static ssize_t rk_fb_read(struct fb_info *info, char __user *buf,
        /* only read the current frame buffer */
        if (win->area[0].format == RGB565) {
                total_size = win->area[0].y_vir_stride * win->area[0].yact << 1;
-       } else if (win->area[0].format == YUV420) {
+       } else if ((win->area[0].format == YUV420) ||
+                  (win->area[0].format == YUV420_NV21)) {
                total_size =
                    (win->area[0].y_vir_stride * win->area[0].yact * 6);
        } else {
@@ -2754,7 +2763,8 @@ static int rk_fb_set_par(struct fb_info *info)
                cblen = crlen = (xvir * yvir) >> 1;
                uv_y_act = win->area[0].yact >> 1;
                break;
-       case YUV420:            /* 420sp */
+       case YUV420:            /* nv12 */
+       case YUV420_NV21:       /* nv21 */
        case YUV420_A:
                is_pic_yuv = 1;
                stride = stride_32bit_1;
@@ -2848,8 +2858,10 @@ static int rk_fb_set_par(struct fb_info *info)
        win->g_alpha_val = 0;
 
        if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
-           (win->area[0].format == YUV420 || win->area[0].format == YUV420_A))
-           win->state = 1;
+           (win->area[0].format == YUV420 ||
+            win->area[0].format == YUV420_NV21 ||
+            win->area[0].format == YUV420_A))
+                win->state = 1;
 
        dev_drv->ops->set_par(dev_drv, win_id);
 
index da80013612d7783bb4853cb023bf57a315d00b5c..bbac53ff86f0fdc7e5ce704950e58504d5e48b09 100755 (executable)
@@ -48,6 +48,7 @@ static char *get_format_str(enum data_format format)
        case RGB565:
                return "RGB565";
        case YUV420:
+       case YUV420_NV21:
                return "YUV420";
        case YUV422:
                return "YUV422";
@@ -65,9 +66,9 @@ static char *get_format_str(enum data_format format)
                return "XBGR888";
        case ABGR888:
                return "ABGR888";
+       default:
+               return "invalid";        
        }
-
-       return "invalid";
 }
 
 static ssize_t show_screen_info(struct device *dev,
index e513b2b1cca25094bbdfd0a0fda80c006a1f36dc..18a55f57b79f68e3f67913c4ecbfefa0ce140a65 100755 (executable)
@@ -213,7 +213,8 @@ enum data_format {
        ABGR888,
        YUV420_A = 10,
        YUV422_A,
-       YUV444_A,       
+       YUV444_A,
+       YUV420_NV21,
 };
 
 enum
@@ -315,6 +316,7 @@ struct rk_lcdc_win_area {
        enum data_format format;
        u8 fmt_cfg;
        u8 swap_rb;
+       u8 swap_uv;
        u32 y_offset;           /*yuv/rgb offset  -->LCDC_WINx_YRGB_MSTx*/
        u32 c_offset;           /*cb cr offset--->LCDC_WINx_CBR_MSTx*/
        u16 xpos;               /*start point in panel  --->LCDC_WINx_DSP_ST*/