From 170875f34dede7a7c1989c70e5d51f0e57a42eed Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 14 May 2024 14:05:09 +0800 Subject: [PATCH 1/3] media: i2c: rk628: fix mutex_lock when get_fmt if nosignal Fixes: 7f0bc0de39ed ("media: i2c: rk628: add nosignal process when get_fmt and enable stream") Change-Id: I94b55ca0bdd9dd17168f28d25590c66e9f1dd923 Signed-off-by: Jianwei Fan --- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 729b813a3658..6e626eda25f5 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -1729,10 +1729,9 @@ static int rk628_hdmirx_general_isr(struct v4l2_subdev *sd, u32 status, bool *ha __func__, hact, vact); rk628_csi_enable_interrupts(sd, false); - if (csi->rk628->version < RK628F_VERSION) { + if (csi->rk628->version < RK628F_VERSION) enable_stream(sd, false); - csi->nosignal = true; - } + csi->nosignal = true; v4l2_event_queue(sd->devnode, &evt_signal_lost); schedule_delayed_work(&csi->delayed_work_res_change, msecs_to_jiffies(100)); @@ -2066,15 +2065,15 @@ static int rk628_csi_get_fmt(struct v4l2_subdev *sd, { struct rk628_csi *csi = to_csi(sd); - /* The application don't wants this to be blocked, so use mutex_trylock() */ - if (!mutex_trylock(&csi->confctl_mutex)) { + if (!tx_5v_power_present(sd) || csi->nosignal) { + v4l2_info(sd, "%s hdmirx no signal\n", __func__); format->format.code = csi->mbus_fmt_code; format->format.width = RK628_DEFAULT_WIDTH; format->format.height = RK628_DEFAULT_HEIGHT; format->format.field = V4L2_FIELD_NONE; return 0; } - + mutex_lock(&csi->confctl_mutex); format->format.code = csi->mbus_fmt_code; format->format.width = ALIGN_DOWN(csi->timings.bt.width, 8); format->format.height = csi->timings.bt.height; @@ -2943,6 +2942,7 @@ static irqreturn_t plugin_detect_irq(int irq, void *dev_id) rk628_csi_enable_csi_interrupts(sd, false); rk628_csi_disable_stream(sd); } + csi->nosignal = true; /* control hpd after 50ms */ schedule_delayed_work(&csi->delayed_work_enable_hotplug, HZ / 20); v4l2_event_queue(sd->devnode, &evt_signal_lost); From 63172c061d7b5ec885d84c0d89ad177b839d6971 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Mon, 20 May 2024 10:28:09 +0800 Subject: [PATCH 2/3] phy: rockchip: csi2-dphy: fixes dphy open/close stuck issue for rk3576 This fixes system stuck when open/close dphy connected sensor. Unable to handle kernel access to user memory outside uaccess routines at virtual address 000000010000035c Call trace: rockchip_csi2_dphy_detach_hw+0x368/0x598 csi2_dphy_s_stream+0x184/0x6a0 csi2_s_stream+0x1e4/0x6c8 rkcif_pipeline_set_stream+0x1e4/0x780 rkcif_do_stop_stream+0x390/0x1260 rkcif_stop_streaming+0x18/0x24 __vb2_queue_cancel+0x38/0x260 vb2_core_streamoff+0x28/0xac vb2_ioctl_streamoff+0x5c/0x8c v4l_streamoff+0x24/0x30 __video_do_ioctl+0x2d8/0x3f0 video_usercopy+0x418/0x9ac video_ioctl2+0x18/0x24 v4l2_ioctl+0x4c/0x5c __arm64_sys_ioctl+0x90/0xc8 invoke_syscall+0x40/0x104 el0_svc_common+0xbc/0x168 do_el0_svc+0x1c/0x28 el0_svc+0x1c/0x68 el0t_64_sync_handler+0x68/0xb4 el0t_64_sync+0x164/0x168 Signed-off-by: Wang Panzhenzhuan Change-Id: I568c8790df3ea23b767b71cf414439583853d4b0 --- drivers/phy/rockchip/phy-rockchip-csi2-dphy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index 143f08b3fdbe..489afe88abd2 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -294,6 +294,7 @@ static int rockchip_csi2_dphy_attach_hw(struct csi2_dphy *dphy, int csi_idx, int else dphy->phy_index = 5; } + dphy_hw->dphy_dev[dphy_hw->dphy_dev_num] = dphy; dphy_hw->dphy_dev_num++; dphy->dphy_hw = dphy_hw; dphy->phy_hw[index] = (void *)dphy_hw; From fc87ca81ee14b8313e90c0264b9703cb680d685a Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 13 May 2024 14:44:10 +0800 Subject: [PATCH 3/3] drm/rockchip: dw-dp: use low link rate for low pixel clock timing When DPTX controller config 2 pixe mode and work in sst mode, and a low pixel clock image transmit in high link rate(HBR3), some monitor may display flicker. To avoid this issue appear, use lower link rate(HBR2) when transmit a low pixel clock image. Change-Id: I75ac8fcb963631cb372dd76c4b45ca33e960f6c9 Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/dw-dp.c | 49 ++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 706b4433b0f4..e455b8c34ac4 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -313,6 +313,7 @@ struct drm_dp_link_train { struct dw_dp_link { u8 dpcd[DP_RECEIVER_CAP_SIZE]; unsigned char revision; + unsigned int max_rate; unsigned int rate; unsigned int lanes; struct drm_dp_link_caps caps; @@ -1573,6 +1574,7 @@ static void dw_dp_link_reset(struct dw_dp_link *link) link->rate = 0; link->lanes = 0; + link->max_rate = 0; } static int dw_dp_link_power_up(struct dw_dp *dp) @@ -1668,10 +1670,11 @@ static int dw_dp_link_probe(struct dw_dp *dp) !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED); link->revision = link->dpcd[DP_DPCD_REV]; - link->rate = min_t(u32, min(dp->max_link_rate, dp->phy->attrs.max_link_rate * 100), - drm_dp_max_link_rate(link->dpcd)); + link->max_rate = min_t(u32, min(dp->max_link_rate, dp->phy->attrs.max_link_rate * 100), + drm_dp_max_link_rate(link->dpcd)); link->lanes = min_t(u8, phy_get_bus_width(dp->phy), - drm_dp_max_lane_count(link->dpcd)); + drm_dp_max_lane_count(link->dpcd)); + link->rate = link->max_rate; link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd); link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd); @@ -3135,7 +3138,7 @@ dw_dp_bridge_mode_valid(struct drm_bridge *bridge, drm_mode_is_420_only(info, &m)) return MODE_NO_420; - if (!dw_dp_bandwidth_ok(dp, &m, min_bpp, link->lanes, link->rate)) + if (!dw_dp_bandwidth_ok(dp, &m, min_bpp, link->lanes, link->max_rate)) return MODE_CLOCK_HIGH; return MODE_OK; @@ -3171,17 +3174,21 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on) switch (FIELD_GET(PHY_RATE, value)) { case 3: link->rate = 810000; + link->max_rate = 810000; break; case 2: link->rate = 540000; + link->max_rate = 540000; break; case 1: link->rate = 270000; + link->max_rate = 270000; break; case 0: fallthrough; default: link->rate = 162000; + link->max_rate = 162000; break; } @@ -3418,7 +3425,7 @@ dw_dp_mst_connector_mode_valid(struct drm_connector *connector, struct drm_displ if (drm_connector_is_unregistered(connector)) return MODE_ERROR; - if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, dp->link.lanes, dp->link.rate)) + if (!dw_dp_bandwidth_ok(dp, mode, min_bpp, dp->link.lanes, dp->link.max_rate)) return MODE_CLOCK_HIGH; if (drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) @@ -3561,6 +3568,32 @@ static void dw_dp_enable_vop_gate(struct dw_dp *dp, struct drm_crtc *crtc, rockchip_drm_crtc_output_pre_disable(crtc, output_if); } +/* + * When DPTX controller config 2 pixe mode and work in sst mode, + * and a low pixel clock image transmit in high link rate(HBR3), + * some monitor may display flicker. To avoid this issue appear, use + * lower link rate(HBR2) when transmit a low pixel clock image. + */ +static void dw_dp_limit_max_link_rate(struct dw_dp *dp) +{ + struct dw_dp_link *link = &dp->link; + struct dw_dp_video *video = &dp->video; + + link->rate = link->max_rate; + + if (dp->is_mst) + return; + + if (dp->pixel_mode != DPTX_MP_DUAL_PIXEL) + return; + + if (video->mode.clock > 50000) + return; + + if (link->max_rate > 540000) + link->rate = 540000; +} + static void dw_dp_mst_encoder_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { @@ -3597,6 +3630,8 @@ static void dw_dp_mst_encoder_atomic_enable(struct drm_encoder *encoder, mst_enc->mst_conn = mst_conn; if (first_mst_stream) { + dw_dp_limit_max_link_rate(dp); + ret = phy_power_on(dp->phy); if (ret) dev_err(dp->dev, "phy power on failed: %d\n", ret); @@ -4155,6 +4190,8 @@ static int dw_dp_link_enable(struct dw_dp *dp) { int ret; + dw_dp_limit_max_link_rate(dp); + ret = phy_power_on(dp->phy); if (ret) return ret; @@ -4412,7 +4449,7 @@ static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, fmt->color_format != DRM_COLOR_FORMAT_YCBCR420) continue; - if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->rate)) + if (!dw_dp_bandwidth_ok(dp, &mode, fmt->bpp, link->lanes, link->max_rate)) continue; if (dp_state->bpc != 0) {