media: i2c: rk628: add private interface, compatible with hdmirx.

Change-Id: I737dcb068bc830baccb932d985bdbede56b5d490
Signed-off-by: Wangqiang Guo <kay.guo@rock-chips.com>
This commit is contained in:
Wangqiang Guo
2024-02-04 12:48:34 +00:00
committed by 郭旺强
parent f1132b51ff
commit b65bb3bb00
4 changed files with 187 additions and 7 deletions

View File

@@ -105,6 +105,7 @@ struct rk628_csi {
u32 stream_state;
int hdmirx_irq;
int plugin_irq;
int avi_rdy;
bool nosignal;
bool rxphy_pwron;
bool txphy_pwron;
@@ -116,6 +117,7 @@ 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;
@@ -719,10 +721,9 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
{
u8 video_fmt;
u32 val;
int avi_rdy;
mutex_lock(&csi->confctl_mutex);
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
mutex_unlock(&csi->confctl_mutex);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
@@ -751,7 +752,7 @@ static void rk628_dsi_set_scs(struct rk628_csi *csi)
}
/* if avi packet is not stable, reset ctrl*/
if (!avi_rdy) {
if (!csi->avi_rdy) {
csi->nosignal = true;
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
}
@@ -919,7 +920,6 @@ 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;
@@ -1077,7 +1077,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
}
mutex_lock(&csi->confctl_mutex);
avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
csi->avi_rdy = rk628_is_avi_ready(csi->rk628, csi->avi_rcv_rdy);
mutex_unlock(&csi->confctl_mutex);
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_AVI_PB, &val);
@@ -1101,7 +1101,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 (!avi_rdy) {
if (!csi->avi_rdy) {
csi->nosignal = true;
schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20);
}
@@ -1242,8 +1242,12 @@ 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))
if (csi->rk628->version < RK628F_VERSION && (val & DVI_DET)) {
csi->is_dvi = true;
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");
@@ -2226,6 +2230,32 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
else
*(int *)arg = RKMODULE_CSI_INPUT;
break;
case RK_HDMIRX_CMD_GET_FPS:
*(int *)arg = fps_calc(&csi->timings.bt);
break;
case RK_HDMIRX_CMD_GET_HDCP_ENC_STATUS:
*(int *)arg = rk628_hdmirx_get_hdcp_enc_status(csi->rk628);
break;
case RK_HDMIRX_CMD_GET_INPUT_MODE:
*(int *)arg = csi->is_dvi;
break;
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
*(int *)arg = csi->avi_rdy;
break;
case RK_HDMIRX_CMD_GET_SCAN_MODE:
if (csi->timings.bt.interlaced == V4L2_DV_INTERLACED)
*(int *)arg = HDMIRX_INTERLACED;
else
*(int *)arg = HDMIRX_PROGRESSIVE;
break;
case RK_HDMIRX_CMD_GET_EDID_MODE:
*(int *)arg = HDMIRX_EDID_4K60HZ_YUV444;
break;
case RK_HDMIRX_CMD_SET_EDID_MODE:
break;
case RK_HDMIRX_CMD_GET_COLOR_RANGE:
*(int *)arg = rk628_hdmirx_get_range(csi->rk628);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -2398,6 +2428,118 @@ static long rk628_csi_compat_ioctl32(struct v4l2_subdev *sd,
}
kfree(seq);
break;
case RK_HDMIRX_CMD_GET_FPS:
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;
case RK_HDMIRX_CMD_GET_HDCP_ENC_STATUS:
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;
case RK_HDMIRX_CMD_GET_INPUT_MODE:
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;
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
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;
case RK_HDMIRX_CMD_GET_SCAN_MODE:
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;
case RK_HDMIRX_CMD_GET_EDID_MODE:
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;
case RK_HDMIRX_CMD_SET_EDID_MODE:
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;
case RK_HDMIRX_CMD_GET_COLOR_RANGE:
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

@@ -213,6 +213,17 @@ void rk628_hdmirx_controller_setup(struct rk628 *rk628)
}
EXPORT_SYMBOL(rk628_hdmirx_controller_setup);
int rk628_hdmirx_get_hdcp_enc_status(struct rk628 *rk628)
{
u32 val;
rk628_i2c_read(rk628, HDMI_RX_HDCP_STS, &val);
val &= HDCP_ENC_STATE;
return val ? 1 : 0;
}
EXPORT_SYMBOL(rk628_hdmirx_get_hdcp_enc_status);
static bool is_validfs(int fs)
{
int i = 0;

View File

@@ -121,6 +121,7 @@
#define HDMI_RX_HDCP_DBG (HDMI_RX_BASE + 0x00e0)
#define HDMI_RX_HDCP_AN0 (HDMI_RX_BASE + 0x00f0)
#define HDMI_RX_HDCP_STS (HDMI_RX_BASE + 0x00fc)
#define HDCP_ENC_STATE BIT(9)
#define HDMI_RX_MD_HCTRL1 (HDMI_RX_BASE + 0x0140)
#define HACT_PIX_ITH(x) UPDATE(x, 10, 8)
#define HACT_PIX_SRC(x) UPDATE(x, 5, 5)
@@ -516,6 +517,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);
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);
bool rk628_hdmirx_is_signal_change_ists(struct rk628 *rk628);

View File

@@ -44,6 +44,19 @@ enum hdmirx_color_space {
HDMIRX_BT2020_RGB_OR_YCC = 6,
};
/* hdmirx scan mode */
enum hdmirx_scan_mode {
HDMIRX_PROGRESSIVE = 0,
HDMIRX_INTERLACED = 1,
};
enum hdmirx_edid_mode {
HDMIRX_EDID_2K60HZ_YUV444,
HDMIRX_EDID_4K30HZ_YUV444,
HDMIRX_EDID_4K60HZ_YUV444,
HDMIRX_EDID_4K60HZ_YUV420,
};
/* Private v4l2 ioctl */
#define RK_HDMIRX_CMD_GET_FPS \
_IOR('V', BASE_VIDIOC_PRIVATE + 0, int)
@@ -78,6 +91,18 @@ enum hdmirx_color_space {
#define RK_HDMIRX_CMD_GET_COLOR_SPACE \
_IOR('V', BASE_VIDIOC_PRIVATE + 10, int)
#define RK_HDMIRX_CMD_GET_SCAN_MODE \
_IOR('V', BASE_VIDIOC_PRIVATE + 11, __u8)
#define RK_HDMIRX_CMD_GET_EDID_MODE \
_IOR('V', BASE_VIDIOC_PRIVATE + 12, __u8)
#define RK_HDMIRX_CMD_SET_EDID_MODE \
_IOW('V', BASE_VIDIOC_PRIVATE + 13, __u8)
#define RK_HDMIRX_CMD_GET_HDCP_ENC_STATUS \
_IOR('V', BASE_VIDIOC_PRIVATE + 14, __u8)
/* Private v4l2 event */
#define RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST \
(V4L2_EVENT_PRIVATE_START + 1)