From: zwl Date: Mon, 28 Apr 2014 08:12:11 +0000 (+0800) Subject: rk3288 hdmi: add support csc function that RGB to YCbCr and RGB_0_255 to RGB_16_235 X-Git-Tag: firefly_0821_release~5420 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cb3d792c142d66807183c076432982acb8941ef4;p=firefly-linux-kernel-4.4.55.git rk3288 hdmi: add support csc function that RGB to YCbCr and RGB_0_255 to RGB_16_235 --- diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c index 8472702031db..869caf8d1ffc 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c @@ -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; diff --git a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h index 522f869e00e2..22047cae6cb1 100644 --- a/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h +++ b/drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h @@ -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 diff --git a/drivers/video/rockchip/hdmi/rk_hdmi.h b/drivers/video/rockchip/hdmi/rk_hdmi.h index ed7b8a199f50..62741e4dc1f0 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi.h +++ b/drivers/video/rockchip/hdmi/rk_hdmi.h @@ -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 { diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c index 7d5e7e7844cd..5cf4cc74362c 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c +++ b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c @@ -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)