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:
Chen Shunqing
2025-04-16 10:12:24 +08:00
parent 610a9bdb86
commit 9042f7a974
5 changed files with 43 additions and 24 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);