mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
media: i2c: rk628: fix i2c error when hdmirx reset
Signed-off-by: Chen Shunqing <csq@rock-chips.com> Change-Id: Ia8f2a890433fd10f3fee4346e8d8a645385c5acf
This commit is contained in:
@@ -276,7 +276,13 @@ int rk628_media_i2c_write(struct rk628 *rk628, u32 reg, u32 val)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(rk628->regmap[region], reg, val);
|
||||
if (region == RK628_DEV_HDMIRX) {
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
ret = regmap_write(rk628->regmap[region], reg, val);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
} else {
|
||||
ret = regmap_write(rk628->regmap[region], reg, val);
|
||||
}
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err reg=0x%x, val=0x%x, ret=%d\n", __func__, reg, val, ret);
|
||||
@@ -296,7 +302,13 @@ int rk628_media_i2c_read(struct rk628 *rk628, u32 reg, u32 *val)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_read(rk628->regmap[region], reg, val);
|
||||
if (region == RK628_DEV_HDMIRX) {
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
ret = regmap_read(rk628->regmap[region], reg, val);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
} else {
|
||||
ret = regmap_read(rk628->regmap[region], reg, val);
|
||||
}
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err reg=0x%x, val=0x%x ret=%d\n", __func__, reg, *val, ret);
|
||||
@@ -309,6 +321,7 @@ int rk628_media_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
int ret;
|
||||
|
||||
if (region >= RK628_DEV_MAX) {
|
||||
dev_err(rk628->dev,
|
||||
@@ -316,7 +329,15 @@ int rk628_media_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rk628->regmap[region], reg, mask, val);
|
||||
if (region == RK628_DEV_HDMIRX) {
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
ret = regmap_update_bits(rk628->regmap[region], reg, mask, val);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
} else {
|
||||
ret = regmap_update_bits(rk628->regmap[region], reg, mask, val);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_media_i2c_update_bits);
|
||||
|
||||
|
||||
@@ -306,6 +306,8 @@ struct rk628 {
|
||||
bool dual_mipi;
|
||||
struct mipi_timing mipi_timing[2];
|
||||
struct mutex rst_lock;
|
||||
int dvi_mode;
|
||||
int vic;
|
||||
int tx_mode;
|
||||
int dbg_en;
|
||||
struct dentry *debug_dir;
|
||||
|
||||
@@ -347,6 +347,7 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd)
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_bt1120_hdmirx_reset(sd);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628);
|
||||
@@ -431,7 +432,7 @@ static void rk628_bt1120_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
if (plugin) {
|
||||
rk628_set_io_func_to_vop(bt1120->rk628);
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
cancel_delayed_work_sync(&bt1120->delayed_work_res_change);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_setup(bt1120->audio_info);
|
||||
rk628_hdmirx_set_hdcp(bt1120->rk628, &bt1120->hdcp, bt1120->hdcp.enable);
|
||||
rk628_hdmirx_controller_setup(bt1120->rk628);
|
||||
@@ -498,6 +499,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
if (bt1120->rk628->version >= RK628F_VERSION) {
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_bt1120_hdmirx_reset(sd);
|
||||
rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628);
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug,
|
||||
msecs_to_jiffies(100));
|
||||
@@ -516,6 +518,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
}
|
||||
} else {
|
||||
rk628_bt1120_format_change(sd);
|
||||
bt1120->nosignal = false;
|
||||
rk628_bt1120_enable_interrupts(sd, true);
|
||||
}
|
||||
}
|
||||
@@ -1120,11 +1123,9 @@ static int rk628_hdmirx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
mutex_lock(&bt1120->rk628->rst_lock);
|
||||
rk628_hdmirx_general_isr(sd, status, handled);
|
||||
if (bt1120->cec_enable && bt1120->cec)
|
||||
rk628_hdmirx_cec_irq(bt1120->rk628, bt1120->cec);
|
||||
mutex_unlock(&bt1120->rk628->rst_lock);
|
||||
|
||||
rk628_bt1120_clear_hdmirx_interrupts(sd);
|
||||
|
||||
|
||||
@@ -510,6 +510,7 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd)
|
||||
rk628_csi_enable_interrupts(sd, false);
|
||||
cancel_delayed_work(&csi->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true);
|
||||
rk628_csi_hdmirx_reset(sd);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_verisyno_phy_power_off(csi->rk628);
|
||||
@@ -567,7 +568,7 @@ static void rk628_csi_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
if (plugin) {
|
||||
extcon_set_state_sync(csi->extcon, EXTCON_JACK_VIDEO_IN, true);
|
||||
rk628_csi_enable_interrupts(sd, false);
|
||||
cancel_delayed_work_sync(&csi->delayed_work_res_change);
|
||||
cancel_delayed_work(&csi->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_setup(csi->audio_info);
|
||||
rk628_hdmirx_set_hdcp(csi->rk628, &csi->hdcp, csi->hdcp.enable);
|
||||
rk628_hdmirx_controller_setup(csi->rk628);
|
||||
@@ -632,13 +633,14 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
if (csi->rk628->version >= RK628F_VERSION) {
|
||||
rk628_csi_enable_interrupts(sd, false);
|
||||
rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true);
|
||||
rk628_csi_hdmirx_reset(sd);
|
||||
rk628_hdmirx_verisyno_phy_power_off(csi->rk628);
|
||||
schedule_delayed_work(&csi->delayed_work_enable_hotplug,
|
||||
msecs_to_jiffies(100));
|
||||
} else {
|
||||
rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(csi->rk628);
|
||||
rk628_csi_hdmirx_reset(sd);
|
||||
rk628_hdmirx_audio_setup(csi->audio_info);
|
||||
rk628_hdmirx_set_hdcp(csi->rk628, &csi->hdcp, csi->hdcp.enable);
|
||||
rk628_hdmirx_controller_setup(csi->rk628);
|
||||
@@ -651,6 +653,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
}
|
||||
} else {
|
||||
rk628_csi_format_change(sd);
|
||||
csi->nosignal = false;
|
||||
rk628_csi_enable_interrupts(sd, true);
|
||||
}
|
||||
}
|
||||
@@ -1852,11 +1855,9 @@ static int rk628_hdmirx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
{
|
||||
struct rk628_csi *csi = to_csi(sd);
|
||||
|
||||
mutex_lock(&csi->rk628->rst_lock);
|
||||
rk628_hdmirx_general_isr(sd, status, handled);
|
||||
if (csi->cec_enable && csi->cec)
|
||||
rk628_hdmirx_cec_irq(csi->rk628, csi->cec);
|
||||
mutex_unlock(&csi->rk628->rst_lock);
|
||||
|
||||
rk628_csi_clear_hdmirx_interrupts(sd);
|
||||
|
||||
@@ -2530,7 +2531,6 @@ 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;
|
||||
u32 stream = 0;
|
||||
int edid_version, i;
|
||||
|
||||
@@ -2583,8 +2583,7 @@ 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:
|
||||
rk628_i2c_read(csi->rk628, HDMI_RX_PDEC_STS, &val);
|
||||
*(int *)arg = val & DVI_DET;
|
||||
*(int *)arg = csi->rk628->dvi_mode;
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS:
|
||||
*(int *)arg = !csi->nosignal;
|
||||
@@ -2601,10 +2600,10 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
case RK_HDMIRX_CMD_SET_EDID_MODE:
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_COLOR_RANGE:
|
||||
*(int *)arg = rk628_hdmirx_get_range(csi->rk628);
|
||||
*(int *)arg = csi->rk628->color_range;
|
||||
break;
|
||||
case RK_HDMIRX_CMD_GET_COLOR_SPACE:
|
||||
*(int *)arg = rk628_hdmirx_get_color_space(csi->rk628);
|
||||
*(int *)arg = csi->rk628->color_space;
|
||||
break;
|
||||
case RKMODULE_GET_DSI_MODE:
|
||||
*(int *)arg = csi->dsi.vid_mode;
|
||||
|
||||
@@ -1126,10 +1126,8 @@ static int rk628_hdmirx_cec_log_addr(struct cec_adapter *adap, u8 logical_addr)
|
||||
else
|
||||
cec->addresses |= BIT(logical_addr) | BIT(15);
|
||||
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_ADDR_L, cec->addresses & 0xff);
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_ADDR_H, (cec->addresses >> 8) & 0xff);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1139,7 +1137,6 @@ static int rk628_hdmirx_cec_enable(struct cec_adapter *adap, bool enable)
|
||||
struct rk628_hdmirx_cec *cec = cec_get_drvdata(adap);
|
||||
struct rk628 *rk628 = cec->rk628;
|
||||
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
if (!enable) {
|
||||
rk628_i2c_write(rk628, HDMI_RX_AUD_CEC_IEN_CLR, ~0);
|
||||
rk628_i2c_update_bits(rk628, HDMI_RX_DMI_DISABLE_IF, CEC_ENABLE_MASK, 0);
|
||||
@@ -1156,7 +1153,6 @@ static int rk628_hdmirx_cec_enable(struct cec_adapter *adap, bool enable)
|
||||
irqs = ERROR_INIT_ENSET | NACK_ENSET | EOM_ENSET | DONE_ENSET;
|
||||
rk628_i2c_write(rk628, HDMI_RX_AUD_CEC_IEN_SET, irqs);
|
||||
}
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1188,13 +1184,11 @@ static int rk628_hdmirx_cec_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
if (msg_len <= 0)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
for (i = 0; i < msg_len; i++)
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_TX_DATA_0 + i * 4, msg->msg[i]);
|
||||
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_TX_CNT, msg_len);
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_CTRL, ctrl | CEC_SEND);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1298,7 +1292,6 @@ struct rk628_hdmirx_cec *rk628_hdmirx_cec_register(struct rk628 *rk628)
|
||||
rk628_i2c_update_bits(rk628, HDMI_RX_DMI_DISABLE_IF, CEC_ENABLE_MASK, CEC_ENABLE_MASK);
|
||||
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_TX_CNT, 0);
|
||||
rk628_i2c_write(rk628, HDMI_RX_CEC_RX_CNT, 0);
|
||||
/* clk_hdmirx_cec = 32.768k */
|
||||
rk628_clk_set_rate(rk628, CGU_CLK_HDMIRX_CEC, 32768);
|
||||
|
||||
@@ -1633,6 +1626,7 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
vic = (val & VID_IDENT_CODE_MASK) >> 24;
|
||||
rk628->vic = vic;
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_GCP_AVMUTE, &format);
|
||||
format = (format & PKTDEC_GCP_CD_MASK) >> 4;
|
||||
video_fmt = rk628_hdmirx_get_format(rk628);
|
||||
@@ -1641,6 +1635,8 @@ static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
rk628->color_range = color_range;
|
||||
color_space = rk628_hdmirx_get_color_space(rk628);
|
||||
rk628->color_space = color_space;
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_STS, &val);
|
||||
rk628->dvi_mode = val & DVI_DET;
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
//format:color depth, 5: 10bit, 4: 8bit
|
||||
if (format == 5) {
|
||||
@@ -1865,12 +1861,12 @@ void rk628_hdmirx_controller_reset(struct rk628 *rk628)
|
||||
udelay(10);
|
||||
rk628_control_deassert(rk628, RGU_HDMIRX);
|
||||
rk628_control_deassert(rk628, RGU_HDMIRX_PON);
|
||||
udelay(10);
|
||||
usleep_range(20 * 1000, 20 * 1100);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_SW_RST, 0x000101ff);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x00000000);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0000017f);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0001017f);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_controller_reset);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user