media: i2c: rk628: add color_range/color_space interface.

Change-Id: I9f2633f8ff4f9f2b3e9d6c02b3865eff125f30a5
Signed-off-by: Wangqiang Guo <kay.guo@rock-chips.com>
This commit is contained in:
Wangqiang Guo
2024-03-20 16:29:13 +08:00
committed by Tao Huang
parent 7d65dab0e2
commit e0cfe1fa23
4 changed files with 109 additions and 32 deletions

View File

@@ -106,7 +106,6 @@ struct rk628_csi {
u32 stream_state;
int hdmirx_irq;
int plugin_irq;
int avi_rdy;
bool nosignal;
bool rxphy_pwron;
bool txphy_pwron;
@@ -118,7 +117,6 @@ struct rk628_csi {
bool continues_clk;
bool cec_enable;
struct rk628_hdmirx_cec *cec;
bool is_dvi;
struct rk628_hdcp hdcp;
bool i2s_enable_default;
HAUDINFO audio_info;
@@ -731,11 +729,9 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
{
u8 video_fmt;
u32 val;
int avi_rdy;
mutex_lock(&csi->confctl_mutex);
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
mutex_unlock(&csi->confctl_mutex);
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
video_fmt = (val & VIDEO_FORMAT_MASK) >> 5;
v4l2_info(&csi->sd, "%s PDEC_AVI_PB:%#x, video format:%d\n",
@@ -762,7 +758,7 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
}
/* if avi packet is not stable, reset ctrl*/
if (!csi->avi_rdy) {
if (!avi_rdy) {
csi->nosignal = true;
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
}
@@ -930,6 +926,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
u8 lanes = csi->csi_lanes_in_use;
u8 lane_num;
u32 wc_usrdef, val;
int avi_rdy;
lane_num = lanes - 1;
csi->rk628->dphy_lane_en = (1 << (lanes + 1)) - 1;
@@ -1086,9 +1083,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
v4l2_dbg(1, debug, sd, "%s csi1 config done\n", __func__);
}
mutex_lock(&csi->confctl_mutex);
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
mutex_unlock(&csi->confctl_mutex);
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
video_fmt = (val & VIDEO_FORMAT_MASK) >> 5;
@@ -1111,7 +1106,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
rk628_post_process_csc_en(csi->rk628);
}
/* if avi packet is not stable, reset ctrl*/
if (!csi->avi_rdy) {
if (!avi_rdy) {
csi->nosignal = true;
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
}
@@ -1252,12 +1247,8 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
__func__, width, height, frame_width, frame_height, status, cnt);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_STS, &val);
if (csi->rk628->version < RK628F_VERSION && (val & DVI_DET)) {
csi->is_dvi = true;
if (csi->rk628->version < RK628F_VERSION && (val & DVI_DET))
dev_info(csi->dev, "DVI mode detected\n");
} else {
csi->is_dvi = false;
}
if (!tx_5v_power_present(sd)) {
v4l2_info(sd, "HDMI pull out, return!\n");
@@ -2188,6 +2179,7 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
long ret = 0;
struct rkmodule_csi_dphy_param *dphy_param;
struct rkmodule_capture_info *capture_info;
u32 val;
switch (cmd) {
case RKMODULE_GET_MODULE_INFO:
@@ -2234,10 +2226,11 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
*(int *)arg = rk628_hdmirx_get_hdcp_enc_status(csi->rk628);
break;
case RK_HDMIRX_CMD_GET_INPUT_MODE:
*(int *)arg = csi->is_dvi;
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_STS, &val);
*(int *)arg = val & DVI_DET;
break;
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
*(int *)arg = csi->avi_rdy;
*(int *)arg = !csi->nosignal;
break;
case RK_HDMIRX_CMD_GET_SCAN_MODE:
if (csi->timings.bt.interlaced == V4L2_DV_INTERLACED)
@@ -2253,6 +2246,9 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
case RK_HDMIRX_CMD_GET_COLOR_RANGE:
*(int *)arg = rk628_hdmirx_get_range(csi->rk628);
break;
case RK_HDMIRX_CMD_GET_COLOR_SPACE:
*(int *)arg = rk628_hdmirx_get_color_space(csi->rk628);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2537,6 +2533,20 @@ static long rk628_csi_compat_ioctl32(struct v4l2_subdev *sd,
}
kfree(seq);
break;
case RK_HDMIRX_CMD_GET_COLOR_SPACE:
seq = kzalloc(sizeof(*seq), GFP_KERNEL);
if (!seq) {
ret = -ENOMEM;
return ret;
}
ret = rk628_csi_ioctl(sd, cmd, seq);
if (!ret) {
ret = copy_to_user(up, seq, sizeof(*seq));
if (ret)
ret = -EFAULT;
}
kfree(seq);
break;
default:
ret = -ENOIOCTLCMD;
break;

View File

@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/soc/rockchip/rk_vendor_storage.h>
#include <linux/slab.h>
#include <linux/rk_hdmirx_config.h>
#include "rk628.h"
#include "rk628_combrxphy.h"
@@ -49,6 +50,30 @@ struct hdmirx_tmdsclk_cnt {
u8 cnt;
};
enum hdmirx_pix_fmt {
HDMIRX_RGB888 = 0,
HDMIRX_YUV422 = 1,
HDMIRX_YUV444 = 2,
HDMIRX_YUV420 = 3,
};
static const char * const bus_format_str[] = {
"RGB",
"YUV422",
"YUV444",
"YUV420",
"UNKNOWN",
};
static const char *bus_color_range_str[3] = {
"Default", "Limited", "Full"
};
static const char *bus_color_space_str[8] = {
"xvYCC601", "xvYCC709", "sYCC601", "Adobe_YCC601",
"Adobe_RGB", "BT2020_YcCbcCrc", "BT2020_RGB_OR_YCbCr"
};
#define HDMIRX_GET_TMDSCLK_TIME 21
static int supported_fs[] = {
@@ -1185,14 +1210,6 @@ void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628)
}
EXPORT_SYMBOL(rk628_hdmirx_phy_prepclk_cfg);
static const char * const bus_format_str[] = {
"RGB",
"YUV422",
"YUV444",
"YUV420",
"UNKNOWN",
};
u8 rk628_hdmirx_get_format(struct rk628 *rk628)
{
u32 val;
@@ -1280,7 +1297,7 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
u32 hofs_pix, hbp, hfp, vbp, vfp;
u32 tmds_clk, tmdsclk_cnt;
u64 tmp_data;
u8 video_fmt;
u8 video_fmt, vic, color_range, color_space;
memset(timings, 0, sizeof(struct v4l2_dv_timings));
timings->type = V4L2_DV_BT_656_1120;
@@ -1341,7 +1358,11 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
hfp = htotal - hact - hofs_pix;
vfp = vtotal - vact - vs - vbp;
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
vic = (val & VID_IDENT_CODE_MASK) >> 24;
video_fmt = rk628_hdmirx_get_format(rk628);
color_range = rk628_hdmirx_get_range(rk628);
color_space = rk628_hdmirx_get_color_space(rk628);
if (video_fmt == BUS_FMT_YUV420) {
htotal *= 2;
hact *= 2;
@@ -1352,6 +1373,8 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
dev_info(rk628->dev, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
HDMIRX_MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs, modetclk_cnt_vs, hofs_pix);
dev_info(rk628->dev, "get current aviif: vic:%d, color_range: %s, color_space %s",
vic, bus_color_range_str[color_range], bus_color_space_str[color_space]);
bt->width = hact;
bt->height = vact;
@@ -1490,20 +1513,57 @@ EXPORT_SYMBOL(rk628_hdmirx_get_timings);
u8 rk628_hdmirx_get_range(struct rk628 *rk628)
{
u32 val;
u8 color_range;
u32 val, vic, fmt;
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
color_range = (val & RGB_COLORRANGE_MASK) >> 18;
if (color_range == 0x1)
color_range = CSC_LIMIT_RANGE;
else
color_range = CSC_FULL_RANGE;
vic = (val & VID_IDENT_CODE_MASK) >> 24;
fmt = (val & VIDEO_FORMAT_MASK) >> 5;
if (fmt == HDMIRX_RGB888 && color_range == HDMIRX_DEFAULT_RANGE) {
(vic) ?
(color_range = HDMIRX_LIMIT_RANGE) :
(color_range = HDMIRX_FULL_RANGE);
}
return color_range;
}
EXPORT_SYMBOL(rk628_hdmirx_get_range);
u8 rk628_hdmirx_get_color_space(struct rk628 *rk628)
{
u32 val, EC2_0, C1_C0, fmt;
u8 color_space;
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
EC2_0 = (val & EXT_COLORIMETRY_MASK) >> 20;
C1_C0 = (val & COLORIMETRY_MASK) >> 14;
fmt = (val & VIDEO_FORMAT_MASK) >> 5;
if (fmt == HDMIRX_RGB888) {
(C1_C0 == 0) ?
(color_space = HDMIRX_RGB) :
(color_space = EC2_0);
} else {
switch (C1_C0) {
case 0:
color_space = HDMIRX_XVYCC709;
break;
case 1:
color_space = HDMIRX_XVYCC601;
break;
case 2:
color_space = HDMIRX_XVYCC709;
break;
default:
color_space = EC2_0;
break;
}
}
return color_space;
}
EXPORT_SYMBOL(rk628_hdmirx_get_color_space);
void rk628_hdmirx_controller_reset(struct rk628 *rk628)
{
mutex_lock(&rk628->rst_lock);

View File

@@ -255,7 +255,12 @@
#define DVI_DET BIT(28)
#define HDMI_RX_PDEC_GCP_AVMUTE (HDMI_RX_BASE + 0x0380)
#define PKTDEC_GCP_CD_MASK GENMASK(7, 4)
#define HDMI_RX_PDEC_AVI_HB (HDMI_RX_BASE + 0x03a0)
#define HDMI_RX_PDEC_AVI_PB (HDMI_RX_BASE + 0x03a4)
#define VID_IDENT_CODE_VIC7 BIT(31)
#define VID_IDENT_CODE_MASK GENMASK(30, 24)
#define EXT_COLORIMETRY_MASK GENMASK(22, 20)
#define COLORIMETRY_MASK GENMASK(15, 14)
#define VIDEO_FORMAT_MASK GENMASK(6, 5)
#define VIDEO_FORMAT(x) UPDATE(x, 6, 5)
#define RGB_COLORRANGE_MASK GENMASK(19, 18)
@@ -517,6 +522,7 @@ u32 rk628_hdmirx_get_tmdsclk_cnt(struct rk628 *rk628);
int rk628_hdmirx_get_timings(struct rk628 *rk628,
struct v4l2_dv_timings *timings);
u8 rk628_hdmirx_get_range(struct rk628 *rk628);
u8 rk628_hdmirx_get_color_space(struct rk628 *rk628);
int rk628_hdmirx_get_hdcp_enc_status(struct rk628 *rk628);
void rk628_hdmirx_controller_reset(struct rk628 *rk628);
bool rk628_hdmirx_scdc_ced_err(struct rk628 *rk628);

View File

@@ -42,6 +42,7 @@ enum hdmirx_color_space {
HDMIRX_ADOBE_RGB = 4,
HDMIRX_BT2020_YCC_CONST_LUM = 5,
HDMIRX_BT2020_RGB_OR_YCC = 6,
HDMIRX_RGB = 7,
};
/* hdmirx scan mode */