rk3288 hdmi: add support csc function that RGB to YCbCr and RGB_0_255 to RGB_16_235
authorzwl <zwl@rock-chips.com>
Mon, 28 Apr 2014 08:12:11 +0000 (16:12 +0800)
committerzwl <zwl@rock-chips.com>
Mon, 28 Apr 2014 08:12:41 +0000 (16:12 +0800)
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h
drivers/video/rockchip/hdmi/rk_hdmi.h
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c

index 8472702031dbd1b298e97b8f9127477c2be6cd5e..869caf8d1ffc5a0d175444e3125839e117ecafee 100644 (file)
@@ -682,7 +682,8 @@ int rk3288_hdmi_config_vsi(struct hdmi *hdmi_drv, unsigned char vic_3d, unsigned
 
 static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic, struct hdmi_video_para *vpara)
 {
-       int colorimetry, ext_colorimetry, aspect_ratio, y1y0;
+       unsigned char colorimetry, ext_colorimetry, aspect_ratio, y1y0;
+       unsigned char rgb_quan_range = AVI_QUANTIZATION_RANGE_DEFAULT;
        struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
 
        //Set AVI infoFrame Data byte1
@@ -731,7 +732,8 @@ static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic, str
        hdmi_writel(hdmi_dev, FC_AVICONF1, v_FC_COLORIMETRY(colorimetry) | v_FC_PIC_ASPEC_RATIO(aspect_ratio) | v_FC_ACT_ASPEC_RATIO(ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME));
 
        //Set AVI infoFrame Data byte3
-       hdmi_msk_reg(hdmi_dev, FC_AVICONF2, m_FC_EXT_COLORIMETRY, v_FC_EXT_COLORIMETRY(ext_colorimetry));
+       hdmi_msk_reg(hdmi_dev, FC_AVICONF2, m_FC_EXT_COLORIMETRY | m_FC_QUAN_RANGE,
+               v_FC_EXT_COLORIMETRY(ext_colorimetry) | v_FC_QUAN_RANGE(rgb_quan_range));
 
        //Set AVI infoFrame Data byte4
        hdmi_writel(hdmi_dev, FC_AVIVID, (vic & 0xff));
@@ -747,28 +749,70 @@ static const char coeff_csc[][24] = {
                //   A1    |    A2     |    A3     |    A4    |
                //   B1    |    B2     |    B3     |    B4    |
                //   C1    |    C2     |    C3     |    C4    |
-       {       //CSC_RGB_TO_ITU601
-               0x25, 0x91, 0x13, 0x22, 0x07, 0x4b, 0x00, 0x00,         //Y
-               0x65, 0x35, 0x20, 0x00, 0x7a, 0xcc, 0x02, 0x00,         //Cr
-               0x6a, 0xcd, 0x75, 0x34, 0x20, 0x00, 0x02, 0x00,         //Cb
+       {       //CSC_RGB_0_255_TO_RGB_16_235_8BIT
+               0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,         //G
+               0x00, 0x00, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x20,         //R
+               0x00, 0x00, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x20,         //B
        },
-       {       //CSC_RGB_TO_ITU709
-               0x2d, 0xc5, 0x0d, 0x9b, 0x04, 0x9e, 0x00, 0x00,         //Y
-               0x62, 0xf0, 0x20, 0x00, 0x7d, 0x11, 0x02, 0x00,         //Cr
-               0x67, 0x56, 0x78, 0xab, 0x20, 0x00, 0x02, 0x00,         //Cb
+       {       //CSC_RGB_0_255_TO_RGB_16_235_10BIT
+               0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,         //G
+               0x00, 0x00, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x80,         //R
+               0x00, 0x00, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x80,         //B
        },
+#if 0
+       {       //CSC_RGB_0_255_TO_ITU601_16_235_8BIT
+               0x25, 0x91, 0x13, 0x23, 0x07, 0x4c, 0x00, 0x00,         //Y
+               0xe5, 0x34, 0x20, 0x00, 0xfa, 0xcc, 0x02, 0x00,         //Cr
+               0xea, 0xcd, 0xf5, 0x33, 0x20, 0x00, 0x02, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU601_16_235_10BIT
+               0x25, 0x91, 0x13, 0x23, 0x07, 0x4c, 0x00, 0x00,         //Y
+               0xe5, 0x34, 0x20, 0x00, 0xfa, 0xcc, 0x08, 0x00,         //Cr
+               0xea, 0xcd, 0xf5, 0x33, 0x20, 0x00, 0x08, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU709_16_235_8BIT
+               0x2d, 0xc6, 0x0d, 0x9b, 0x04, 0x9f, 0x00, 0x00,         //Y
+               0xe2, 0xef, 0x20, 0x00, 0xfd, 0x11, 0x02, 0x00,         //Cr
+               0xe7, 0x55, 0xf8, 0xab, 0x20, 0x00, 0x02, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU709_16_235_10BIT
+               0x2d, 0xc6, 0x0d, 0x9b, 0x04, 0x9f, 0x00, 0x00,         //Y
+               0xe2, 0xef, 0x20, 0x00, 0xfd, 0x11, 0x08, 0x00,         //Cr
+               0xe7, 0x55, 0xf8, 0xab, 0x20, 0x00, 0x08, 0x00,         //Cb
+       },
+#else
+       {       //CSC_RGB_0_255_TO_ITU601_16_235_8BIT
+               0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x00, 0x40,         //Y
+               0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x02, 0x00,         //Cr
+               0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x02, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU601_16_235_10BIT
+               0x20, 0x40, 0x10, 0x80, 0x06, 0x40, 0x01, 0x00,         //Y
+               0xe8, 0x80, 0x1c, 0x00, 0xfb, 0x80, 0x08, 0x00,         //Cr
+               0xed, 0x80, 0xf6, 0x80, 0x1c, 0x00, 0x08, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU709_16_235_8BIT
+               0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x00, 0x40,         //Y
+               0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x02, 0x00,         //Cr
+               0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x02, 0x00,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU709_16_235_10BIT
+               0x27, 0x40, 0x0b, 0xc0, 0x04, 0x00, 0x01, 0x00,         //Y
+               0xe6, 0x80, 0x1c, 0x00, 0xfd, 0x80, 0x08, 0x00,         //Cr
+               0xea, 0x40, 0xf9, 0x80, 0x1c, 0x00, 0x08, 0x00,         //Cb
+       },
+#endif
                //Y             Cr          Cb          Bias
-       {       //CSC_ITU601_TO_RGB
-               0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e,         //R 
-               0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a,         //G
+       {       //CSC_ITU601_16_235_TO_RGB_0_255_8BIT
+               0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e,         //G 
+               0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a,         //R
                0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b,         //B
        },
-       {       //CSC_ITU709_TO_RGB
-               0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7,         //R
-               0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d,         //G
+       {       //CSC_ITU709_16_235_TO_RGB_0_255_8BIT
+               0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7,         //G
+               0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d,         //R
                0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25,         //B
        },
-
 };
 
 static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
@@ -778,9 +822,7 @@ static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *
        unsigned char color_depth = 0;
        struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
 
-       if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) ||
-               ((vpara->input_color != VIDEO_INPUT_COLOR_RGB) && (vpara->output_color != VIDEO_OUTPUT_RGB444) ))
-       {
+       if ((vpara->input_color == vpara->output_color) && (vpara->color_limit_range == 0)) {
                hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(0));
                return 0;
        }
@@ -797,24 +839,6 @@ static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *
                hdmi_msk_reg(hdmi_dev, CSC_CFG, m_CSC_DECIMODE, v_CSC_DECIMODE(decimation));
        }
 
-       switch (vpara->color_depth) {
-               case HDMI_COLOR_DEPTH_8BIT:
-                       color_depth = COLOR_DEPTH_24BIT;
-                       break;
-               case HDMI_COLOR_DEPTH_10BIT:
-                       color_depth = COLOR_DEPTH_30BIT;
-                       break;
-               case HDMI_COLOR_DEPTH_12BIT:
-                       color_depth = COLOR_DEPTH_36BIT;
-                       break;
-               case HDMI_COLOR_DEPTH_16BIT:
-                       color_depth = COLOR_DEPTH_48BIT;
-                       break;
-               default:
-                       color_depth = COLOR_DEPTH_24BIT;
-                       break;
-       }
-
        switch(vpara->vic)
        {
                case HDMI_720x480i_60Hz_4_3:
@@ -825,27 +849,52 @@ static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *
                case HDMI_720x576i_50Hz_16_9:
                case HDMI_720x480p_60Hz_16_9:
                case HDMI_720x576p_50Hz_16_9:
-                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
-                               mode = CSC_RGB_TO_ITU601;
+                       if (vpara->input_color == VIDEO_INPUT_COLOR_RGB && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
+                               mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
                                csc_scale = 0;
-                       }
-                       else if(vpara->output_color == VIDEO_OUTPUT_RGB444) {
-                               mode = CSC_ITU601_TO_RGB;
+                       } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444 && vpara->output_color == VIDEO_OUTPUT_RGB444) {
+                               mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
                                csc_scale = 1;
                        }
                        break;
                default:
-                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
-                               mode = CSC_RGB_TO_ITU709;
+                       if (vpara->input_color == VIDEO_INPUT_COLOR_RGB && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
+                               mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
                                csc_scale = 0;
-                       }
-                       else if(vpara->output_color == VIDEO_OUTPUT_RGB444) {
-                               mode = CSC_ITU709_TO_RGB;
+                       } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444 && vpara->output_color == VIDEO_OUTPUT_RGB444) {
+                               mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
                                csc_scale = 1;
                        }
                        break;
        }
 
