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 06:54:05 +0000 (14:54 +0800)
Signed-off-by: hjc <hjc@rock-chips.com>
Conflicts:
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_fb.h

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 6ea6f846a214976ff37334b63d2437d45635dda9..0cd8e3036402a9fbd9f903affc4bc83d826274ba 100755 (executable)
@@ -161,6 +161,7 @@ int rk_fb_pixel_width(int data_format)
                break;
        case YUV422:
        case YUV420:
+       case YUV420_NV21:
        case YUV444:
                pixel_width = 1 * 8;
                break;
@@ -200,6 +201,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;
@@ -516,6 +520,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:
@@ -1279,7 +1284,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;
@@ -1665,6 +1671,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);
@@ -2002,7 +2009,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;
@@ -2604,7 +2612,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 {
@@ -2790,7 +2799,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;
@@ -2840,8 +2850,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 a6a2f61b87719368a486eeb74e847278c2d8483c..6a9f6037f2a2a988d1ffff443a3e507cea2b7c68 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";
@@ -72,10 +73,8 @@ static char *get_format_str(enum data_format format)
        case FBDC_RGBX_888:
                return "FBDC_RGBX_888";
        default:
-               break;
+               return "invalid";        
        }
-
-       return "invalid";
 }
 
 static ssize_t show_screen_info(struct device *dev,
index e8027589ed0a3b7bfd87d00b1307c2d6afaf7e68..85d7b17f0346c206639bf9f70a8f163e3d789d11 100644 (file)
@@ -215,6 +215,7 @@ enum data_format {
        YUV420_A = 10,
        YUV422_A,
        YUV444_A,
+       YUV420_NV21,
        FBDC_RGB_565 = 0x26,
        FBDC_ARGB_888,
        FBDC_RGBX_888,
@@ -319,6 +320,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*/