mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user