+       if ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)
+                                                       && (vpara->color_limit_range == 1)) {
+               mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
+               csc_scale = 1;
+       }
+
+       switch (vpara->color_depth) {
+               case HDMI_COLOR_DEPTH_8BIT:
+                       color_depth = COLOR_DEPTH_24BIT;
+                       break;
+               case HDMI_COLOR_DEPTH_10BIT:
+                       color_depth = COLOR_DEPTH_30BIT;
+                       mode += 1;
+                       break;
+               case HDMI_COLOR_DEPTH_12BIT:
+                       color_depth = COLOR_DEPTH_36BIT;
+                       mode += 2;
+                       break;
+               case HDMI_COLOR_DEPTH_16BIT:
+                       color_depth = COLOR_DEPTH_48BIT;
+                       mode += 3;
+                       break;
+               default:
+                       color_depth = COLOR_DEPTH_24BIT;
+                       break;
+       }
+
        coeff = coeff_csc[mode];
        for(i = 0; i < 24; i++) {
                hdmi_writel(hdmi_dev, CSC_COEF_A1_MSB + i, coeff[i]);
@@ -864,7 +913,6 @@ int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpar
 {
        rk3288_hdmi_av_mute(hdmi_drv, 1);
 
-       vpara->output_color = VIDEO_OUTPUT_RGB444;
        //Color space convert
        if (rk3288_hdmi_video_forceOutput(hdmi_drv, 1) < 0)
                return -1;
index 522f869e00e239004f283b08b7b2c1ef46a76acf..22047cae6cb1b819933b3baa3de6a34bb77a4069 100644 (file)
@@ -19,10 +19,16 @@ enum{
 
 /* Color Space Convertion Mode */
 enum {
-       CSC_RGB_TO_ITU601 = 0,  //RGB input to YCbCr output according BT601
-       CSC_RGB_TO_ITU709,      //RGB input to YCbCr output accroding BT709
-       CSC_ITU601_TO_RGB,      //YCbCr input to RGB output according BT601
-       CSC_ITU709_TO_RGB,      //YCbCr input to RGB output according BT709
+       CSC_RGB_0_255_TO_RGB_16_235_8BIT,       //RGB 0-255 input to RGB 16-235 output that is 8bit clolor depth
+       CSC_RGB_0_255_TO_RGB_16_235_10BIT,      //RGB 0-255 input to RGB 16-235 output that is 8bit clolor depth
+       CSC_RGB_0_255_TO_ITU601_16_235_8BIT,    //RGB 0-255 input to YCbCr 16-235 output according BT601 that is 8bit clolor depth
+       CSC_RGB_0_255_TO_ITU601_16_235_10BIT,   //RGB 0-255 input to YCbCr 16-235 output according BT601 that is 10bit clolor depth
+       CSC_RGB_0_255_TO_ITU709_16_235_8BIT,    //RGB 0-255 input to YCbCr 16-235 output accroding BT709 that is 8bit clolor depth
+       CSC_RGB_0_255_TO_ITU709_16_235_10BIT,   //RGB 0-255 input to YCbCr 16-235 output accroding BT709 that is 10bit clolor depth
+       CSC_ITU601_16_235_TO_RGB_16_235_8BIT,   //YCbCr 16-235 input to RGB 16-235 output according BT601 that is 8bit clolor depth
+       CSC_ITU709_16_235_TO_RGB_16_235_8BIT,   //YCbCr 16-235 input to RGB 16-235 output according BT709 that is 8bit clolor depth
+       CSC_ITU601_16_235_TO_RGB_0_255_8BIT,    //YCbCr 16-235 input to RGB 0-255 output according BT601 that is 8bit clolor depth
+       CSC_ITU709_16_235_TO_RGB_0_255_8BIT     //YCbCr 16-235 input to RGB 0-255 output according BT709 that is 8bit clolor depth
 };
 
 /*VIC VIDEO FORMAT*/
@@ -480,7 +486,11 @@ enum {
        ACTIVE_ASPECT_RATE_16_9,
        ACTIVE_ASPECT_RATE_14_9
 };
-
+enum {
+       AVI_QUANTIZATION_RANGE_DEFAULT = 0,
+       AVI_QUANTIZATION_RANGE_LIMITED,
+       AVI_QUANTIZATION_RANGE_FULL
+};
 
 #define        FC_AVICONF0                     0x1019
 #define m_FC_RGC_YCC_2         (1 << 7)        //use for HDMI2.0 TX
index ed7b8a199f50f242e1c0fd0e84d89e05539eef6f..62741e4dc1f066a553911097124e1b590920f687 100755 (executable)
@@ -273,6 +273,7 @@ struct hdmi_video_para {
        unsigned char color_depth;      //color depth: 8bit; 10bit; 12bit; 16bit;
        unsigned char pixel_repet;      //pixel repettion
        unsigned char pixel_pack_phase; //pixel packing default phase
+       unsigned char color_limit_range;//quantization range 0: full range(0~255) 1:limit range(16~235)
 };
 
 struct hdmi {
index 7d5e7e7844cdb3970feeaf4a77169e7f1cd8f90d..5cf4cc74362cd500c39293e26e1ae601e5b98797 100755 (executable)
@@ -558,6 +558,7 @@ int hdmi_init_video_para(struct hdmi *hdmi_drv, struct hdmi_video_para *video)
        video->output_mode = hdmi_drv->edid.sink_hdmi;
        video->format_3d = 0;   /*TODO modify according to EDID if need*/
        video->pixel_repet = 0;
+       video->color_limit_range = 1; //0:IT Video Format  1:CE Video Format --TODO modify according to EDID
 
 #ifdef SOURCE_ABOVE_10BIT
        if (hdmi_drv->edid.deepcolor & HDMI_COLOR_DEPTH_16BIT)