From ae0bee602927ec774f2608cb8cf0792de7d0f8bb Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Fri, 19 Jul 2024 11:21:05 +0800 Subject: [PATCH] media: i2c: rk628: fix user set csc color range Change-Id: Ibc35c8bbbc54c9b4de4977d9500083afa2857b36 Signed-off-by: Jianwei Fan --- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 57 ++++++++++++-------- drivers/media/i2c/rk628/rk628_post_process.c | 12 ++--- drivers/media/i2c/rk628/rk628_post_process.h | 2 +- include/uapi/linux/rk_hdmirx_config.h | 8 ++- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 9f1802bd3d21..e799a65c6e58 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -62,12 +62,6 @@ enum tx_mode_type { DSI_MODE, }; -enum output_color_range { - OUT_RANGE_AUTO = 0, - OUT_RANGE_LIMIT = 1, - OUT_RANGE_FULL = 2, -}; - struct rk628_plat_data { int bus_fmt; int tx_mode; @@ -138,7 +132,7 @@ struct rk628_csi { bool is_streaming; bool csi_ints_en; bool dual_mipi_use; - int output_range; + enum user_color_range user_color_range; }; struct rk628_csi_mode { @@ -816,13 +810,13 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi) color_range = rk628_hdmirx_get_range(csi->rk628); rk628_i2c_write(csi->rk628, GRF_CSC_CTRL_CON, SW_YUV2VYU_SWP(0)); - if (csi->output_range == OUT_RANGE_AUTO) + if (csi->user_color_range == COLOR_RANGE_AUTO) rk628_post_process_csc_en(csi->rk628, - color_range == HDMIRX_LIMIT_RANGE ? false : true); - else if (csi->output_range == OUT_RANGE_LIMIT) - rk628_post_process_csc_en(csi->rk628, false); + color_range == HDMIRX_LIMIT_RANGE ? false : true, true); + else if (csi->user_color_range == COLOR_RANGE_LIMIT) + rk628_post_process_csc_en(csi->rk628, false, true); else - rk628_post_process_csc_en(csi->rk628, true); + rk628_post_process_csc_en(csi->rk628, true, true); } /* if avi packet is not stable, reset ctrl*/ @@ -1173,13 +1167,13 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd) color_range = rk628_hdmirx_get_range(csi->rk628); rk628_i2c_write(csi->rk628, GRF_CSC_CTRL_CON, SW_YUV2VYU_SWP(1)); - if (csi->output_range == OUT_RANGE_AUTO) + if (csi->user_color_range == COLOR_RANGE_AUTO) rk628_post_process_csc_en(csi->rk628, - color_range == HDMIRX_LIMIT_RANGE ? false : true); - else if (csi->output_range == OUT_RANGE_LIMIT) - rk628_post_process_csc_en(csi->rk628, false); + color_range == HDMIRX_LIMIT_RANGE ? false : true, true); + else if (csi->user_color_range == COLOR_RANGE_LIMIT) + rk628_post_process_csc_en(csi->rk628, false, true); else - rk628_post_process_csc_en(csi->rk628, true); + rk628_post_process_csc_en(csi->rk628, true, true); } /* if avi packet is not stable, reset ctrl*/ if (!avi_rdy) { @@ -2456,6 +2450,21 @@ static void rk628_csi_reset_streaming(struct v4l2_subdev *sd, int on) fps_calc(&csi->timings.bt)); } +static void rk628_csi_set_color_range(struct v4l2_subdev *sd) +{ + struct rk628_csi *csi = to_csi(sd); + u8 color_range; + + color_range = rk628_hdmirx_get_range(csi->rk628); + if (csi->user_color_range == COLOR_RANGE_AUTO) + rk628_post_process_csc_en(csi->rk628, + color_range == HDMIRX_LIMIT_RANGE ? false : true, true); + else if (csi->user_color_range == COLOR_RANGE_LIMIT) + rk628_post_process_csc_en(csi->rk628, false, true); + else + rk628_post_process_csc_en(csi->rk628, true, true); +} + static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct rk628_csi *csi = to_csi(sd); @@ -2540,9 +2549,13 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKMODULE_GET_DSI_MODE: *(int *)arg = csi->dsi.vid_mode; break; - case RK_HDMIRX_CMD_SET_OUTPUT_RANGE: - csi->output_range = *((int *)arg); - v4l2_dbg(1, debug, sd, "set output_range: %d\n", csi->output_range); + case RK_HDMIRX_CMD_SET_COLOR_RANGE: + csi->user_color_range = *((int *)arg); + if (csi->user_color_range > COLOR_RANGE_FULL || + csi->user_color_range < COLOR_RANGE_AUTO) + csi->user_color_range = COLOR_RANGE_AUTO; + v4l2_info(sd, "user set color range: %d\n", csi->user_color_range); + rk628_csi_set_color_range(sd); break; default: ret = -ENOIOCTLCMD; @@ -2887,7 +2900,7 @@ static long rk628_csi_compat_ioctl32(struct v4l2_subdev *sd, } kfree(seq); break; - case RK_HDMIRX_CMD_SET_OUTPUT_RANGE: + case RK_HDMIRX_CMD_SET_COLOR_RANGE: ret = copy_from_user(&is_full_range, up, sizeof(int)); if (!ret) ret = rk628_csi_ioctl(sd, cmd, &is_full_range); @@ -3216,7 +3229,7 @@ static int rk628_csi_probe_of(struct rk628_csi *csi) csi->nosignal = true; csi->stream_state = 0; csi->avi_rcv_rdy = false; - csi->output_range = OUT_RANGE_AUTO; + csi->user_color_range = COLOR_RANGE_AUTO; ret = 0; diff --git a/drivers/media/i2c/rk628/rk628_post_process.c b/drivers/media/i2c/rk628/rk628_post_process.c index f60a0e0154c2..359631156ac3 100644 --- a/drivers/media/i2c/rk628/rk628_post_process.c +++ b/drivers/media/i2c/rk628/rk628_post_process.c @@ -1608,7 +1608,8 @@ static u8 rk628_get_output_color_space(struct rk628 *rk628, u8 input_color_space } } -static void rk628_post_process_csc(struct rk628 *rk628, bool is_output_full_range) +static void rk628_post_process_csc(struct rk628 *rk628, + bool is_input_full_range, bool is_output_full_range) { enum bus_format in_fmt, out_fmt; struct post_csc_coef csc_coef = {}; @@ -1623,14 +1624,11 @@ static void rk628_post_process_csc(struct rk628 *rk628, bool is_output_full_rang else if (out_fmt == BUS_FMT_RGB) rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_Y2R_EN(1)); } else { - u8 in_color_range, in_color_space, output_color_space; + u8 in_color_space, output_color_space; enum color_space_type input_color_space; - bool is_input_full_range; - in_color_range = rk628_hdmirx_get_range(rk628); in_color_space = rk628_hdmirx_get_color_space(rk628); input_color_space = rk628_csc_color_space_convert(in_color_space, in_fmt); - is_input_full_range = (in_color_range == HDMIRX_LIMIT_RANGE) ? false : true; output_color_space = rk628_get_output_color_space(rk628, input_color_space); rockchip_calc_post_csc(rk628, &csc_coef, is_input_full_range, @@ -1718,9 +1716,9 @@ void rk628_post_process_pattern_node(struct rk628 *rk628) } EXPORT_SYMBOL(rk628_post_process_pattern_node); -void rk628_post_process_csc_en(struct rk628 *rk628, bool output_full_range) +void rk628_post_process_csc_en(struct rk628 *rk628, bool input_full_range, bool output_full_range) { - rk628_post_process_csc(rk628, output_full_range); + rk628_post_process_csc(rk628, input_full_range, output_full_range); rk628_i2c_write(rk628, GRF_SCALER_CON0, SCL_EN(1)); } EXPORT_SYMBOL(rk628_post_process_csc_en); diff --git a/drivers/media/i2c/rk628/rk628_post_process.h b/drivers/media/i2c/rk628/rk628_post_process.h index 835f3657f379..bb9b4bcfccb2 100644 --- a/drivers/media/i2c/rk628/rk628_post_process.h +++ b/drivers/media/i2c/rk628/rk628_post_process.h @@ -7,7 +7,7 @@ #ifndef POST_PROCESS_H #define POST_PROCESS_H -void rk628_post_process_csc_en(struct rk628 *rk628, bool output_full_range); +void rk628_post_process_csc_en(struct rk628 *rk628, bool input_full_range, bool output_full_range); void rk628_post_process_csc_dis(struct rk628 *rk628); void rk628_post_process_pattern_node(struct rk628 *rk628); #endif diff --git a/include/uapi/linux/rk_hdmirx_config.h b/include/uapi/linux/rk_hdmirx_config.h index 376d271b39bc..241d89a21a99 100644 --- a/include/uapi/linux/rk_hdmirx_config.h +++ b/include/uapi/linux/rk_hdmirx_config.h @@ -58,6 +58,12 @@ enum hdmirx_edid_mode { HDMIRX_EDID_4K60HZ_YUV420, }; +enum user_color_range { + COLOR_RANGE_AUTO = 0, + COLOR_RANGE_LIMIT = 1, + COLOR_RANGE_FULL = 2, +}; + /* Private v4l2 ioctl */ #define RK_HDMIRX_CMD_GET_FPS \ _IOR('V', BASE_VIDIOC_PRIVATE + 0, int) @@ -104,7 +110,7 @@ enum hdmirx_edid_mode { #define RK_HDMIRX_CMD_GET_HDCP_ENC_STATUS \ _IOR('V', BASE_VIDIOC_PRIVATE + 14, __u8) -#define RK_HDMIRX_CMD_SET_OUTPUT_RANGE \ +#define RK_HDMIRX_CMD_SET_COLOR_RANGE \ _IOW('V', BASE_VIDIOC_PRIVATE + 15, int) /* Private v4l2 event */