From 41d5dce87df30b38a001e0dd8f14b4d9749d0d86 Mon Sep 17 00:00:00 2001 From: Zhibin Huang Date: Thu, 18 Apr 2024 17:35:56 +0800 Subject: [PATCH 1/9] arm64: dts: rockchip: rk3399-ind: Fix black screen on wake from sleep with low backlight Type: Fix Redmine ID: #453222 Associated modifications: N/A Test: N/A Signed-off-by: Zhibin Huang Change-Id: Idb7905027e6f53cf302b4dd218f28ec33b318dae --- arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dtsi index 98f04773e351..6b96f571c8cb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb-ind.dtsi @@ -39,7 +39,7 @@ compatible = "pwm-backlight"; pwms = <&pwm2 0 25000 0>; brightness-levels = < - 0 1 2 3 4 5 6 7 + 2 2 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 From 8a366952754df8da083de4cd2b276296866a3bbd Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Mon, 29 Apr 2024 11:45:47 +0800 Subject: [PATCH 2/9] media: i2c: rk628: fix the last few lines offset Change-Id: I232a15790ce10dbd316514e019b941a8632536cb Signed-off-by: Chen Shunqing --- drivers/media/i2c/rk628/rk628.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/rk628/rk628.c b/drivers/media/i2c/rk628/rk628.c index ba03abf3a680..adb2d128450a 100644 --- a/drivers/media/i2c/rk628/rk628.c +++ b/drivers/media/i2c/rk628/rk628.c @@ -573,6 +573,8 @@ static void calc_dsp_frm_hst_vst(const struct videomode *src, do_div(t_frm_st, src_pixclock); *dsp_frame_hst = do_div(t_frm_st, src_htotal); + if (src->vfront_porch < t_frm_st) + t_frm_st = src->vfront_porch; *dsp_frame_vst = t_frm_st; } From 54ebfaf34f055360d78444613bcde859ed6165ef Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Mon, 6 May 2024 11:10:56 +0800 Subject: [PATCH 3/9] media: i2c: rk628: fix mipi dphy reset and mipi timing Change-Id: I93fafa890dd81800c7dbe19549d6a548b7b74f59 Signed-off-by: Jianwei Fan --- drivers/media/i2c/rk628/rk628.h | 3 + drivers/media/i2c/rk628/rk628_csi_v4l2.c | 77 +++++++++++++---------- drivers/media/i2c/rk628/rk628_dsi.c | 28 +++++++-- drivers/media/i2c/rk628/rk628_mipi_dphy.c | 41 +++++------- drivers/media/i2c/rk628/rk628_mipi_dphy.h | 5 +- 5 files changed, 87 insertions(+), 67 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628.h b/drivers/media/i2c/rk628/rk628.h index d3fc15ea4ca5..7a5146b16d87 100644 --- a/drivers/media/i2c/rk628/rk628.h +++ b/drivers/media/i2c/rk628/rk628.h @@ -279,9 +279,11 @@ enum { }; struct mipi_timing { + u8 data_lp; u8 data_prepare; u8 data_zero; u8 data_trail; + u8 clk_lp; u8 clk_prepare; u8 clk_zero; u8 clk_trail; @@ -302,6 +304,7 @@ struct rk628 { int dbg_en; struct dentry *debug_dir; struct gpio_desc *hdmirx_det_gpio; + bool last_mipi_status; }; #define rk628_dbg(rk628, format, ...) \ diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 57d6d2d91fad..6cd7f0e09ad5 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -245,20 +245,20 @@ static const unsigned int rk628_csi_extcon_cable[] = { }; static const struct mipi_timing rk628d_csi_mipi = { - 0x4a, 0xf, 0x5d, 0x3a, 0x3a, 0x5a, 0x1f + 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f }; static const struct mipi_timing rk628f_csi0_mipi = { - 0x4a, 0xf, 0x5d, 0x3a, 0x3a, 0x5a, 0x1f + 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f }; static const struct mipi_timing rk628f_csi1_mipi = { -//data-pre, data-zero, data-trail, clk-pre, clk-zero, clk-trail, clk-post - 0x4a, 0xf, 0x66, 0x3a, 0x3a, 0x5a, 0x1f +//data_lp, data-pre, data-zero, data-trail, clk_lp, clk-pre, clk-zero, clk-trail, clk-post + 0x0b, 0x53, 0x10, 0x5b, 0x0b, 0x43, 0x2c, 0x50, 0x0f }; static const struct mipi_timing rk628f_dsi0_mipi = { - 0x70, 0x1c, 0x7f, 0x70, 0x3f, 0x7f, 0x1f + 0x10, 0x70, 0x1c, 0x7f, 0x10, 0x70, 0x3f, 0x7f, 0x1f }; static struct rkmodule_csi_dphy_param rk3588_dcphy_param = { @@ -811,45 +811,34 @@ static void rk628_dsi_enable(struct v4l2_subdev *sd) csi->dsi.timings = csi->timings; csi->dsi.lane_mbps = csi->lane_mbps; rk628_mipi_dsi_power_on(&csi->dsi); + rk628_mipi_txdata_reset(sd); csi->txphy_pwron = true; v4l2_dbg(2, debug, sd, "%s: txphy power on!\n", __func__); usleep_range(1000, 1500); rk628_dsi_set_scs(csi); } -static void enable_dsitx(struct v4l2_subdev *sd) +static void rk628_dsi_disable(struct v4l2_subdev *sd) { struct rk628_csi *csi = to_csi(sd); - /* rst for dsi0 */ - rk628_control_assert(csi->rk628, RGU_DSI0); - udelay(20); - rk628_control_deassert(csi->rk628, RGU_DSI0); - udelay(20); - - /* rst for dsi1 */ - rk628_control_assert(csi->rk628, RGU_DSI1); - udelay(20); - rk628_control_deassert(csi->rk628, RGU_DSI1); - udelay(20); + rk628_dsi_disable_stream(&csi->dsi); + csi->txphy_pwron = false; +} +static void enable_dsitx(struct v4l2_subdev *sd) +{ + rk628_dsi_disable(sd); rk628_dsi_enable(sd); } -static void rk628_dsi_enable_stream(struct v4l2_subdev *sd, bool en) +static void rk628_disable_dsitx(struct v4l2_subdev *sd) { struct rk628_csi *csi = to_csi(sd); - if (en) { - rk628_hdmirx_vid_enable(sd, true); - rk628_i2c_write(csi->rk628, GRF_SCALER_CON0, SCL_EN(1)); - rk628_dsi_set_scs(csi); - return; - } - rk628_hdmirx_vid_enable(sd, false); rk628_i2c_write(csi->rk628, GRF_SCALER_CON0, SCL_EN(0)); - rk628_dsi_disable_stream(&csi->dsi); + rk628_dsi_disable(sd); } static void rk628_csi_disable_stream(struct v4l2_subdev *sd) @@ -871,6 +860,8 @@ static void rk628_csi_disable_stream(struct v4l2_subdev *sd) csi->continues_clk ? CONT_MODE_CLK_CLR(1) : CONT_MODE_CLK_CLR(0)); rk628_i2c_write(csi->rk628, CSITX1_CONFIG_DONE, CONFIG_DONE_IMD); } + mipi_dphy_power_off(csi); + csi->txphy_pwron = false; } static void enable_stream(struct v4l2_subdev *sd, bool en) @@ -902,7 +893,7 @@ static void enable_stream(struct v4l2_subdev *sd, bool en) rk628_hdmirx_vid_enable(sd, false); rk628_csi_disable_stream(sd); } else { - rk628_dsi_enable_stream(sd, en); + rk628_disable_dsitx(sd); } csi->is_streaming = false; } @@ -970,7 +961,6 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd) rk628_csi0_cru_reset(sd); if (csi->rk628->version >= RK628F_VERSION) rk628_csi1_cru_reset(sd); - rk628_mipi_dphy_reset(csi->rk628); rk628_post_process_setup(sd); if (csi->txphy_pwron) { @@ -1400,10 +1390,9 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd) } csi->rk628->dphy_lane_en = 0x1f; - if (csi->plat_data->tx_mode == CSI_MODE) { - rk628_mipi_dphy_reset(csi->rk628); + if (csi->plat_data->tx_mode == CSI_MODE) mipi_dphy_power_on(csi); - } + csi->txphy_pwron = true; if (tx_5v_power_present(sd)) schedule_delayed_work(&csi->delayed_work_enable_hotplug, msecs_to_jiffies(4000)); @@ -2338,7 +2327,7 @@ static void rk628_csi_reset_streaming(struct v4l2_subdev *sd, int on) msleep(20); rk628_csi_disable_stream(sd); } else { - rk628_dsi_enable_stream(sd, false); + rk628_disable_dsitx(sd); } csi->is_streaming = false; } @@ -2381,7 +2370,7 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKMODULE_GET_CAPTURE_MODE: capture_info = (struct rkmodule_capture_info *)arg; if (csi->rk628->dual_mipi) { - v4l2_info(sd, "set dual mipi mode\n"); + v4l2_dbg(1, debug, sd, "set dual mipi mode\n"); capture_info->mode = RKMODULE_MULTI_DEV_COMBINE_ONE; capture_info->multi_dev = csi->multi_dev_info; } else { @@ -2449,6 +2438,7 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) unsigned int val; u32 bus_width, mask; struct v4l2_subdev *sd = &csi->sd; + int ret; if (csi->timings.bt.pixelclock > 150000000 || csi->csi_lanes_in_use <= 2) { csi->lane_mbps = MIPI_DATARATE_MBPS_HIGH; @@ -2466,6 +2456,7 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) rk628_txphy_set_bus_width(csi->rk628, bus_width); rk628_txphy_set_mode(csi->rk628, PHY_MODE_VIDEO_MIPI); + rk628_mipi_dphy_reset_assert(csi->rk628); rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 0); if (csi->rk628->version >= RK628F_VERSION) rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1); @@ -2482,7 +2473,7 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) if (csi->rk628->version >= RK628F_VERSION) rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1); } - + rk628_mipi_dphy_reset_deassert(csi->rk628); usleep_range(1500, 2000); rk628_txphy_power_on(csi->rk628); @@ -2502,6 +2493,24 @@ static int mipi_dphy_power_on(struct rk628_csi *csi) } udelay(10); + mask = STOPSTATE_CLK | STOPSTATE_LANE0; + ret = regmap_read_poll_timeout(csi->rk628->regmap[RK628_DEV_CSI], + CSITX_CSITX_STATUS1, + val, (val & mask) == mask, + 0, 1000); + if (ret < 0) + dev_err(csi->rk628->dev, "csi0 lane module is not in stop state, val: 0x%x\n", val); + + if (csi->rk628->version >= RK628F_VERSION) { + ret = regmap_read_poll_timeout(csi->rk628->regmap[RK628_DEV_CSI1], + CSITX1_CSITX_STATUS1, + val, (val & mask) == mask, + 0, 1000); + if (ret < 0) + dev_err(csi->rk628->dev, + "csi1 lane module is not in stop state, val: 0x%x\n", val); + } + return 0; } diff --git a/drivers/media/i2c/rk628/rk628_dsi.c b/drivers/media/i2c/rk628/rk628_dsi.c index 1712061fb992..b1499796519b 100644 --- a/drivers/media/i2c/rk628/rk628_dsi.c +++ b/drivers/media/i2c/rk628/rk628_dsi.c @@ -341,13 +341,27 @@ void rk628_mipi_dsi_power_on(struct rk628_dsi *dsi) dev_info(dsi->rk628->dev, "%s mipi bitrate:%llu mbps\n", __func__, dsi->lane_mbps); + /* rst for dsi0 */ + rk628_control_assert(dsi->rk628, RGU_DSI0); + udelay(20); + rk628_control_deassert(dsi->rk628, RGU_DSI0); + udelay(20); + rk628_dsi_pre_enable(dsi, 0); - if (rk628->dual_mipi) + + if (rk628->dual_mipi) { + /* rst for dsi1 */ + rk628_control_assert(dsi->rk628, RGU_DSI1); + udelay(20); + rk628_control_deassert(dsi->rk628, RGU_DSI1); + udelay(20); rk628_dsi_pre_enable(dsi, 1); + } rk628_dsi_enable(dsi, 0); if (rk628->dual_mipi) rk628_dsi_enable(dsi, 1); + rk628->last_mipi_status = rk628->dual_mipi; } EXPORT_SYMBOL(rk628_mipi_dsi_power_on); @@ -361,11 +375,13 @@ void rk628_dsi_disable_stream(struct rk628_dsi *dsi) dsi_write(rk628, 0, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE)); dsi_write(rk628, 0, DSI_PWR_UP, POWER_UP); - dsi_write(rk628, 1, DSI_PWR_UP, RESET); - dsi_write(rk628, 1, DSI_LPCLK_CTRL, 0); - dsi_write(rk628, 1, DSI_EDPI_CMD_SIZE, 0); - dsi_write(rk628, 1, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE)); - dsi_write(rk628, 1, DSI_PWR_UP, POWER_UP); + if (rk628->last_mipi_status) { + dsi_write(rk628, 1, DSI_PWR_UP, RESET); + dsi_write(rk628, 1, DSI_LPCLK_CTRL, 0); + dsi_write(rk628, 1, DSI_EDPI_CMD_SIZE, 0); + dsi_write(rk628, 1, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE)); + dsi_write(rk628, 1, DSI_PWR_UP, POWER_UP); + } rk628_txphy_power_off(rk628); } diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.c b/drivers/media/i2c/rk628/rk628_mipi_dphy.c index 8a9fe28458fa..5b53a6028ebf 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.c +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.c @@ -193,6 +193,9 @@ void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mip dev_info(rk628->dev, "mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false"); //config mipi timing when mipi freq is 1250Mbps + rk628_testif_write(rk628, 0x70, + manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_lp) | BIT(6)) : 0, mipi_id); + usleep_range(1500, 2000); rk628_testif_write(rk628, 0x71, manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id); usleep_range(1500, 2000); @@ -202,6 +205,9 @@ void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mip rk628_testif_write(rk628, 0x73, manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id); usleep_range(1500, 2000); + rk628_testif_write(rk628, 0x60, + manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_lp) | BIT(6)) : 0, mipi_id); + usleep_range(1500, 2000); rk628_testif_write(rk628, 0x61, manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id); usleep_range(1500, 2000); @@ -212,15 +218,12 @@ void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mip manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id); usleep_range(1500, 2000); rk628_testif_write(rk628, 0x65, - manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(5)) : 0, mipi_id); + manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(4)) : 0, mipi_id); } EXPORT_SYMBOL(rk628_mipi_dphy_init_hsmanual); -int rk628_mipi_dphy_reset(struct rk628 *rk628) +int rk628_mipi_dphy_reset_assert(struct rk628 *rk628) { - u32 val, mask; - int ret; - rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1); if (rk628->version >= RK628F_VERSION) rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x1); @@ -248,6 +251,13 @@ int rk628_mipi_dphy_reset(struct rk628 *rk628) mipi_dphy_enablelane_assert(rk628, 0); if (rk628->version >= RK628F_VERSION) mipi_dphy_enablelane_assert(rk628, 1); + + return 0; +} +EXPORT_SYMBOL(rk628_mipi_dphy_reset_assert); + +int rk628_mipi_dphy_reset_deassert(struct rk628 *rk628) +{ mipi_dphy_shutdownz_deassert(rk628); mipi_dphy_rstz_deassert(rk628); rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x0); @@ -255,25 +265,6 @@ int rk628_mipi_dphy_reset(struct rk628 *rk628) rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x0); usleep_range(10000, 11000); - mask = STOPSTATE_CLK | STOPSTATE_LANE0; - - ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI], - CSITX_CSITX_STATUS1, - val, (val & mask) == mask, - 0, 1000); - if (ret < 0) - dev_err(rk628->dev, "csi0 lane module is not in stop state, val: 0x%x\n", val); - - if (rk628->version >= RK628F_VERSION) { - ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI1], - CSITX1_CSITX_STATUS1, - val, (val & mask) == mask, - 0, 1000); - if (ret < 0) - dev_err(rk628->dev, - "csi1 lane module is not in stop state, val: 0x%x\n", val); - } - return 0; } -EXPORT_SYMBOL(rk628_mipi_dphy_reset); +EXPORT_SYMBOL(rk628_mipi_dphy_reset_deassert); diff --git a/drivers/media/i2c/rk628/rk628_mipi_dphy.h b/drivers/media/i2c/rk628/rk628_mipi_dphy.h index 531dfe440415..923cc3eaa034 100644 --- a/drivers/media/i2c/rk628/rk628_mipi_dphy.h +++ b/drivers/media/i2c/rk628/rk628_mipi_dphy.h @@ -14,7 +14,7 @@ #define HSFREQRANGE(x) UPDATE(x, 6, 1) #define HSTX(x) UPDATE(x, 6, 0) #define HSZERO(x) UPDATE(x, 5, 0) -#define HSPOST(x) UPDATE(x, 4, 0) +#define HSPOST(x) UPDATE(x, 3, 0) #define HSEXIT(x) UPDATE(x, 4, 0) void rk628_testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id); @@ -23,6 +23,7 @@ u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t m u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id); void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id); void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id); -int rk628_mipi_dphy_reset(struct rk628 *rk628); +int rk628_mipi_dphy_reset_assert(struct rk628 *rk628); +int rk628_mipi_dphy_reset_deassert(struct rk628 *rk628); #endif From 853e8825b386d20de9272506287188efcf19acda Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Mon, 6 May 2024 11:12:57 +0800 Subject: [PATCH 4/9] media: i2c: rk628: disable tx stream when plug interrupt Change-Id: Ib014617ebd53e34a731420d5ebda0479e824017d Signed-off-by: Jianwei Fan --- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 6cd7f0e09ad5..0ad5720c11a2 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -744,6 +744,7 @@ static void enable_csitx(struct v4l2_subdev *sd) rk628_i2c_write(csi->rk628, CSITX1_ERR_INTR_CLR_IMD, 0xffffffff); rk628_i2c_write(csi->rk628, CSITX1_CONFIG_DONE, CONFIG_DONE_IMD); } + csi->is_streaming = true; } static void rk628_dsi_set_scs(struct rk628_csi *csi) @@ -862,6 +863,7 @@ static void rk628_csi_disable_stream(struct v4l2_subdev *sd) } mipi_dphy_power_off(csi); csi->txphy_pwron = false; + csi->is_streaming = false; } static void enable_stream(struct v4l2_subdev *sd, bool en) @@ -885,7 +887,6 @@ static void enable_stream(struct v4l2_subdev *sd, bool en) rk628_csi_enable_csi_interrupts(sd, true); } rk628_hdmirx_vid_enable(sd, true); - csi->is_streaming = true; } else { if (csi->plat_data->tx_mode == CSI_MODE) { rk628_csi_enable_csi_interrupts(sd, false); @@ -895,7 +896,6 @@ static void enable_stream(struct v4l2_subdev *sd, bool en) } else { rk628_disable_dsitx(sd); } - csi->is_streaming = false; } } @@ -2315,11 +2315,11 @@ static void rk628_csi_reset_streaming(struct v4l2_subdev *sd, int on) rk628_i2c_write(csi->rk628, CSITX1_CONFIG_DONE, CONFIG_DONE_IMD); } rk628_csi_enable_csi_interrupts(sd, true); + csi->is_streaming = true; } else { enable_dsitx(sd); } rk628_hdmirx_vid_enable(sd, true); - csi->is_streaming = true; } else { rk628_hdmirx_vid_enable(sd, false); if (csi->plat_data->tx_mode == CSI_MODE) { @@ -2329,7 +2329,6 @@ static void rk628_csi_reset_streaming(struct v4l2_subdev *sd, int on) } else { rk628_disable_dsitx(sd); } - csi->is_streaming = false; } v4l2_info(sd, "%s: on: %d, %dx%d@%d\n", __func__, on, csi->timings.bt.width, @@ -2872,6 +2871,12 @@ static irqreturn_t plugin_detect_irq(int irq, void *dev_id) .type = RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST, }; + if (csi->plat_data->tx_mode == DSI_MODE) + rk628_dsi_disable(sd); + if (csi->plat_data->tx_mode == CSI_MODE) { + rk628_csi_enable_csi_interrupts(sd, false); + rk628_csi_disable_stream(sd); + } /* control hpd after 50ms */ schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20); v4l2_event_queue(sd->devnode, &evt_signal_lost); From ee034abd435f638eb3b85c04550b0e4941c91e38 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Fri, 19 Apr 2024 14:40:22 +0800 Subject: [PATCH 5/9] media: i2c: rk628: hdmirx phy power off when plug out Change-Id: I0173e25ce4c87ba883c87c36322112a7d1821c30 Signed-off-by: Chen Shunqing --- drivers/media/i2c/rk628/rk628_bt1120_v4l2.c | 3 ++- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 3 ++- drivers/media/i2c/rk628/rk628_hdmirx.c | 9 +++++++++ drivers/media/i2c/rk628/rk628_hdmirx.h | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 09646df819c2..3e6df9a151e0 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -332,6 +332,7 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true); rk628_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_inno_phy_power_off(sd); + rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628); rk628_hdmirx_controller_reset(bt1120->rk628); rk628_clk_set_rate(bt1120->rk628, CGU_CLK_CPLL, CPLL_REF_CLK); } @@ -471,7 +472,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work) rk628_bt1120_enable_interrupts(sd, false); rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true); rk628_hdmirx_hpd_ctrl(sd, false); - rk628_hdmirx_inno_phy_power_off(sd); + rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628); rk628_hdmirx_controller_reset(bt1120->rk628); schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, msecs_to_jiffies(1100)); diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 0ad5720c11a2..02c3075dbc40 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -474,6 +474,7 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true); rk628_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_inno_phy_power_off(sd); + rk628_hdmirx_verisyno_phy_power_off(csi->rk628); rk628_hdmirx_controller_reset(csi->rk628); rk628_clk_set_rate(csi->rk628, CGU_CLK_CPLL, CPLL_REF_CLK); } @@ -580,7 +581,7 @@ static void rk628_delayed_work_res_change(struct work_struct *work) rk628_csi_enable_interrupts(sd, false); rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true); rk628_hdmirx_hpd_ctrl(sd, false); - rk628_hdmirx_inno_phy_power_off(sd); + rk628_hdmirx_verisyno_phy_power_off(csi->rk628); rk628_hdmirx_controller_reset(csi->rk628); schedule_delayed_work(&csi->delayed_work_enable_hotplug, msecs_to_jiffies(1100)); diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.c b/drivers/media/i2c/rk628/rk628_hdmirx.c index 10875baff934..4329e7234d9f 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.c +++ b/drivers/media/i2c/rk628/rk628_hdmirx.c @@ -1186,6 +1186,15 @@ void rk628_hdmirx_verisyno_phy_power_on(struct rk628 *rk628) } EXPORT_SYMBOL(rk628_hdmirx_verisyno_phy_power_on); +void rk628_hdmirx_verisyno_phy_power_off(struct rk628 *rk628) +{ + if (rk628->version < RK628F_VERSION) + return; + + rk628_i2c_write(rk628, GRF_SW_HDMIRXPHY_CRTL, 0x07); +} +EXPORT_SYMBOL(rk628_hdmirx_verisyno_phy_power_off); + void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628) { u32 format; diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.h b/drivers/media/i2c/rk628/rk628_hdmirx.h index bb88f3bc3993..b9deafed68f6 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.h +++ b/drivers/media/i2c/rk628/rk628_hdmirx.h @@ -511,6 +511,7 @@ void rk628_csi_isr_ctsn(HAUDINFO info, u32 pdec_ints); void rk628_csi_isr_fifoints(HAUDINFO info, u32 fifo_ints); int rk628_is_avi_ready(struct rk628 *rk628, bool avi_rcv_rdy); void rk628_hdmirx_verisyno_phy_power_on(struct rk628 *rk628); +void rk628_hdmirx_verisyno_phy_power_off(struct rk628 *rk628); void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628); int rk628_hdmirx_verisyno_phy_init(struct rk628 *rk628); u8 rk628_hdmirx_get_format(struct rk628 *rk628); From c7111f012dda0d0cc37946c80bd0f3e3c134926f Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Thu, 25 Apr 2024 10:59:56 +0800 Subject: [PATCH 6/9] media: i2c: rk628: remove hdmirx ctrl reset for rk628f Signed-off-by: Chen Shunqing Change-Id: I2941f2269f8ae64fdaf1c1d399eb9b5d68b199db --- drivers/media/i2c/rk628/rk628_bt1120_v4l2.c | 51 ++++++++------------- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 51 +++++++-------------- drivers/media/i2c/rk628/rk628_hdmirx.c | 4 ++ drivers/media/i2c/rk628/rk628_hdmirx.h | 1 + 4 files changed, 40 insertions(+), 67 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 3e6df9a151e0..7e56090e6883 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -74,7 +74,6 @@ struct rk628_bt1120 { struct clk *clk_rx_read; struct delayed_work delayed_work_enable_hotplug; struct delayed_work delayed_work_res_change; - struct work_struct work_isr; struct timer_list timer; struct work_struct work_i2c_poll; struct mutex confctl_mutex; @@ -333,7 +332,6 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) rk628_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_inno_phy_power_off(sd); rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628); - rk628_hdmirx_controller_reset(bt1120->rk628); rk628_clk_set_rate(bt1120->rk628, CGU_CLK_CPLL, CPLL_REF_CLK); } @@ -406,6 +404,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); rk628_hdmirx_audio_setup(bt1120->audio_info); rk628_hdmirx_set_hdcp(bt1120->rk628, &bt1120->hdcp, bt1120->hdcp.enable); rk628_hdmirx_controller_setup(bt1120->rk628); @@ -471,9 +470,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_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_verisyno_phy_power_off(bt1120->rk628); - rk628_hdmirx_controller_reset(bt1120->rk628); schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, msecs_to_jiffies(1100)); } else { @@ -960,17 +957,19 @@ static void rk628_bt1120_clear_hdmirx_interrupts(struct v4l2_subdev *sd) rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x01000100); } -static void rk628_work_isr(struct work_struct *work) +static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled) { - struct rk628_bt1120 *bt1120 = container_of(work, struct rk628_bt1120, work_isr); - struct v4l2_subdev *sd = &bt1120->sd; + struct rk628_bt1120 *bt1120 = to_bt1120(sd); u32 md_ints, pdec_ints, fifo_ints, hact, vact; bool plugin; void *audio_info = bt1120->audio_info; - bool handled = false; u32 int0_status; - mutex_lock(&bt1120->rk628->rst_lock); + if (handled == NULL) { + v4l2_err(sd, "handled NULL, err return!\n"); + return -EINVAL; + } + rk628_i2c_read(bt1120->rk628, GRF_INTR0_STATUS, &int0_status); v4l2_dbg(1, debug, sd, "%s: int0 status: 0x%x\n", __func__, int0_status); @@ -980,24 +979,25 @@ static void rk628_work_isr(struct work_struct *work) rk628_hdmirx_is_signal_change_ists(bt1120->rk628, md_ints, pdec_ints)) rk628_set_bg_enable(bt1120->rk628, true); - rk628_bt1120_clear_hdmirx_interrupts(sd); plugin = tx_5v_power_present(sd); - if (!plugin) + if (!plugin) { rk628_bt1120_enable_interrupts(sd, false); + return 0; + } if (bt1120->rk628->version < RK628F_VERSION) { if (rk628_audio_ctsnints_enabled(audio_info)) { if (pdec_ints & (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) { rk628_csi_isr_ctsn(audio_info, pdec_ints); pdec_ints &= ~(ACR_CTS_CHG_ICLR | ACR_CTS_CHG_ICLR); - handled = true; + *handled = true; } } if (rk628_audio_fifoints_enabled(audio_info)) { rk628_i2c_read(bt1120->rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints); if (fifo_ints & 0x18) { rk628_csi_isr_fifoints(audio_info, fifo_ints); - handled = true; + *handled = true; } } } @@ -1021,7 +1021,7 @@ static void rk628_work_isr(struct work_struct *work) v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n", __func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS))); - handled = true; + *handled = true; } if ((pdec_ints & AVI_RCV_ISTS) && plugin && !bt1120->avi_rcv_rdy) { @@ -1030,26 +1030,12 @@ static void rk628_work_isr(struct work_struct *work) /* After get the AVI_RCV interrupt state, disable interrupt. */ rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS); - handled = true; + *handled = true; } } - if (!handled) + if (*handled != true) v4l2_dbg(1, debug, sd, "%s: unhandled interrupt!\n", __func__); - mutex_unlock(&bt1120->rk628->rst_lock); -} - -static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled) -{ - struct rk628_bt1120 *bt1120 = to_bt1120(sd); - - if (handled == NULL) { - v4l2_err(sd, "handled NULL, err return!\n"); - return -EINVAL; - } - - schedule_work(&bt1120->work_isr); - return 0; } @@ -1063,6 +1049,8 @@ static irqreturn_t rk628_bt1120_irq_handler(int irq, void *dev_id) if (bt1120->cec_enable && bt1120->cec) rk628_hdmirx_cec_irq(bt1120->rk628, bt1120->cec); + rk628_bt1120_clear_hdmirx_interrupts(&bt1120->sd); + return handled ? IRQ_HANDLED : IRQ_NONE; } @@ -2015,7 +2003,6 @@ static int rk628_bt1120_probe(struct i2c_client *client, rk628_bt1120_delayed_work_enable_hotplug); INIT_DELAYED_WORK(&bt1120->delayed_work_res_change, rk628_delayed_work_res_change); - INIT_WORK(&bt1120->work_isr, rk628_work_isr); bt1120->audio_info = rk628_hdmirx_audioinfo_alloc(dev, &bt1120->confctl_mutex, rk628, @@ -2083,7 +2070,6 @@ err_work_queues: flush_work(&bt1120->work_i2c_poll); cancel_delayed_work(&bt1120->delayed_work_enable_hotplug); cancel_delayed_work(&bt1120->delayed_work_res_change); - cancel_work_sync(&bt1120->work_isr); rk628_hdmirx_audio_destroy(bt1120->audio_info); err_hdl: mutex_destroy(&bt1120->confctl_mutex); @@ -2108,7 +2094,6 @@ static void rk628_bt1120_remove(struct i2c_client *client) cancel_delayed_work_sync(&bt1120->delayed_work_enable_hotplug); cancel_delayed_work_sync(&bt1120->delayed_work_res_change); - cancel_work_sync(&bt1120->work_isr); rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true); rk628_hdmirx_audio_cancel_work_rate_change(bt1120->audio_info, true); diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 02c3075dbc40..da5834a1f048 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -97,7 +97,6 @@ struct rk628_csi { struct clk *clk_rx_read; struct delayed_work delayed_work_enable_hotplug; struct delayed_work delayed_work_res_change; - struct work_struct work_isr; struct timer_list timer; struct work_struct work_i2c_poll; struct mutex confctl_mutex; @@ -475,7 +474,6 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) rk628_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_inno_phy_power_off(sd); rk628_hdmirx_verisyno_phy_power_off(csi->rk628); - rk628_hdmirx_controller_reset(csi->rk628); rk628_clk_set_rate(csi->rk628, CGU_CLK_CPLL, CPLL_REF_CLK); } @@ -517,6 +515,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); rk628_hdmirx_audio_setup(csi->audio_info); rk628_hdmirx_set_hdcp(csi->rk628, &csi->hdcp, csi->hdcp.enable); rk628_hdmirx_controller_setup(csi->rk628); @@ -580,9 +579,7 @@ 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_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_verisyno_phy_power_off(csi->rk628); - rk628_hdmirx_controller_reset(csi->rk628); schedule_delayed_work(&csi->delayed_work_enable_hotplug, msecs_to_jiffies(1100)); } else { @@ -1640,21 +1637,23 @@ static void rk628_csi_error_process(struct v4l2_subdev *sd) } } -static void rk628_work_isr(struct work_struct *work) +static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled) { - struct rk628_csi *csi = container_of(work, struct rk628_csi, work_isr); - struct v4l2_subdev *sd = &csi->sd; + struct rk628_csi *csi = to_csi(sd); u32 md_ints = 0x0, pdec_ints = 0x0, fifo_ints, hact, vact; bool plugin; void *audio_info = csi->audio_info; - bool handled = false; u32 csi0_raw_ints = 0x0, csi1_raw_ints = 0x0; u32 int0_status; const struct v4l2_event evt_signal_lost = { .type = RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST, }; - mutex_lock(&csi->rk628->rst_lock); + if (handled == NULL) { + v4l2_err(sd, "handled NULL, err return!\n"); + return -EINVAL; + } + rk628_i2c_read(csi->rk628, GRF_INTR0_STATUS, &int0_status); v4l2_dbg(1, debug, sd, "%s: int0 status: 0x%x\n", __func__, int0_status); @@ -1664,7 +1663,6 @@ static void rk628_work_isr(struct work_struct *work) if (csi->rk628->version >= RK628F_VERSION && rk628_hdmirx_is_signal_change_ists(csi->rk628, md_ints, pdec_ints)) rk628_set_bg_enable(csi->rk628, true); - rk628_csi_clear_hdmirx_interrupts(sd); } if ((int0_status & (BIT(6) | BIT(7)))) { rk628_i2c_read(csi->rk628, CSITX_ERR_INTR_RAW_STATUS_IMD, &csi0_raw_ints); @@ -1677,6 +1675,7 @@ static void rk628_work_isr(struct work_struct *work) if (!plugin) { rk628_csi_enable_interrupts(sd, false); rk628_csi_enable_csi_interrupts(sd, false); + return 0; } if (csi->rk628->version < RK628F_VERSION && (int0_status & BIT(8))) { @@ -1684,14 +1683,14 @@ static void rk628_work_isr(struct work_struct *work) if (pdec_ints & (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) { rk628_csi_isr_ctsn(audio_info, pdec_ints); pdec_ints &= ~(ACR_CTS_CHG_ICLR | ACR_CTS_CHG_ICLR); - handled = true; + *handled = true; } } if (rk628_audio_fifoints_enabled(audio_info)) { rk628_i2c_read(csi->rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints); if (fifo_ints & 0x18) { rk628_csi_isr_fifoints(audio_info, fifo_ints); - handled = true; + *handled = true; } } } @@ -1715,7 +1714,7 @@ static void rk628_work_isr(struct work_struct *work) v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n", __func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS))); - handled = true; + *handled = true; } if ((pdec_ints & AVI_RCV_ISTS) && plugin && !csi->avi_rcv_rdy) { @@ -1726,7 +1725,7 @@ static void rk628_work_isr(struct work_struct *work) /* After get the AVI_RCV interrupt state, disable interrupt. */ rk628_i2c_write(csi->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS); - handled = true; + *handled = true; } } @@ -1735,27 +1734,12 @@ static void rk628_work_isr(struct work_struct *work) "%s: csi interrupt: csi0_raw_ints: 0x%x, csi1_raw_ints: 0x%x!\n", __func__, csi0_raw_ints, csi1_raw_ints); rk628_csi_error_process(sd); - handled = true; + *handled = true; } - if (!handled) + if (*handled != true) v4l2_dbg(1, debug, sd, "%s: unhandled interrupt!\n", __func__); - mutex_unlock(&csi->rk628->rst_lock); -} - - -static int rk628_csi_isr(struct v4l2_subdev *sd, u32 status, bool *handled) -{ - struct rk628_csi *csi = to_csi(sd); - - if (handled == NULL) { - v4l2_err(sd, "handled NULL, err return!\n"); - return -EINVAL; - } - - schedule_work(&csi->work_isr); - return 0; } @@ -1769,6 +1753,8 @@ static irqreturn_t rk628_csi_irq_handler(int irq, void *dev_id) if (csi->cec_enable && csi->cec) rk628_hdmirx_cec_irq(csi->rk628, csi->cec); + rk628_csi_clear_hdmirx_interrupts(&csi->sd); + return handled ? IRQ_HANDLED : IRQ_NONE; } @@ -3368,7 +3354,6 @@ static int rk628_csi_probe(struct i2c_client *client, rk628_csi_delayed_work_enable_hotplug); INIT_DELAYED_WORK(&csi->delayed_work_res_change, rk628_delayed_work_res_change); - INIT_WORK(&csi->work_isr, rk628_work_isr); csi->audio_info = rk628_hdmirx_audioinfo_alloc(dev, &csi->confctl_mutex, rk628, @@ -3440,7 +3425,6 @@ err_work_queues: flush_work(&csi->work_i2c_poll); cancel_delayed_work(&csi->delayed_work_enable_hotplug); cancel_delayed_work(&csi->delayed_work_res_change); - cancel_work_sync(&csi->work_isr); rk628_hdmirx_audio_destroy(csi->audio_info); err_hdl: mutex_destroy(&csi->confctl_mutex); @@ -3473,7 +3457,6 @@ static int rk628_csi_remove(struct i2c_client *client) rk628_hdmirx_audio_cancel_work_rate_change(csi->audio_info, true); cancel_delayed_work_sync(&csi->delayed_work_enable_hotplug); cancel_delayed_work_sync(&csi->delayed_work_res_change); - cancel_work_sync(&csi->work_isr); if (csi->rxphy_pwron) rk628_rxphy_power_off(csi->rk628); diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.c b/drivers/media/i2c/rk628/rk628_hdmirx.c index 4329e7234d9f..ef69600a5340 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.c +++ b/drivers/media/i2c/rk628/rk628_hdmirx.c @@ -181,6 +181,7 @@ static int rk628_hdmi_hdcp_load_key(struct rk628 *rk628, struct rk628_hdcp *hdcp KEY_DECRIPT_ENABLE_MASK, KEY_DECRIPT_ENABLE(0)); } + hdcp->hdcp_start = true; return 0; } @@ -192,6 +193,8 @@ void rk628_hdmirx_set_hdcp(struct rk628 *rk628, struct rk628_hdcp *hdcp, bool en hdcp->rk628 = rk628; hdcp->enable = en; if (en) { + if (hdcp->hdcp_start && rk628->version >= RK628F_VERSION) + return; rk628_hdmi_hdcp_load_key(rk628, hdcp); } else { rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL, @@ -199,6 +202,7 @@ void rk628_hdmirx_set_hdcp(struct rk628 *rk628, struct rk628_hdcp *hdcp, bool en HDCP_ENC_EN_MASK, HDCP_ENABLE(0) | HDCP_ENC_EN(0)); + hdcp->hdcp_start = false; } } EXPORT_SYMBOL(rk628_hdmirx_set_hdcp); diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.h b/drivers/media/i2c/rk628/rk628_hdmirx.h index b9deafed68f6..1f0a302a75a8 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.h +++ b/drivers/media/i2c/rk628/rk628_hdmirx.h @@ -474,6 +474,7 @@ struct rk628_hdcp { struct hdcp_keys *keys; struct rk628 *rk628; int enable; + bool hdcp_start; }; struct rk628_hdmirx_cec { From 47e0b52d12ed4ef39ee7c4f72a7ef307abe2c66c Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Wed, 17 Apr 2024 16:29:15 +0800 Subject: [PATCH 7/9] media: i2c: rk628: extended hpd pull down time Signed-off-by: Chen Shunqing Change-Id: I6a1d531f9c37ad4d7873bd86f2d5dc1f6e66e75f --- drivers/media/i2c/rk628/rk628_bt1120_v4l2.c | 10 ++++++++-- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 7e56090e6883..17714a133ab1 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -90,6 +90,7 @@ struct rk628_bt1120 { u32 stream_state; int hdmirx_irq; int plugin_irq; + int lock_fail_time; bool nosignal; bool rxphy_pwron; bool enable_hdcp; @@ -337,13 +338,14 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) static void rk628_hdmirx_config_all(struct v4l2_subdev *sd) { - int ret; + int ret, delay; struct rk628_bt1120 *bt1120 = to_bt1120(sd); ret = rk628_hdmirx_phy_setup(sd); if (ret >= 0 && !rk628_hdmirx_scdc_ced_err(bt1120->rk628)) { ret = rk628_bt1120_format_change(sd); if (!ret) { + bt1120->lock_fail_time = 0; bt1120->nosignal = false; return; } @@ -351,8 +353,12 @@ static void rk628_hdmirx_config_all(struct v4l2_subdev *sd) if (ret < 0 || rk628_hdmirx_scdc_ced_err(bt1120->rk628)) { rk628_hdmirx_plugout(sd); + bt1120->lock_fail_time++; + v4l2_dbg(1, debug, sd, "%s: lock fail time: %d\n", + __func__, bt1120->lock_fail_time); + delay = 800 + 800 * ((bt1120->lock_fail_time + 1) % 2); schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, - msecs_to_jiffies(800)); + msecs_to_jiffies(delay)); } } diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index da5834a1f048..c9bfec4738e0 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -114,6 +114,7 @@ struct rk628_csi { u32 stream_state; int hdmirx_irq; int plugin_irq; + int lock_fail_time; bool nosignal; bool rxphy_pwron; bool txphy_pwron; @@ -479,13 +480,14 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) static void rk628_hdmirx_config_all(struct v4l2_subdev *sd) { - int ret; + int ret, delay; struct rk628_csi *csi = to_csi(sd); ret = rk628_hdmirx_phy_setup(sd); if (ret >= 0 && !rk628_hdmirx_scdc_ced_err(csi->rk628)) { ret = rk628_csi_format_change(sd); if (!ret) { + csi->lock_fail_time = 0; csi->nosignal = false; return; } @@ -493,8 +495,12 @@ static void rk628_hdmirx_config_all(struct v4l2_subdev *sd) if (ret < 0 || rk628_hdmirx_scdc_ced_err(csi->rk628)) { rk628_hdmirx_plugout(sd); + csi->lock_fail_time++; + v4l2_dbg(1, debug, sd, "%s: lock fail time: %d\n", + __func__, csi->lock_fail_time); + delay = 800 + 800 * ((csi->lock_fail_time + 1) % 2); schedule_delayed_work(&csi->delayed_work_enable_hotplug, - msecs_to_jiffies(800)); + msecs_to_jiffies(delay)); } } From 0ca707d0053efcab34b690b0ed616b1f4d4b2f13 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 24 Jan 2022 20:35:32 +0800 Subject: [PATCH 8/9] usb: gadget: f_hid: fix zero length packet transfer If the hid transfer with size divisible to EPs max packet size, it needs to set the req->zero to true, then the usb controller can transfer a zero length packet at the end according to the USB 2.0 spec. Signed-off-by: William Wu Change-Id: Ia63060b4551d30821beaf494c1ccd7dfb3b6ca22 --- drivers/usb/gadget/function/f_hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 6be6009f911e..35987d4619fe 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -489,7 +489,7 @@ try_again: } req->status = 0; - req->zero = 0; + req->zero = ((count % hidg->in_ep->maxpacket) == 0); req->length = count; req->complete = f_hidg_req_complete; req->context = hidg; From 0bf324da22d947baab4a05d33107fe5f0b3f9f65 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 29 Apr 2024 11:22:24 +0800 Subject: [PATCH 9/9] usb: gadget: f_hid: fix zero length packet transfer for ep0 If the hid transfer with size divisible to EP0 max packet size, it needs to set the req->zero to true, then the usb controller can transfer a zero length packet at the end according to the USB 2.0 spec. Signed-off-by: William Wu Change-Id: Iae8c06966efe49c3a33213f9c36dd752633e8bd1 --- drivers/usb/gadget/function/f_hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 35987d4619fe..034ea7fb8b9c 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -760,7 +760,7 @@ stall: return -EOPNOTSUPP; respond: - req->zero = 0; + req->zero = ((length % cdev->gadget->ep0->maxpacket) == 0); req->length = length; status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); if (status < 0)