drm/rockchip: MIPI fixes & improvements
Subsystems (4)
v2 cover drm/rockchip: MIPI fixes & improvements
This is a re-roll of a series originally posted back in September [1]. It's mostly unchanged but in response to Chris and Mark's feedback I have dropped the first two patches and replaces them with the new patches 3 and 4; it's a slightly different approach from Mark's suggestion because it turns out that we only use the mode in the enable function and it is safe to read from the connector state there.
[1] https://www.spinics.net/lists/arm-kernel/msg532931.html
John Keeping (26):
drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for
MIPI
drm/rockchip: dw-mipi-dsi: rename commit hook to enable drm/rockchip: dw-mipi-dsi: pass mode in where needed drm/rockchip: dw-mipi-dsi: remove mode_set hook drm/rockchip: dw-mipi-dsi: fix command header writes drm/rockchip: dw-mipi-dsi: fix generic packet status check drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf drm/rockchip: dw-mipi-dsi: include bad value in error message drm/rockchip: dw-mipi-dsi: respect message flags drm/rockchip: dw-mipi-dsi: only request HS clock when required drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned drm/rockchip: dw-mipi-dsi: prepare panel after phy init drm/rockchip: dw-mipi-dsi: allow commands in panel_disable drm/rockchip: dw-mipi-dsi: fix escape clock rate drm/rockchip: dw-mipi-dsi: ensure PHY is reset drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured drm/rockchip: dw-mipi-dsi: properly configure PHY timing drm/rockchip: dw-mipi-dsi: improve PLL configuration drm/rockchip: dw-mipi-dsi: use specific poll helper drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC drm/rockchip: vop: test for P{H,V}SYNC
drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded drm/rockchip: dw-mipi-dsi: support non-burst modes drm/rockchip: dw-mipi-dsi: add reset control
drm/rockchip: dw-mipi-dsi: support read commands
drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 341 +++++++++++++++++++--------- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 +- 2 files changed, 239 insertions(+), 106 deletions(-)
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 1/26 drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for MIPI
With atomic modesetting the hardware will be powered off when the mode_set function is called. We should configure the hardware in the commit function (or even the enable function, but switching from commit to enable is left for a future patch).
---
v2:
- also move dw_mipi_dsi_get_lane_bps into the commit function
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 45 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 26 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +19 -26
@@ -819,34 +819,8 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -int ret; dsi->mode = adjusted_mode; - - ret =dw_mipi_dsi_get_lane_bps (dsi); -if (ret <0 ) -return ; - -if (clk_prepare_enable (dsi->pclk)) { -dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__); -return ; - } - -dw_mipi_dsi_init (dsi); -dw_mipi_dsi_dpi_config (dsi, mode); -dw_mipi_dsi_packet_handler_config (dsi); -dw_mipi_dsi_video_mode_config (dsi); -dw_mipi_dsi_video_packet_config (dsi, mode); -dw_mipi_dsi_command_mode_config (dsi); -dw_mipi_dsi_line_timer_config (dsi); -dw_mipi_dsi_vertical_timing_config (dsi); -dw_mipi_dsi_dphy_timing_config (dsi); -dw_mipi_dsi_dphy_interface_config (dsi); -dw_mipi_dsi_clear_err (dsi); -if (drm_panel_prepare (dsi->panel)) -dev_err (dsi->dev,"failed to prepare panel\n" ); - -clk_disable_unprepare (dsi->pclk); }static void dw_mipi_dsi_encoder_disable (struct drm_encoder *encoder)
@@ -880,12 +854,31 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder);int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val; +int ret; + + ret =dw_mipi_dsi_get_lane_bps (dsi); +if (ret <0 ) +return ;if (clk_prepare_enable (dsi->pclk)) {dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__);return ; } +dw_mipi_dsi_init (dsi); +dw_mipi_dsi_dpi_config (dsi, dsi->mode); +dw_mipi_dsi_packet_handler_config (dsi); +dw_mipi_dsi_video_mode_config (dsi); +dw_mipi_dsi_video_packet_config (dsi, dsi->mode); +dw_mipi_dsi_command_mode_config (dsi); +dw_mipi_dsi_line_timer_config (dsi); +dw_mipi_dsi_vertical_timing_config (dsi); +dw_mipi_dsi_dphy_timing_config (dsi); +dw_mipi_dsi_dphy_interface_config (dsi); +dw_mipi_dsi_clear_err (dsi); +if (drm_panel_prepare (dsi->panel)) +dev_err (dsi->dev,"failed to prepare panel\n" ); +dw_mipi_dsi_phy_init (dsi);dw_mipi_dsi_wait_for_two_frames (dsi);
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 01/26] drm/rockchip: dw-mipi-dsi: don't configure hardware in mode_set for MIPI
Hi John
Quoted 4 lines · John Keeping
With atomic modesetting the hardware will be powered off when the
mode_setfunction is called. We should configure the hardware in the commit function (or even the enable function, but switching from commit to enable is left for a future patch).
I tend to merge the 2 patches into one.
Quoted 80 lines
Signed-off-by John Keeping <[email protected]>---
v2:
- also movedw_mipi_dsi_get_lane_bpsinto the commit function--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 45 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 26 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +19
-26@@ -819,34 +819,8 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -int ret; dsi->mode = adjusted_mode; - - ret =dw_mipi_dsi_get_lane_bps (dsi); -if (ret <0 ) -return ; - -if (clk_prepare_enable (dsi->pclk)) { -dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__); -return ; - } - -dw_mipi_dsi_init (dsi); -dw_mipi_dsi_dpi_config (dsi, mode); -dw_mipi_dsi_packet_handler_config (dsi); -dw_mipi_dsi_video_mode_config (dsi); -dw_mipi_dsi_video_packet_config (dsi, mode); -dw_mipi_dsi_command_mode_config (dsi); -dw_mipi_dsi_line_timer_config (dsi); -dw_mipi_dsi_vertical_timing_config (dsi); -dw_mipi_dsi_dphy_timing_config (dsi); -dw_mipi_dsi_dphy_interface_config (dsi); -dw_mipi_dsi_clear_err (dsi); -if (drm_panel_prepare (dsi->panel)) -dev_err (dsi->dev,"failed to prepare panel\n" ); - -clk_disable_unprepare (dsi->pclk); }static void dw_mipi_dsi_encoder_disable (struct drm_encoder *encoder)@@ -880,12 +854,31 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder)struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder);int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val; +int ret; + + ret =dw_mipi_dsi_get_lane_bps (dsi); +if (ret <0 ) +return ;if (clk_prepare_enable (dsi->pclk)) {dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__);return ; } +dw_mipi_dsi_init (dsi); +dw_mipi_dsi_dpi_config (dsi, dsi->mode); +dw_mipi_dsi_packet_handler_config (dsi); +dw_mipi_dsi_video_mode_config (dsi); +dw_mipi_dsi_video_packet_config (dsi, dsi->mode); +dw_mipi_dsi_command_mode_config (dsi); +dw_mipi_dsi_line_timer_config (dsi); +dw_mipi_dsi_vertical_timing_config (dsi); +dw_mipi_dsi_dphy_timing_config (dsi); +dw_mipi_dsi_dphy_interface_config (dsi); +dw_mipi_dsi_clear_err (dsi); +if (drm_panel_prepare (dsi->panel)) +dev_err (dsi->dev,"failed to prepare panel\n" ); +dw_mipi_dsi_phy_init (dsi);dw_mipi_dsi_wait_for_two_frames (dsi);
PATCH v2 2/26 drm/rockchip: dw-mipi-dsi: rename commit hook to enable
In reply to John KeepingRockchip DRM is fully atomic and commit is deprecated for atomic drivers. No changed are needed beyond renaming the function.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2 -2
@@ -849,7 +849,7 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)clk_disable_unprepare (dsi->pclk); } -static void dw_mipi_dsi_encoder_commit (struct drm_encoder *encoder) +static void dw_mipi_dsi_encoder_enable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder);int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);
@@ -926,7 +926,7 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,static struct drm_encoder_helper_funcs dw_mipi_dsi_encoder_helper_funcs = { - .commit = dw_mipi_dsi_encoder_commit, + .enable = dw_mipi_dsi_encoder_enable, .mode_set = dw_mipi_dsi_encoder_mode_set, .disable = dw_mipi_dsi_encoder_disable, .atomic_check = dw_mipi_dsi_encoder_atomic_check,
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 3/26 drm/rockchip: dw-mipi-dsi: pass mode in where needed
In reply to John KeepingThis shows that we only use the mode from the enable function and prepares us to remove the "mode" field and the mode_set hook in the next commit.
---
New in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +22 -19
@@ -330,11 +330,11 @@ static int max_mbps_to_testdin(unsigned int max_mbps)* The controller should generate 2 frames before * preparing the peripheral. */ -static void dw_mipi_dsi_wait_for_two_frames (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_wait_for_two_frames (struct drm_display_mode *mode) {int refresh, two_frames; - refresh =drm_mode_vrefresh (dsi->mode); + refresh =drm_mode_vrefresh (mode); two_frames =DIV_ROUND_UP (MSEC_PER_SEC , refresh) *2 ;msleep (two_frames); }
@@ -459,7 +459,8 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)return ret; } -static int dw_mipi_dsi_get_lane_bps (struct dw_mipi_dsi *dsi) +static int dw_mipi_dsi_get_lane_bps (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {unsigned int i, pre;unsigned long mpclk, pllref, tmp;
@@ -474,7 +475,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)return bpp; } - mpclk =DIV_ROUND_UP (dsi->mode->clock,MSEC_PER_SEC ); + mpclk =DIV_ROUND_UP (mode->clock,MSEC_PER_SEC );if (mpclk) {/* take 1 / 0.9, since mbps must big than bandwidth of RGB */ tmp = mpclk * (bpp / dsi->lanes) *10 /9 ;
@@ -742,43 +743,44 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)/* Get lane byte clock cycles. */ static u32 dw_mipi_dsi_get_hcomponent_lbcc (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode,u32 hcomponent) {u32 frac, lbcc; lbcc = hcomponent * dsi->lane_mbps *MSEC_PER_SEC /8 ; - frac = lbcc % dsi->mode->clock; - lbcc = lbcc / dsi->mode->clock; + frac = lbcc % mode->clock; + lbcc = lbcc / mode->clock;if (frac) lbcc++;return lbcc; } -static void dw_mipi_dsi_line_timer_config (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_line_timer_config (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {u32 htotal, hsa, hbp, lbcc; -struct drm_display_mode *mode = dsi->mode; htotal = mode->htotal; hsa = mode->hsync_end - mode->hsync_start; hbp = mode->htotal - mode->hsync_end; - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, htotal); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, htotal);dsi_write (dsi,DSI_VID_HLINE_TIME , lbcc); - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, hsa); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, hsa);dsi_write (dsi,DSI_VID_HSA_TIME , lbcc); - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, hbp); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, hbp);dsi_write (dsi,DSI_VID_HBP_TIME , lbcc); } -static void dw_mipi_dsi_vertical_timing_config (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_vertical_timing_config (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {u32 vactive, vsa, vfp, vbp; -struct drm_display_mode *mode = dsi->mode; vactive = mode->vdisplay; vsa = mode->vsync_end - mode->vsync_start;
@@ -852,11 +854,12 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)static void dw_mipi_dsi_encoder_enable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); +struct drm_display_mode *mode = dsi->mode;int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val;int ret; - ret =dw_mipi_dsi_get_lane_bps (dsi); + ret =dw_mipi_dsi_get_lane_bps (dsi, mode);if (ret <0 )return ;
@@ -866,13 +869,13 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) }dw_mipi_dsi_init (dsi); -dw_mipi_dsi_dpi_config (dsi, dsi->mode); +dw_mipi_dsi_dpi_config (dsi, mode);dw_mipi_dsi_packet_handler_config (dsi);dw_mipi_dsi_video_mode_config (dsi); -dw_mipi_dsi_video_packet_config (dsi, dsi->mode); +dw_mipi_dsi_video_packet_config (dsi, mode);dw_mipi_dsi_command_mode_config (dsi); -dw_mipi_dsi_line_timer_config (dsi); -dw_mipi_dsi_vertical_timing_config (dsi); +dw_mipi_dsi_line_timer_config (dsi, mode); +dw_mipi_dsi_vertical_timing_config (dsi, mode);dw_mipi_dsi_dphy_timing_config (dsi);dw_mipi_dsi_dphy_interface_config (dsi);dw_mipi_dsi_clear_err (dsi);
@@ -880,7 +883,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)dev_err (dsi->dev,"failed to prepare panel\n" );dw_mipi_dsi_phy_init (dsi); -dw_mipi_dsi_wait_for_two_frames (dsi); +dw_mipi_dsi_wait_for_two_frames (mode);dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE );drm_panel_enable (dsi->panel);
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 03/26] drm/rockchip: dw-mipi-dsi: pass mode in where needed
Hi John
Quoted 143 lines · John Keeping
This shows that we only use the mode from the enable function and prepares us to remove the "mode" field and the
mode_sethook in the next commit.Signed-off-by John Keeping <[email protected]>---
New in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +22
-19@@ -330,11 +330,11 @@ static int max_mbps_to_testdin(unsigned int max_mbps)* The controller should generate 2 frames before * preparing the peripheral. */ -static void dw_mipi_dsi_wait_for_two_frames (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_wait_for_two_frames (struct drm_display_mode *mode) {int refresh, two_frames; - refresh =drm_mode_vrefresh (dsi->mode); + refresh =drm_mode_vrefresh (mode); two_frames =DIV_ROUND_UP (MSEC_PER_SEC , refresh) *2 ;msleep (two_frames); }@@ -459,7 +459,8 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)return ret; } -static int dw_mipi_dsi_get_lane_bps (struct dw_mipi_dsi *dsi) +static int dw_mipi_dsi_get_lane_bps (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {unsigned int i, pre;unsigned long mpclk, pllref, tmp;@@ -474,7 +475,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi)return bpp; } - mpclk =DIV_ROUND_UP (dsi->mode->clock,MSEC_PER_SEC ); + mpclk =DIV_ROUND_UP (mode->clock,MSEC_PER_SEC );if (mpclk) {/* take 1 / 0.9, since mbps must big than bandwidth of RGB */ tmp = mpclk * (bpp / dsi->lanes) *10 /9 ;@@ -742,43 +743,44 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)/* Get lane byte clock cycles. */ static u32 dw_mipi_dsi_get_hcomponent_lbcc (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode,u32 hcomponent) {u32 frac, lbcc; lbcc = hcomponent * dsi->lane_mbps *MSEC_PER_SEC /8 ; - frac = lbcc % dsi->mode->clock; - lbcc = lbcc / dsi->mode->clock; + frac = lbcc % mode->clock; + lbcc = lbcc / mode->clock;if (frac) lbcc++;return lbcc; } -static void dw_mipi_dsi_line_timer_config (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_line_timer_config (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {u32 htotal, hsa, hbp, lbcc; -struct drm_display_mode *mode = dsi->mode; htotal = mode->htotal; hsa = mode->hsync_end - mode->hsync_start; hbp = mode->htotal - mode->hsync_end; - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, htotal); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, htotal);dsi_write (dsi,DSI_VID_HLINE_TIME , lbcc); - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, hsa); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, hsa);dsi_write (dsi,DSI_VID_HSA_TIME , lbcc); - lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, hbp); + lbcc =dw_mipi_dsi_get_hcomponent_lbcc (dsi, mode, hbp);dsi_write (dsi,DSI_VID_HBP_TIME , lbcc); } -static void dw_mipi_dsi_vertical_timing_config (struct dw_mipi_dsi *dsi) +static void dw_mipi_dsi_vertical_timing_config (struct dw_mipi_dsi *dsi, +struct drm_display_mode *mode) {u32 vactive, vsa, vfp, vbp; -struct drm_display_mode *mode = dsi->mode; vactive = mode->vdisplay; vsa = mode->vsync_end - mode->vsync_start;@@ -852,11 +854,12 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)static void dw_mipi_dsi_encoder_enable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); +struct drm_display_mode *mode = dsi->mode;int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val;int ret; - ret =dw_mipi_dsi_get_lane_bps (dsi); + ret =dw_mipi_dsi_get_lane_bps (dsi, mode);if (ret <0 )return ;@@ -866,13 +869,13 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) }dw_mipi_dsi_init (dsi); -dw_mipi_dsi_dpi_config (dsi, dsi->mode); +dw_mipi_dsi_dpi_config (dsi, mode);dw_mipi_dsi_packet_handler_config (dsi);dw_mipi_dsi_video_mode_config (dsi); -dw_mipi_dsi_video_packet_config (dsi, dsi->mode); +dw_mipi_dsi_video_packet_config (dsi, mode);dw_mipi_dsi_command_mode_config (dsi); -dw_mipi_dsi_line_timer_config (dsi); -dw_mipi_dsi_vertical_timing_config (dsi); +dw_mipi_dsi_line_timer_config (dsi, mode); +dw_mipi_dsi_vertical_timing_config (dsi, mode);dw_mipi_dsi_dphy_timing_config (dsi);dw_mipi_dsi_dphy_interface_config (dsi);dw_mipi_dsi_clear_err (dsi);@@ -880,7 +883,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)dev_err (dsi->dev,"failed to prepare panel\n" );dw_mipi_dsi_phy_init (dsi); -dw_mipi_dsi_wait_for_two_frames (dsi); +dw_mipi_dsi_wait_for_two_frames (mode);dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE );drm_panel_enable (dsi->panel);
PATCH v2 4/26 drm/rockchip: dw-mipi-dsi: remove mode_set hook
In reply to John KeepingThis is not needed since we can access the mode via the CRTC from the enable hook. Also remove the "mode" field that is no longer used.
---
New in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1 -12
@@ -286,7 +286,6 @@ struct dw_mipi_dsi {u32 format;u16 input_div;u16 feedback_div; -struct drm_display_mode *mode;const struct dw_mipi_dsi_plat_data *pdata; };
@@ -816,15 +815,6 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)dsi_write (dsi,DSI_INT_MSK1 ,0 ); } -static void dw_mipi_dsi_encoder_mode_set (struct drm_encoder *encoder, -struct drm_display_mode *mode, -struct drm_display_mode *adjusted_mode) -{ -struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); - - dsi->mode = adjusted_mode; -} -static void dw_mipi_dsi_encoder_disable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder);
@@ -854,7 +844,7 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)static void dw_mipi_dsi_encoder_enable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -struct drm_display_mode *mode = dsi->mode; +struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val;int ret;
@@ -930,7 +920,6 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,static struct drm_encoder_helper_funcs dw_mipi_dsi_encoder_helper_funcs = { .enable = dw_mipi_dsi_encoder_enable, - .mode_set = dw_mipi_dsi_encoder_mode_set, .disable = dw_mipi_dsi_encoder_disable, .atomic_check = dw_mipi_dsi_encoder_atomic_check, };
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 04/26] drm/rockchip: dw-mipi-dsi: remove mode_set hook
Hi John
Quoted 55 lines · John Keeping
This is not needed since we can access the mode via the CRTC from the enable hook. Also remove the "mode" field that is no longer used.
Signed-off-by John Keeping <[email protected]>---
New in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-12@@ -286,7 +286,6 @@ struct dw_mipi_dsi {u32 format;u16 input_div;u16 feedback_div; -struct drm_display_mode *mode;const struct dw_mipi_dsi_plat_data *pdata; };@@ -816,15 +815,6 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)dsi_write (dsi,DSI_INT_MSK1 ,0 ); } -static void dw_mipi_dsi_encoder_mode_set (struct drm_encoder *encoder, -struct drm_display_mode *mode, -struct drm_display_mode *adjusted_mode) -{ -struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); - - dsi->mode = adjusted_mode; -} -static void dw_mipi_dsi_encoder_disable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder);@@ -854,7 +844,7 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)static void dw_mipi_dsi_encoder_enable (struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -struct drm_display_mode *mode = dsi->mode; +struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;int mux =drm_of_encoder_active_endpoint_id (dsi->dev->of_node, encoder);u32 val;int ret;@@ -930,7 +920,6 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,static struct drm_encoder_helper_funcs dw_mipi_dsi_encoder_helper_funcs = { .enable = dw_mipi_dsi_encoder_enable, - .mode_set = dw_mipi_dsi_encoder_mode_set, .disable = dw_mipi_dsi_encoder_disable, .atomic_check = dw_mipi_dsi_encoder_atomic_check, };
PATCH v2 5/26 drm/rockchip: dw-mipi-dsi: fix command header writes
In reply to John KeepingIn a couple of places here we use "val" for the value that is about to be written to a register but then reuse the same variable for the value of a status register before we get around to writing it. Rename the value to be written to so that we write the value we intend to and not what we have just read from the status register.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +6 -4
@@ -542,9 +542,10 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,return 0 ; } -static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 val) +static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 hdr_val) {int ret; +u32 val; ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS, val, !(val & GEN_CMD_FULL), 1000,
@@ -554,7 +555,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 val)return ret; } -dsi_write (dsi,DSI_GEN_HDR , val); +dsi_write (dsi,DSI_GEN_HDR , hdr_val); ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS, val, val & (GEN_CMD_EMPTY | GEN_PLD_W_EMPTY),
@@ -587,8 +588,9 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, {const u32 *tx_buf = msg->tx_buf;int len = msg->tx_len, pld_data_bytes =sizeof (*tx_buf), ret; -u32 val =GEN_HDATA (msg->tx_len) |GEN_HTYPE (msg->type); +u32 hdr_val =GEN_HDATA (msg->tx_len) |GEN_HTYPE (msg->type);u32 remainder =0 ; +u32 val;if (msg->tx_len <3 ) { dev_err(dsi->dev, "wrong tx buf length %zu for long write\n",
@@ -617,7 +619,7 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, } } -return dw_mipi_dsi_gen_pkt_hdr_write (dsi, val); +return dw_mipi_dsi_gen_pkt_hdr_write (dsi, hdr_val); } static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 6/26 drm/rockchip: dw-mipi-dsi: fix generic packet status check
In reply to John KeepingWe want to check that both the GEN_CMD_EMPTY and GEN_PLD_W_EMPTY bits are set so we can't just check "val & mask" because that will be true if either bit is set.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +3 -2
@@ -545,7 +545,7 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 hdr_val) {int ret; -u32 val; +u32 val, mask; ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS, val, !(val & GEN_CMD_FULL), 1000,
@@ -557,8 +557,9 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)dsi_write (dsi,DSI_GEN_HDR , hdr_val); + mask =GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ; ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , - val, val & (GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ), + val, (val & mask) == mask,1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {dev_err (dsi->dev,"failed to write command FIFO\n" );
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 06/26] drm/rockchip: dw-mipi-dsi: fix generic packet status check
Hi John
Quoted 3 lines · John Keeping
We want to check that both the
GEN_CMD_EMPTYandGEN_PLD_W_EMPTYbits are set so we can't just check "val & mask" because that will be true if either bit is set.
According to DW mipi dsi controller databook, you are right. we should check both the 2 BIT.gen_pld_w_empty:
This bit indicates the empty status of the generic write payload FIFO. Dependency : DSI_GENERIC = 1. Otherwise, this bit is reserved. Value after reset : 0x1
Quoted 31 lines
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +3
-2@@ -545,7 +545,7 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 hdr_val) {int ret; -u32 val; +u32 val, mask; ret = readx_poll_timeout(readl, dsi->base + DSI_CMD_PKT_STATUS, val, !(val & GEN_CMD_FULL), 1000,@@ -557,8 +557,9 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)dsi_write (dsi,DSI_GEN_HDR , hdr_val); + mask =GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ; ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , - val, val & (GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ), + val, (val & mask) == mask,1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {dev_err (dsi->dev,"failed to write command FIFO\n" );
PATCH v2 7/26 drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
In reply to John KeepingAs a side-effect of this, encode the endianness explicitly rather than casting a u16.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +7 -2
@@ -572,8 +572,13 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)static int dw_mipi_dsi_dcs_short_write (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { -const u16 *tx_buf = msg->tx_buf; -u32 val =GEN_HDATA (*tx_buf) |GEN_HTYPE (msg->type); +const u8 *tx_buf = msg->tx_buf; +u32 val =GEN_HTYPE (msg->type); + +if (msg->tx_len >0 ) + val |=GEN_HDATA (tx_buf[0 ]); +if (msg->tx_len >1 ) + val |=GEN_HDATA (tx_buf[1 ] <<8 );if (msg->tx_len >2 ) { dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 07/26] drm/rockchip: dw-mipi-dsi: avoid out-of-bounds read on tx_buf
Hi John
Quoted 30 lines · John Keeping
As a side-effect of this, encode the endianness explicitly rather than casting a u16.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +7
-2@@ -572,8 +572,13 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)static int dw_mipi_dsi_dcs_short_write (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { -const u16 *tx_buf = msg->tx_buf; -u32 val =GEN_HDATA (*tx_buf) |GEN_HTYPE (msg->type); +const u8 *tx_buf = msg->tx_buf; +u32 val =GEN_HTYPE (msg->type); + +if (msg->tx_len >0 ) + val |=GEN_HDATA (tx_buf[0 ]); +if (msg->tx_len >1 ) + val |=GEN_HDATA (tx_buf[1 ] <<8 );if (msg->tx_len >2 ) { dev_err(dsi->dev, "too long tx buf length %zu for short write\n",
PATCH v2 8/26 drm/rockchip: dw-mipi-dsi: include bad value in error message
In reply to John KeepingAs an aid to debugging.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2 -1
@@ -644,7 +644,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, ret =dw_mipi_dsi_dcs_long_write (dsi, msg);break ;default : -dev_err (dsi->dev,"unsupported message type\n" ); +dev_err (dsi->dev,"unsupported message type 0x%02x\n" , + msg->type); ret = -EINVAL ; }
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 08/26] drm/rockchip: dw-mipi-dsi: include bad value in error message
Hi John
Quoted 23 lines · John Keeping
As an aid to debugging.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2
-1@@ -644,7 +644,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, ret =dw_mipi_dsi_dcs_long_write (dsi, msg);break ;default : -dev_err (dsi->dev,"unsupported message type\n" ); +dev_err (dsi->dev,"unsupported message type 0x%02x\n" , + msg->type); ret = -EINVAL ; }
PATCH v2 9/26 drm/rockchip: dw-mipi-dsi: respect message flags
In reply to John KeepingInstead of always sending commands in LP mode, respect the MIPI_DSI_MSG_USE_LPM flag to decide how to send each message. Also request acks if MIPI_DSI_MSG_REQ_ACK is set.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +15 -1
@@ -542,6 +542,19 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,return 0 ; } +static void dw_mipi_message_config (struct dw_mipi_dsi *dsi, +const struct mipi_dsi_msg *msg) +{ +u32 val =0 ; + +if (msg->flags &MIPI_DSI_MSG_REQ_ACK ) + val |=EN_ACK_RQST ; +if (msg->flags &MIPI_DSI_MSG_USE_LPM ) + val |=CMD_MODE_ALL_LP ; + +dsi_write (dsi,DSI_CMD_MODE_CFG , val); +} +static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 hdr_val) {int ret;
@@ -634,6 +647,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,struct dw_mipi_dsi *dsi =host_to_dsi (host);int ret; +dw_mipi_message_config (dsi, msg); +switch (msg->type) {case MIPI_DSI_DCS_SHORT_WRITE :case MIPI_DSI_DCS_SHORT_WRITE_PARAM :
@@ -745,7 +760,6 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) {dsi_write (dsi,DSI_TO_CNT_CFG ,HSTX_TO_CNT (1000 ) |LPRX_TO_CNT (1000 ));dsi_write (dsi,DSI_BTA_TO_CNT ,0xd00 ); -dsi_write (dsi,DSI_CMD_MODE_CFG ,CMD_MODE_ALL_LP );dsi_write (dsi,DSI_MODE_CFG ,ENABLE_CMD_MODE ); }
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 09/26] drm/rockchip: dw-mipi-dsi: respect message flags
Hi John
Quoted 52 lines · John Keeping
Instead of always sending commands in LP mode, respect the
MIPI_DSI_MSG_USE_LPMflag to decide how to send each message. Also request acks ifMIPI_DSI_MSG_REQ_ACKis set.Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +15
-1@@ -542,6 +542,19 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,return 0 ; } +static void dw_mipi_message_config (struct dw_mipi_dsi *dsi, +const struct mipi_dsi_msg *msg) +{ +u32 val =0 ; + +if (msg->flags &MIPI_DSI_MSG_REQ_ACK ) + val |=EN_ACK_RQST ; +if (msg->flags &MIPI_DSI_MSG_USE_LPM ) + val |=CMD_MODE_ALL_LP ; + +dsi_write (dsi,DSI_CMD_MODE_CFG , val); +} +static int dw_mipi_dsi_gen_pkt_hdr_write (struct dw_mipi_dsi *dsi,u32 hdr_val) {int ret;@@ -634,6 +647,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,struct dw_mipi_dsi *dsi =host_to_dsi (host);int ret; +dw_mipi_message_config (dsi, msg); +switch (msg->type) {case MIPI_DSI_DCS_SHORT_WRITE :case MIPI_DSI_DCS_SHORT_WRITE_PARAM :@@ -745,7 +760,6 @@ static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) {dsi_write (dsi,DSI_TO_CNT_CFG ,HSTX_TO_CNT (1000 ) |LPRX_TO_CNT (1000 ));dsi_write (dsi,DSI_BTA_TO_CNT ,0xd00 ); -dsi_write (dsi,DSI_CMD_MODE_CFG ,CMD_MODE_ALL_LP );dsi_write (dsi,DSI_MODE_CFG ,ENABLE_CMD_MODE ); }
PATCH v2 10/26 drm/rockchip: dw-mipi-dsi: only request HS clock when required
In reply to John KeepingRequesting the HS clock from the PHY before we initialize it causes an invalid signal to be sent out since the input clock is not yet configured. The PHY databook suggests only asserting this signal when performing HS transfers, so let's do that.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4 -2
@@ -545,13 +545,15 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,static void dw_mipi_message_config (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { +bool lpm = msg->flags &MIPI_DSI_MSG_USE_LPM ;u32 val =0 ;if (msg->flags &MIPI_DSI_MSG_REQ_ACK ) val |=EN_ACK_RQST ; -if (msg->flags &MIPI_DSI_MSG_USE_LPM ) +if (lpm) val |=CMD_MODE_ALL_LP ; +dsi_write (dsi,DSI_LPCLK_CTRL , lpm ?0 :PHY_TXREQUESTCLKHS );dsi_write (dsi,DSI_CMD_MODE_CFG , val); }
@@ -693,6 +695,7 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,dsi_write (dsi,DSI_PWR_UP ,RESET );dsi_write (dsi,DSI_MODE_CFG ,ENABLE_VIDEO_MODE );dw_mipi_dsi_video_mode_config (dsi); +dsi_write (dsi,DSI_LPCLK_CTRL ,PHY_TXREQUESTCLKHS );dsi_write (dsi,DSI_PWR_UP ,POWERUP ); } }
@@ -710,7 +713,6 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) | PHY_RSTZ | PHY_SHUTDOWNZ);dsi_write (dsi,DSI_CLKMGR_CFG ,TO_CLK_DIVIDSION (10 ) |TX_ESC_CLK_DIVIDSION (7 )); -dsi_write (dsi,DSI_LPCLK_CTRL ,PHY_TXREQUESTCLKHS ); } static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 10/26] drm/rockchip: dw-mipi-dsi: only request HS clock when required
Hi John
Quoted 49 lines · John Keeping
Requesting the HS clock from the PHY before we initialize it causes an invalid signal to be sent out since the input clock is not yet configured. The PHY databook suggests only asserting this signal when performing HS transfers, so let's do that.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4
-2@@ -545,13 +545,15 @@ static int dw_mipi_dsi_host_detach(struct mipi_dsi_host *host,static void dw_mipi_message_config (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { +bool lpm = msg->flags &MIPI_DSI_MSG_USE_LPM ;u32 val =0 ;if (msg->flags &MIPI_DSI_MSG_REQ_ACK ) val |=EN_ACK_RQST ; -if (msg->flags &MIPI_DSI_MSG_USE_LPM ) +if (lpm) val |=CMD_MODE_ALL_LP ; +dsi_write (dsi,DSI_LPCLK_CTRL , lpm ?0 :PHY_TXREQUESTCLKHS );dsi_write (dsi,DSI_CMD_MODE_CFG , val); }@@ -693,6 +695,7 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,dsi_write (dsi,DSI_PWR_UP ,RESET );dsi_write (dsi,DSI_MODE_CFG ,ENABLE_VIDEO_MODE );dw_mipi_dsi_video_mode_config (dsi); +dsi_write (dsi,DSI_LPCLK_CTRL ,PHY_TXREQUESTCLKHS );dsi_write (dsi,DSI_PWR_UP ,POWERUP ); } }@@ -710,7 +713,6 @@ static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) | PHY_RSTZ | PHY_SHUTDOWNZ);dsi_write (dsi,DSI_CLKMGR_CFG ,TO_CLK_DIVIDSION (10 ) |TX_ESC_CLK_DIVIDSION (7 )); -dsi_write (dsi,DSI_LPCLK_CTRL ,PHY_TXREQUESTCLKHS ); } static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
PATCH v2 11/26 drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
In reply to John KeepingBy dereferencing the MIPI command buffer as a u32* we rely on it being correctly aligned on ARM, but this may not be the case. Copy it into a stack variable that will be correctly aligned.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +7 -5
@@ -607,10 +607,10 @@ static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi,static int dw_mipi_dsi_dcs_long_write (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { -const u32 *tx_buf = msg->tx_buf; -int len = msg->tx_len, pld_data_bytes =sizeof (*tx_buf), ret; +const u8 *tx_buf = msg->tx_buf; +int len = msg->tx_len, pld_data_bytes =sizeof (u32), ret;u32 hdr_val =GEN_HDATA (msg->tx_len) |GEN_HTYPE (msg->type); -u32 remainder =0 ; +u32 remainder;u32 val;if (msg->tx_len <3 ) {
@@ -621,12 +621,14 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,while (DIV_ROUND_UP (len, pld_data_bytes)) {if (len < pld_data_bytes) { + remainder =0 ;memcpy (&remainder, tx_buf, len);dsi_write (dsi,DSI_GEN_PLD_DATA , remainder); len =0 ; }else { -dsi_write (dsi,DSI_GEN_PLD_DATA , *tx_buf); - tx_buf++; +memcpy (&remainder, tx_buf, pld_data_bytes); +dsi_write (dsi,DSI_GEN_PLD_DATA , remainder); + tx_buf += pld_data_bytes; len -= pld_data_bytes; }
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 11/26] drm/rockchip: dw-mipi-dsi: don't assume buffer is aligned
Hi John
Quoted 46 lines · John Keeping
By dereferencing the MIPI command buffer as a u32* we rely on it being correctly aligned on ARM, but this may not be the case. Copy it into a stack variable that will be correctly aligned.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +7
-5@@ -607,10 +607,10 @@ static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi,static int dw_mipi_dsi_dcs_long_write (struct dw_mipi_dsi *dsi,const struct mipi_dsi_msg *msg) { -const u32 *tx_buf = msg->tx_buf; -int len = msg->tx_len, pld_data_bytes =sizeof (*tx_buf), ret; +const u8 *tx_buf = msg->tx_buf; +int len = msg->tx_len, pld_data_bytes =sizeof (u32), ret;u32 hdr_val =GEN_HDATA (msg->tx_len) |GEN_HTYPE (msg->type); -u32 remainder =0 ; +u32 remainder;u32 val;if (msg->tx_len <3 ) {@@ -621,12 +621,14 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,while (DIV_ROUND_UP (len, pld_data_bytes)) {if (len < pld_data_bytes) { + remainder =0 ;memcpy (&remainder, tx_buf, len);dsi_write (dsi,DSI_GEN_PLD_DATA , remainder); len =0 ; }else { -dsi_write (dsi,DSI_GEN_PLD_DATA , *tx_buf); - tx_buf++; +memcpy (&remainder, tx_buf, pld_data_bytes); +dsi_write (dsi,DSI_GEN_PLD_DATA , remainder); + tx_buf += pld_data_bytes; len -= pld_data_bytes; }
PATCH v2 12/26 drm/rockchip: dw-mipi-dsi: prepare panel after phy init
In reply to John KeepingSome panels need to be configured with commands sent over the MIPI link, which they will do in the prepare hook. Call this after the PHY has been initialized so that we are able to send commands to the panel.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4 -2
@@ -896,12 +896,14 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)dw_mipi_dsi_dphy_timing_config (dsi);dw_mipi_dsi_dphy_interface_config (dsi);dw_mipi_dsi_clear_err (dsi); -if (drm_panel_prepare (dsi->panel)) -dev_err (dsi->dev,"failed to prepare panel\n" );dw_mipi_dsi_phy_init (dsi);dw_mipi_dsi_wait_for_two_frames (mode); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE ); +if (drm_panel_prepare (dsi->panel)) +dev_err (dsi->dev,"failed to prepare panel\n" ); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE );drm_panel_enable (dsi->panel);
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 12/26] drm/rockchip: dw-mipi-dsi: prepare panel after phy init
Hi John
Quoted 32 lines · John Keeping
Some panels need to be configured with commands sent over the MIPI link, which they will do in the prepare hook. Call this after the PHY has been initialized so that we are able to send commands to the panel.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4
-2@@ -896,12 +896,14 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)dw_mipi_dsi_dphy_timing_config (dsi);dw_mipi_dsi_dphy_interface_config (dsi);dw_mipi_dsi_clear_err (dsi); -if (drm_panel_prepare (dsi->panel)) -dev_err (dsi->dev,"failed to prepare panel\n" );dw_mipi_dsi_phy_init (dsi);dw_mipi_dsi_wait_for_two_frames (mode); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE ); +if (drm_panel_prepare (dsi->panel)) +dev_err (dsi->dev,"failed to prepare panel\n" ); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE );drm_panel_enable (dsi->panel);
PATCH v2 13/26 drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
In reply to John KeepingPanel drivers may want to sent commands during the disable function, for example MIPI_DCS_SET_DISPLAY_OFF before the video signal ends. In order to send commands we need to write to registers, so pclk must be enabled.
While changing this, remove the unnecessary code after the panel unprepare call which seems to be a workaround for a specific panel and thus belongs in the panel driver.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2 -10
@@ -846,24 +846,16 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -drm_panel_disable (dsi->panel); -if (clk_prepare_enable (dsi->pclk)) {dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__);return ; } +drm_panel_disable (dsi->panel); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE );drm_panel_unprepare (dsi->panel); -dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE ); -/* -* This is necessary to make sure the peripheral will be driven -* normally when the display is enabled again later. -*/ -msleep (120 ); - -dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE );dw_mipi_dsi_disable (dsi);clk_disable_unprepare (dsi->pclk); }
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 13/26] drm/rockchip: dw-mipi-dsi: allow commands in panel_disable
Hi John
Quoted 33 lines · John Keeping
Panel drivers may want to sent commands during the disable function, for example
MIPI_DCS_SET_DISPLAY_OFFbefore the video signal ends. In order to send commands we need to write to registers, so pclk must be enabled.While changing this, remove the unnecessary code after the panel unprepare call which seems to be a workaround for a specific panel and thus belongs in the panel driver.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2
-2@@ -846,24 +846,16 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) {struct dw_mipi_dsi *dsi =encoder_to_dsi (encoder); -drm_panel_disable (dsi->panel); -if (clk_prepare_enable (dsi->pclk)) {dev_err (dsi->dev,"%s: Failed to enable pclk\n" , __func__);return ; } +drm_panel_disable (dsi->panel); +dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE );
drivers/gpu/drm/rockchip/dw-mipi-dsi.c static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) · line 866
Quoted 10 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +0
-8drm_panel_unprepare (dsi->panel); -dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_VID_MODE ); -/* -* This is necessary to make sure the peripheral will be driven -* normally when the display is enabled again later. -*/ -msleep (120 ); - -dw_mipi_dsi_set_mode (dsi,DW_MIPI_DSI_CMD_MODE );
This workaround is from[0], I also think it should be deleted.
[0]
http://www.spinics.net/lists/dri-devel/msg77192.html
Quoted 3 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +0
-0dw_mipi_dsi_disable (dsi);clk_disable_unprepare (dsi->pclk); }
PATCH v2 14/26 drm/rockchip: dw-mipi-dsi: fix escape clock rate
In reply to John KeepingUse the same calculation as the vendor kernel to derive the escape clock speed.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +3 -1
@@ -710,11 +710,13 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)static void dw_mipi_dsi_init (struct dw_mipi_dsi *dsi) { +u32 esc_clk_division = (dsi->lane_mbps >>3 ) /20 +1 ; +dsi_write (dsi,DSI_PWR_UP ,RESET );dsi_write (dsi,DSI_PHY_RSTZ ,PHY_DISFORCEPLL |PHY_DISABLECLK |PHY_RSTZ |PHY_SHUTDOWNZ );dsi_write (dsi,DSI_CLKMGR_CFG ,TO_CLK_DIVIDSION (10 ) | -TX_ESC_CLK_DIVIDSION (7 )); +TX_ESC_CLK_DIVIDSION (esc_clk_division)); } static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 14/26] drm/rockchip: dw-mipi-dsi: fix escape clock rate
Quoted 29 lines · John Keeping
Use the same calculation as the vendor kernel to derive the escape clock speed.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +3
-1@@ -710,11 +710,13 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)static void dw_mipi_dsi_init (struct dw_mipi_dsi *dsi) { +u32 esc_clk_division = (dsi->lane_mbps >>3 ) /20 +1 ; +dsi_write (dsi,DSI_PWR_UP ,RESET );dsi_write (dsi,DSI_PHY_RSTZ ,PHY_DISFORCEPLL |PHY_DISABLECLK |PHY_RSTZ |PHY_SHUTDOWNZ );dsi_write (dsi,DSI_CLKMGR_CFG ,TO_CLK_DIVIDSION (10 ) | -TX_ESC_CLK_DIVIDSION (7 )); +TX_ESC_CLK_DIVIDSION (esc_clk_division)); } static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,
PATCH v2 15/26 drm/rockchip: dw-mipi-dsi: ensure PHY is reset
In reply to John KeepingAlso don't power up the DSI host at this point since this is not necessary in order to configure the PHY and we do so later when selecting video or command mode.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4 -1
@@ -397,7 +397,10 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)return testdin; } -dsi_write (dsi,DSI_PWR_UP ,POWERUP ); +/* Start by clearing PHY state */ +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_UNTESTCLR ); +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_TESTCLR ); +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_UNTESTCLR ); dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE | VCO_RANGE_CON_SEL(vco) |
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 15/26] drm/rockchip: dw-mipi-dsi: ensure PHY is reset
Quoted 27 lines · John Keeping
Also don't power up the DSI host at this point since this is not necessary in order to configure the PHY and we do so later when selecting video or command mode.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +4
-1@@ -397,7 +397,10 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)return testdin; } -dsi_write (dsi,DSI_PWR_UP ,POWERUP ); +/* Start by clearing PHY state */ +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_UNTESTCLR ); +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_TESTCLR ); +dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_UNTESTCLR ); dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE | VCO_RANGE_CON_SEL(vco) |
PATCH v2 16/26 drm/rockchip: dw-mipi-dsi: configure bias and bandgap before enable
In reply to John KeepingWe should configure these functions before enabling them.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +5 -4
@@ -420,6 +420,11 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)dw_mipi_dsi_phy_write (dsi,0x18 ,LOOP_DIV_HIGH_SEL (dsi->feedback_div) |HIGH_PROGRAM_EN ); +dw_mipi_dsi_phy_write (dsi,0x22 ,LOW_PROGRAM_EN | +BIASEXTR_SEL (BIASEXTR_127_7 )); +dw_mipi_dsi_phy_write (dsi,0x22 ,HIGH_PROGRAM_EN | +BANDGAP_SEL (BANDGAP_96_10 )); +dw_mipi_dsi_phy_write (dsi,0x20 ,POWER_CONTROL |INTERNAL_REG_CURRENT |BIAS_BLOCK_ON |BANDGAP_ON );
@@ -429,10 +434,6 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)SETRD_MAX |POWER_MANAGE | TER_RESISTORS_ON); -dw_mipi_dsi_phy_write (dsi,0x22 ,LOW_PROGRAM_EN | -BIASEXTR_SEL (BIASEXTR_127_7 )); -dw_mipi_dsi_phy_write (dsi,0x22 ,HIGH_PROGRAM_EN | -BANDGAP_SEL (BANDGAP_96_10 ));dw_mipi_dsi_phy_write (dsi,0x70 ,TLP_PROGRAM_EN |0xf );dw_mipi_dsi_phy_write (dsi,0x71 ,THS_PRE_PROGRAM_EN |0x55 );
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 17/26 drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
In reply to John Keeping---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1 -1
@@ -413,12 +413,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)dw_mipi_dsi_phy_write (dsi,0x44 ,HSFREQRANGE_SEL (testdin)); -dw_mipi_dsi_phy_write (dsi,0x19 ,PLL_LOOP_DIV_EN |PLL_INPUT_DIV_EN );dw_mipi_dsi_phy_write (dsi,0x17 ,INPUT_DIVIDER (dsi->input_div));dw_mipi_dsi_phy_write (dsi,0x18 ,LOOP_DIV_LOW_SEL (dsi->feedback_div) |LOW_PROGRAM_EN );dw_mipi_dsi_phy_write (dsi,0x18 ,LOOP_DIV_HIGH_SEL (dsi->feedback_div) |HIGH_PROGRAM_EN ); +dw_mipi_dsi_phy_write (dsi,0x19 ,PLL_LOOP_DIV_EN |PLL_INPUT_DIV_EN );dw_mipi_dsi_phy_write (dsi,0x22 ,LOW_PROGRAM_EN |BIASEXTR_SEL (BIASEXTR_127_7 ));
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 17/26] drm/rockchip: dw-mipi-dsi: don't enable PHY PLL until it's configured
Hi John
This patch do the similar thing with
https://patchwork.kernel.org/patch/9530405/
They are changing the phy configuration order, my suggestion is to merge them.
Quoted 25 lines · John Keeping
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-1@@ -413,12 +413,12 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)dw_mipi_dsi_phy_write (dsi,0x44 ,HSFREQRANGE_SEL (testdin)); -dw_mipi_dsi_phy_write (dsi,0x19 ,PLL_LOOP_DIV_EN |PLL_INPUT_DIV_EN );dw_mipi_dsi_phy_write (dsi,0x17 ,INPUT_DIVIDER (dsi->input_div));dw_mipi_dsi_phy_write (dsi,0x18 ,LOOP_DIV_LOW_SEL (dsi->feedback_div) |LOW_PROGRAM_EN );dw_mipi_dsi_phy_write (dsi,0x18 ,LOOP_DIV_HIGH_SEL (dsi->feedback_div) |HIGH_PROGRAM_EN ); +dw_mipi_dsi_phy_write (dsi,0x19 ,PLL_LOOP_DIV_EN |PLL_INPUT_DIV_EN );dw_mipi_dsi_phy_write (dsi,0x22 ,LOW_PROGRAM_EN |BIASEXTR_SEL (BIASEXTR_127_7 ));
PATCH v2 18/26 drm/rockchip: dw-mipi-dsi: properly configure PHY timing
In reply to John KeepingThese values are specified as constant time periods but the PHY configuration is in terms of the current lane byte clock so using constant values guarantees that the timings will be outside the specification with some display configurations.
Derive the necessary configuration from the byte clock in order to ensure that the PHY configuration is correct.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 36 ++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +32 -4
@@ -383,6 +383,26 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_TESTCLK |PHY_UNTESTCLR ); } +/** +* ns2bc - Nanoseconds to byte clock cycles +*/ +static inline unsigned int ns2bc (struct dw_mipi_dsi *dsi,int ns) +{ +unsigned long byte_clk_khz = dsi->lane_mbps *MSEC_PER_SEC /8 ; + +return (ns * (byte_clk_khz /1000 ) +999 ) /1000 ; +} + +/** +* ns2ui - Nanoseconds to UI time periods +*/ +static inline unsigned int ns2ui (struct dw_mipi_dsi *dsi,int ns) +{ +unsigned long byte_clk_khz = dsi->lane_mbps *MSEC_PER_SEC ; + +return (ns * (byte_clk_khz /1000 ) +999 ) /1000 ; +} +static int dw_mipi_dsi_phy_init (struct dw_mipi_dsi *dsi) {int ret, testdin, vco, val;
@@ -434,10 +454,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)SETRD_MAX |POWER_MANAGE | TER_RESISTORS_ON); - -dw_mipi_dsi_phy_write (dsi,0x70 ,TLP_PROGRAM_EN |0xf ); -dw_mipi_dsi_phy_write (dsi,0x71 ,THS_PRE_PROGRAM_EN |0x55 ); -dw_mipi_dsi_phy_write (dsi,0x72 ,THS_ZERO_PROGRAM_EN |0xa ); +dw_mipi_dsi_phy_write (dsi,0x60 ,TLP_PROGRAM_EN |ns2bc (dsi,500 )); +dw_mipi_dsi_phy_write (dsi,0x61 ,THS_PRE_PROGRAM_EN |ns2ui (dsi,40 )); +dw_mipi_dsi_phy_write (dsi,0x62 ,THS_ZERO_PROGRAM_EN |ns2bc (dsi,300 )); +dw_mipi_dsi_phy_write (dsi,0x63 ,THS_PRE_PROGRAM_EN |ns2ui (dsi,100 )); +dw_mipi_dsi_phy_write (dsi,0x64 ,BIT (5 ) |ns2bc (dsi,100 )); +dw_mipi_dsi_phy_write (dsi,0x65 ,BIT (5 ) | (ns2bc (dsi,60 ) +7 )); + +dw_mipi_dsi_phy_write (dsi,0x70 ,TLP_PROGRAM_EN |ns2bc (dsi,500 )); +dw_mipi_dsi_phy_write (dsi,0x71 ,THS_PRE_PROGRAM_EN | (ns2ui (dsi,50 ) +5 )); +dw_mipi_dsi_phy_write (dsi,0x72 ,THS_ZERO_PROGRAM_EN | (ns2bc (dsi,140 ) +2 )); +dw_mipi_dsi_phy_write (dsi,0x73 ,THS_PRE_PROGRAM_EN | (ns2ui (dsi,60 ) +8 )); +dw_mipi_dsi_phy_write (dsi,0x74 ,BIT (5 ) |ns2bc (dsi,100 ));dsi_write (dsi,DSI_PHY_RSTZ ,PHY_ENFORCEPLL |PHY_ENABLECLK |PHY_UNRSTZ |PHY_UNSHUTDOWNZ );
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 18/26] drm/rockchip: dw-mipi-dsi: properly configure PHY timing
Quoted 53 lines · John Keeping
These values are specified as constant time periods but the PHY configuration is in terms of the current lane byte clock so using constant values guarantees that the timings will be outside the specification with some display configurations.
Derive the necessary configuration from the byte clock in order to ensure that the PHY configuration is correct.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 36 ++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +20
-3@@ -383,6 +383,26 @@ static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi *dsi, u8 test_code,dsi_write (dsi,DSI_PHY_TST_CTRL0 ,PHY_TESTCLK |PHY_UNTESTCLR ); } +/** +* ns2bc - Nanoseconds to byte clock cycles +*/ +static inline unsigned int ns2bc (struct dw_mipi_dsi *dsi,int ns) +{ +unsigned long byte_clk_khz = dsi->lane_mbps *MSEC_PER_SEC /8 ; + +return (ns * (byte_clk_khz /1000 ) +999 ) /1000 ; +} + +/** +* ns2ui - Nanoseconds to UI time periods +*/ +static inline unsigned int ns2ui (struct dw_mipi_dsi *dsi,int ns) +{ +unsigned long byte_clk_khz = dsi->lane_mbps *MSEC_PER_SEC ; + +return (ns * (byte_clk_khz /1000 ) +999 ) /1000 ; +} +static int dw_mipi_dsi_phy_init (struct dw_mipi_dsi *dsi) {int ret, testdin, vco, val;@@ -434,10 +454,18 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi)SETRD_MAX |POWER_MANAGE | TER_RESISTORS_ON); - -dw_mipi_dsi_phy_write (dsi,0x70 ,TLP_PROGRAM_EN |0xf ); -dw_mipi_dsi_phy_write (dsi,0x71 ,THS_PRE_PROGRAM_EN |0x55 );
drivers/gpu/drm/rockchip/dw-mipi-dsi.c static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) · line 465
Quoted 10 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +9
-1-dw_mipi_dsi_phy_write (dsi,0x72 ,THS_ZERO_PROGRAM_EN |0xa ); +dw_mipi_dsi_phy_write (dsi,0x60 ,TLP_PROGRAM_EN |ns2bc (dsi,500 )); +dw_mipi_dsi_phy_write (dsi,0x61 ,THS_PRE_PROGRAM_EN |ns2ui (dsi,40 )); +dw_mipi_dsi_phy_write (dsi,0x62 ,THS_ZERO_PROGRAM_EN |ns2bc (dsi,300 )); +dw_mipi_dsi_phy_write (dsi,0x63 ,THS_PRE_PROGRAM_EN |ns2ui (dsi,100 )); +dw_mipi_dsi_phy_write (dsi,0x64 ,BIT (5 ) |ns2bc (dsi,100 )); +dw_mipi_dsi_phy_write (dsi,0x65 ,BIT (5 ) | (ns2bc (dsi,60 ) +7 )); + +dw_mipi_dsi_phy_write (dsi,0x70 ,TLP_PROGRAM_EN |ns2bc (dsi,500 )); +dw_mipi_dsi_phy_write (dsi,0x71 ,THS_PRE_PROGRAM_EN | (ns2ui (dsi,50 ) +5 ));
WARNING: line over 80 characters
drivers/gpu/drm/rockchip/dw-mipi-dsi.c static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) · line 466
Quoted 1 line
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-0+dw_mipi_dsi_phy_write (dsi,0x72 ,THS_ZERO_PROGRAM_EN | (ns2bc (dsi,140 ) +2 ));
WARNING: line over 80 characters
drivers/gpu/drm/rockchip/dw-mipi-dsi.c static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) · line 467
Quoted 1 line
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-0+dw_mipi_dsi_phy_write (dsi,0x73 ,THS_PRE_PROGRAM_EN | (ns2ui (dsi,60 ) +8 ));
WARNING: line over 80 characters
Quoted 4 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-0+dw_mipi_dsi_phy_write (dsi,0x74 ,BIT (5 ) |ns2bc (dsi,100 ));dsi_write (dsi,DSI_PHY_RSTZ ,PHY_ENFORCEPLL |PHY_ENABLECLK |PHY_UNRSTZ |PHY_UNSHUTDOWNZ );
PATCH v2 19/26 drm/rockchip: dw-mipi-dsi: improve PLL configuration
In reply to John KeepingThe multiplication ratio for the PLL is required to be even due to the use of a "by 2 pre-scaler". Currently we are likely to end up with an odd multiplier even though there is an equivalent set of parameters with an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz we end up with M = 27, N = 2 whereas the example in the PHY databook gives M = 54, N = 4 for this bit rate and reference clock.
By walking down through the available multiplier instead of up we are more likely to hit an even multiplier. With the above example we do now get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on the divisor, which are:
40MHz >= (pllref / N) >= 5MHz
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1 -1
@@ -519,7 +519,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, pllref =DIV_ROUND_UP (clk_get_rate (dsi->pllref_clk),USEC_PER_SEC ); tmp = pllref; -for (i =1 ; i <6 ; i++) { +for (i = pllref /5 ; i > (pllref /40 ); i--) { pre = pllref / i;if ((tmp > (target_mbps % pre)) && (target_mbps / pre <512 )) { tmp = target_mbps % pre;
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 19/26] drm/rockchip: dw-mipi-dsi: improve PLL configuration
Hi John
Quoted 9 lines · John Keeping
The multiplication ratio for the PLL is required to be even due to the use of a "by 2 pre-scaler". Currently we are likely to end up with an odd multiplier even though there is an equivalent set of parameters with an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz we end up with M = 27, N = 2 whereas the example in the PHY databook gives M = 54, N = 4 for this bit rate and reference clock.
Quoted 8 lines
By walking down through the available multiplier instead of up we are more likely to hit an even multiplier. With the above example we do now get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on the divisor, which are:
40MHz >= (pllref / N) >= 5MHz
This formula is limit for N, but we still can not guarantee to get an even M.
Do you think we should do a check for M.
such as:
if (m % 2)
continue;
...
for (i = pllref / 5; i > (pllref / 40); i--) {
pre = pllref / i;
if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) {
tmp = target_mbps % pre;
n = i;
m = target_mbps / pre;
if (m % 2)
continue;
}
if (tmp == 0)
break;
}if (m % 2)
m++;
dsi->lane_mbps = pllref / n * m;
dsi->input_div = n;
dsi->feedback_div = m;Quoted 21 lines
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-1@@ -519,7 +519,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, pllref =DIV_ROUND_UP (clk_get_rate (dsi->pllref_clk),USEC_PER_SEC ); tmp = pllref; -for (i =1 ; i <6 ; i++) { +for (i = pllref /5 ; i > (pllref /40 ); i--) { pre = pllref / i;if ((tmp > (target_mbps % pre)) && (target_mbps / pre <512 )) { tmp = target_mbps % pre;
Re: [PATCH v2 19/26] drm/rockchip: dw-mipi-dsi: improve PLL configuration
Hi Chris,
Quoted 39 lines · Chris Zhong
Quoted 9 lines · John Keeping
The multiplication ratio for the PLL is required to be even due to the use of a "by 2 pre-scaler". Currently we are likely to end up with an odd multiplier even though there is an equivalent set of parameters with an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz we end up with M = 27, N = 2 whereas the example in the PHY databook gives M = 54, N = 4 for this bit rate and reference clock.
Quoted 8 lines
By walking down through the available multiplier instead of up we are more likely to hit an even multiplier. With the above example we do now get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on the divisor, which are:
40MHz >= (pllref / N) >= 5MHzThis formula is limit for N, but we still can not guarantee to get an even M.
Do you think we should do a check for M.
such as:
if (m % 2)continue; ... for (i = pllref / 5; i > (pllref / 40); i--) { pre = pllref / i; if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) { tmp = target_mbps % pre; n = i; m = target_mbps / pre; if (m % 2) continue; } if (tmp == 0) break; }
Quoted 6 lines
if (m % 2)
m++; dsi->lane_mbps = pllref / n * m; dsi->input_div = n; dsi->feedback_div = m;
Yes, I agree that there should be a check for M, but I'm not sure if the version above is sufficient. The "m % 2" check inside the loop means that we don't break immediately when tmp=0 but then we are guaranteed to break next time without having modified n, m because now tmp=0 so "tmp > (target_mbps % pre)" is always false and we just hit the "if (tmp == 0) break" case next time.
Given that the descending loop already means that if we can hit "tmp" exactly we are more likely to do so with a bigger N and even M, I think it might be better to just fix M after the loop like:
if (m % 2) {
if (m < 256 && (n * 2) <= (pllref / 5)) {
n *= 2;
m *= 2;
} else {
m++;
}
}but I haven't thought about this too carefully.
For this series, I'd rather either keep this patch as it is or drop it in favour of a more comprehensive solution. I don't want to block the other fixes waiting for a perfect fix here and we can always improve this further with a follow-up patch.
Quoted 22 lines
Quoted 20 lines
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-1@@ -519,7 +519,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, pllref =DIV_ROUND_UP (clk_get_rate (dsi->pllref_clk),USEC_PER_SEC ); tmp = pllref; -for (i =1 ; i <6 ; i++) { +for (i = pllref /5 ; i > (pllref /40 ); i--) { pre = pllref / i;if ((tmp > (target_mbps % pre)) && (target_mbps / pre <512 )) { tmp = target_mbps % pre;
Re: [PATCH v2 19/26] drm/rockchip: dw-mipi-dsi: improve PLL configuration
Quoted 67 lines · John Keeping
Hi Chris,
Quoted 38 lines · Chris Zhong
Quoted 9 lines · John Keeping
The multiplication ratio for the PLL is required to be even due to the use of a "by 2 pre-scaler". Currently we are likely to end up with an odd multiplier even though there is an equivalent set of parameters with an even multiplier.
For example, using the 324MHz bit rate with a reference clock of 24MHz we end up with M = 27, N = 2 whereas the example in the PHY databook gives M = 54, N = 4 for this bit rate and reference clock.
Quoted 8 lines
By walking down through the available multiplier instead of up we are more likely to hit an even multiplier. With the above example we do now get M = 54, N = 4 as given by the databook.
While doing this, change the loop limits to encode the actual limits on the divisor, which are:
40MHz >= (pllref / N) >= 5MHzThis formula is limit for N, but we still can not guarantee to get an even M.
Do you think we should do a check for M.
such as:
if (m % 2)continue; ... for (i = pllref / 5; i > (pllref / 40); i--) { pre = pllref / i; if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) { tmp = target_mbps % pre; n = i; m = target_mbps / pre; if (m % 2) continue; } if (tmp == 0) break; }Quoted 6 lines
if (m % 2)
m++; dsi->lane_mbps = pllref / n * m; dsi->input_div = n; dsi->feedback_div = m;Yes, I agree that there should be a check for M, but I'm not sure if the version above is sufficient. The "m % 2" check inside the loop means that we don't break immediately when tmp=0 but then we are guaranteed to break next time without having modified n, m because now tmp=0 so "tmp > (
target_mbps% pre)" is always false and we just hit the "if (tmp == 0) break" case next time.Given that the descending loop already means that if we can hit "tmp" exactly we are more likely to do so with a bigger N and even M, I think it might be better to just fix M after the loop like:
if (m % 2) { if (m < 256 && (n * 2) <= (pllref / 5)) { n *= 2; m *= 2; } else { m++; } }
Quoted 6 lines
but I haven't thought about this too carefully.
For this series, I'd rather either keep this patch as it is or drop it in favour of a more comprehensive solution. I don't want to block the other fixes waiting for a perfect fix here and we can always improve this further with a follow-up patch.
Agree, We can improve the whole formula in the future.
Quoted 24 lines
Quoted 22 lines
Quoted 21 lines
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +1
-1@@ -519,7 +519,7 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, pllref =DIV_ROUND_UP (clk_get_rate (dsi->pllref_clk),USEC_PER_SEC ); tmp = pllref; -for (i =1 ; i <6 ; i++) { +for (i = pllref /5 ; i > (pllref /40 ); i--) { pre = pllref / i;if ((tmp > (target_mbps % pre)) && (target_mbps / pre <512 )) { tmp = target_mbps % pre;
PATCH v2 20/26 drm/rockchip: dw-mipi-dsi: use specific poll helper
In reply to John KeepingAs the documentation for readx_poll_timeout says, we want to use the specialized macro for readl rather than using the generic version directly.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +5 -5
@@ -471,14 +471,14 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) PHY_UNRSTZ | PHY_UNSHUTDOWNZ); - ret =readx_poll_timeout (readl, dsi->base +DSI_PHY_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_PHY_STATUS , val, val &LOCK ,1000 ,PHY_STATUS_TIMEOUT_US );if (ret <0 ) {dev_err (dsi->dev,"failed to wait for phy lock state\n" );return ret; } - ret =readx_poll_timeout (readl, dsi->base +DSI_PHY_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_PHY_STATUS , val, val &STOP_STATE_CLK_LANE ,1000 ,PHY_STATUS_TIMEOUT_US );if (ret <0 ) {
@@ -594,7 +594,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)int ret;u32 val, mask; - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, !(val &GEN_CMD_FULL ),1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {
@@ -605,7 +605,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)dsi_write (dsi,DSI_GEN_HDR , hdr_val); mask =GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ; - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, (val & mask) == mask,1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {
@@ -664,7 +664,7 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, len -= pld_data_bytes; } - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, !(val &GEN_PLD_W_FULL ),1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 20/26] drm/rockchip: dw-mipi-dsi: use specific poll helper
Quoted 59 lines · John Keeping
As the documentation for
readx_poll_timeoutsays, we want to use the specialized macro for readl rather than using the generic version directly.Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +5
-5@@ -471,14 +471,14 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) PHY_UNRSTZ | PHY_UNSHUTDOWNZ); - ret =readx_poll_timeout (readl, dsi->base +DSI_PHY_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_PHY_STATUS , val, val &LOCK ,1000 ,PHY_STATUS_TIMEOUT_US );if (ret <0 ) {dev_err (dsi->dev,"failed to wait for phy lock state\n" );return ret; } - ret =readx_poll_timeout (readl, dsi->base +DSI_PHY_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_PHY_STATUS , val, val &STOP_STATE_CLK_LANE ,1000 ,PHY_STATUS_TIMEOUT_US );if (ret <0 ) {@@ -594,7 +594,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)int ret;u32 val, mask; - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, !(val &GEN_CMD_FULL ),1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {@@ -605,7 +605,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)dsi_write (dsi,DSI_GEN_HDR , hdr_val); mask =GEN_CMD_EMPTY |GEN_PLD_W_EMPTY ; - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, (val & mask) == mask,1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {@@ -664,7 +664,7 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, len -= pld_data_bytes; } - ret =readx_poll_timeout (readl, dsi->base +DSI_CMD_PKT_STATUS , + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , val, !(val &GEN_PLD_W_FULL ),1000 ,CMD_PKT_STATUS_TIMEOUT_US );if (ret <0 ) {
PATCH v2 21/26 drm/rockchip: dw-mipi-dsi: use positive check for N{H,V}SYNC
In reply to John KeepingThis matches other drivers.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +2 -2
@@ -771,9 +771,9 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi,break ; } -if (!(mode->flags &DRM_MODE_FLAG_PVSYNC )) +if (mode->flags &DRM_MODE_FLAG_NVSYNC ) val |=VSYNC_ACTIVE_LOW ; -if (!(mode->flags &DRM_MODE_FLAG_PHSYNC )) +if (mode->flags &DRM_MODE_FLAG_NHSYNC ) val |=HSYNC_ACTIVE_LOW ;dsi_write (dsi,DSI_DPI_VCID ,DPI_VID (dsi->channel));
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 22/26 drm/rockchip: vop: test for P{H,V}SYNC
In reply to John KeepingWhen connected to the MIPI DSI output, we need to use N{H,V}SYNC for the internal connection but these flags are meaningless for DSI panels. Switch the test so that we do not set the P{H,V}SYNC bits unless the mode requires it.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/rockchip_drm_vop.c +2 -2
@@ -933,8 +933,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) } pin_pol =0x8 ; - pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_NHSYNC ) ?0 :1 ; - pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_NVSYNC ) ?0 : (1 <<1 ); + pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_PHSYNC ) ?1 :0 ; + pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_PVSYNC ) ? (1 <<1 ) :0 ;VOP_CTRL_SET (vop, pin_pol, pin_pol);switch (s->output_type) {
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 22/26] drm/rockchip: vop: test for P{H,V}SYNC
Quoted 17 lines · John Keeping
When connected to the MIPI DSI output, we need to use N{H,V}SYNC for the internal connection but these flags are meaningless for DSI panels. Switch the test so that we do not set the P{H,V}SYNC bits unless the mode requires it.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/gpu/drm/rockchip/rockchip_drm_vop.c +0
-0
drivers/gpu/drm/rockchip/rockchip_drm_vop.c static void vop_crtc_enable(struct drm_crtc *crtc) · line 937
Quoted 7 lines
drivers/gpu/drm/rockchip/rockchip_drm_vop.c +2
-2@@ -933,8 +933,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) } pin_pol =0x8 ; - pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_NHSYNC ) ?0 :1 ; - pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_NVSYNC ) ?0 : (1 <<1 ); + pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_PHSYNC ) ?1 :0 ; + pin_pol |= (adjusted_mode->flags &DRM_MODE_FLAG_PVSYNC ) ? (1 <<1 ) :0 ;
I'm confuse that why SYNC flags have N and P on drm, they are same meaning.
If no one configure display mode's flags, I don't know which one is correct, N or P? it's a problem. Does anyone can answer it?
For this patch, it may effect non-sync flags mode on other connector's behavior,
but seems mostly display mode has sync flags except mipi dsi connector, I think feed mipi's requirement would be better.
So it's no problem on my side.
Quoted 3 lines
drivers/gpu/drm/rockchip/rockchip_drm_vop.c +0
-0VOP_CTRL_SET (vop, pin_pol, pin_pol);switch (s->output_type) {
Signature · 1 line
Mark Yao
PATCH v2 23/26 drm/rockchip: dw-mipi-dsi: defer probe if panel is not loaded
In reply to John KeepingThis ensures that the output resolution is known before fbcon loads.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +9 -2
@@ -1173,10 +1173,17 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->dsi_host.ops = &dw_mipi_dsi_host_ops; dsi->dsi_host.dev = dev; -return mipi_dsi_host_register (&dsi->dsi_host); + ret =mipi_dsi_host_register (&dsi->dsi_host); +if (!ret && !dsi->panel) { +mipi_dsi_host_unregister (&dsi->dsi_host); +drm_encoder_cleanup (&dsi->encoder); +drm_connector_cleanup (&dsi->connector); + ret = -EPROBE_DEFER ; + } err_pllref: -clk_disable_unprepare (dsi->pllref_clk); +if (ret) +clk_disable_unprepare (dsi->pllref_clk);return ret; }
Signature · 1 line
2.11.0.197.gb556de5.dirty
PATCH v2 24/26 drm/rockchip: dw-mipi-dsi: support non-burst modes
In reply to John Keeping---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +9 -7
@@ -82,6 +82,7 @@#define FRAME_BTA_ACK BIT(14)#define ENABLE_LOW_POWER (0x3f << 8)#define ENABLE_LOW_POWER_MASK (0x3f << 8) +#define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1#define VID_MODE_TYPE_BURST_SYNC_PULSES 0x2#define VID_MODE_TYPE_MASK 0x3
@@ -286,6 +287,7 @@ struct dw_mipi_dsi {u32 format;u16 input_div;u16 feedback_div; +unsigned long mode_flags;const struct dw_mipi_dsi_plat_data *pdata; };
@@ -548,15 +550,10 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,return -EINVAL ; } -if (!(device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) || - !(device->mode_flags &MIPI_DSI_MODE_VIDEO_SYNC_PULSE )) { -dev_err (dsi->dev,"device mode is unsupported\n" ); -return -EINVAL ; - } - dsi->lanes = device->lanes; dsi->channel = device->channel; dsi->format = device->format; + dsi->mode_flags = device->mode_flags; dsi->panel =of_drm_find_panel (device->dev.of_node);if (dsi->panel)return drm_panel_attach (dsi->panel, &dsi->connector);
@@ -713,7 +710,12 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) {u32 val; - val =VID_MODE_TYPE_BURST_SYNC_PULSES |ENABLE_LOW_POWER ; + val =ENABLE_LOW_POWER ; + +if (dsi->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + val |=VID_MODE_TYPE_BURST_SYNC_PULSES ; +else if (!(dsi->mode_flags &MIPI_DSI_MODE_VIDEO_SYNC_PULSE )) + val |=VID_MODE_TYPE_NON_BURST_SYNC_EVENTS ;dsi_write (dsi,DSI_VID_MODE_CFG , val); }
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 24/26] drm/rockchip: dw-mipi-dsi: support non-burst modes
Quoted 58 lines · John Keeping
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +9
-7@@ -82,6 +82,7 @@#define FRAME_BTA_ACK BIT(14)#define ENABLE_LOW_POWER (0x3f << 8)#define ENABLE_LOW_POWER_MASK (0x3f << 8) +#define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1#define VID_MODE_TYPE_BURST_SYNC_PULSES 0x2#define VID_MODE_TYPE_MASK 0x3@@ -286,6 +287,7 @@ struct dw_mipi_dsi {u32 format;u16 input_div;u16 feedback_div; +unsigned long mode_flags;const struct dw_mipi_dsi_plat_data *pdata; };@@ -548,15 +550,10 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,return -EINVAL ; } -if (!(device->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) || - !(device->mode_flags &MIPI_DSI_MODE_VIDEO_SYNC_PULSE )) { -dev_err (dsi->dev,"device mode is unsupported\n" ); -return -EINVAL ; - } - dsi->lanes = device->lanes; dsi->channel = device->channel; dsi->format = device->format; + dsi->mode_flags = device->mode_flags; dsi->panel =of_drm_find_panel (device->dev.of_node);if (dsi->panel)return drm_panel_attach (dsi->panel, &dsi->connector);@@ -713,7 +710,12 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) {u32 val; - val =VID_MODE_TYPE_BURST_SYNC_PULSES |ENABLE_LOW_POWER ; + val =ENABLE_LOW_POWER ; + +if (dsi->mode_flags &MIPI_DSI_MODE_VIDEO_BURST ) + val |=VID_MODE_TYPE_BURST_SYNC_PULSES ; +else if (!(dsi->mode_flags &MIPI_DSI_MODE_VIDEO_SYNC_PULSE )) + val |=VID_MODE_TYPE_NON_BURST_SYNC_EVENTS ;dsi_write (dsi,DSI_VID_MODE_CFG , val); }
PATCH v2 25/26 drm/rockchip: dw-mipi-dsi: add reset control
In reply to John KeepingIn order to fully reset the state of the MIPI controller we must assert this reset.
This is slightly more complicated than it could be in order to maintain compatibility with device trees that do not specify the reset property.
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +30 -0
@@ -13,6 +13,7 @@#include <linux/module.h> #include <linux/of_device.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/mfd/syscon.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h>
@@ -1121,6 +1122,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,of_match_device (dw_mipi_dsi_dt_ids, dev);const struct dw_mipi_dsi_plat_data *pdata = of_id->data;struct platform_device *pdev =to_platform_device (dev); +struct reset_control *apb_rst;struct drm_device *drm = data;struct dw_mipi_dsi *dsi;struct resource *res;
@@ -1159,6 +1161,34 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,return ret; } +/* +* Note that the reset was not defined in the initial device tree, so +* we have to be prepared for it not being found. +*/ + apb_rst =devm_reset_control_get (dev,"apb" ); +if (IS_ERR (apb_rst)) { +if (PTR_ERR (apb_rst) == -ENODEV ) { + apb_rst =NULL ; + }else { +dev_err (dev,"Unable to get reset control: %d\n" , ret); +return PTR_ERR (apb_rst); + } + } + +if (apb_rst) { + ret =clk_prepare_enable (dsi->pclk); +if (ret) { +dev_err (dev,"%s: Failed to enable pclk\n" , __func__); +return ret; + } + +reset_control_assert (apb_rst); +usleep_range (10 ,20 ); +reset_control_deassert (apb_rst); + +clk_disable_unprepare (dsi->pclk); + } + ret =clk_prepare_enable (dsi->pllref_clk);if (ret) {dev_err (dev,"%s: Failed to enable pllref_clk\n" , __func__);
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 25/26] drm/rockchip: dw-mipi-dsi: add reset control
Quoted 68 lines · John Keeping
In order to fully reset the state of the MIPI controller we must assert this reset.
This is slightly more complicated than it could be in order to maintain compatibility with device trees that do not specify the reset property.
Signed-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +30
-0@@ -13,6 +13,7 @@#include <linux/module.h> #include <linux/of_device.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/mfd/syscon.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> @@ -1121,6 +1122,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,of_match_device (dw_mipi_dsi_dt_ids, dev);const struct dw_mipi_dsi_plat_data *pdata = of_id->data;struct platform_device *pdev =to_platform_device (dev); +struct reset_control *apb_rst;struct drm_device *drm = data;struct dw_mipi_dsi *dsi;struct resource *res;@@ -1159,6 +1161,34 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,return ret; } +/* +* Note that the reset was not defined in the initial device tree, so +* we have to be prepared for it not being found. +*/ + apb_rst =devm_reset_control_get (dev,"apb" ); +if (IS_ERR (apb_rst)) { +if (PTR_ERR (apb_rst) == -ENODEV ) { + apb_rst =NULL ; + }else { +dev_err (dev,"Unable to get reset control: %d\n" , ret); +return PTR_ERR (apb_rst); + } + } + +if (apb_rst) { + ret =clk_prepare_enable (dsi->pclk); +if (ret) { +dev_err (dev,"%s: Failed to enable pclk\n" , __func__); +return ret; + } + +reset_control_assert (apb_rst); +usleep_range (10 ,20 ); +reset_control_deassert (apb_rst); + +clk_disable_unprepare (dsi->pclk); + } + ret =clk_prepare_enable (dsi->pllref_clk);if (ret) {dev_err (dev,"%s: Failed to enable pllref_clk\n" , __func__);
PATCH v2 26/26 drm/rockchip: dw-mipi-dsi: support read commands
In reply to John KeepingI haven't found any method for getting the length of a response, so this just uses the requested rx_len
---
Unchanged in v2
--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +54 -0
@@ -675,6 +675,54 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,return dw_mipi_dsi_gen_pkt_hdr_write (dsi, hdr_val); } +static int dw_mipi_dsi_dcs_read (struct dw_mipi_dsi *dsi, +const struct mipi_dsi_msg *msg) +{ +const u8 *tx_buf = msg->tx_buf; +u8 *rx_buf = msg->rx_buf; +size_t i; +int ret, val; + +dsi_write (dsi,DSI_PCKHDL_CFG ,EN_CRC_RX |EN_ECC_RX |EN_BTA ); +dsi_write (dsi,DSI_GEN_HDR ,GEN_HDATA (tx_buf[0 ]) |GEN_HTYPE (msg->type)); + + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , + val, !(val &GEN_RD_CMD_BUSY ),1000 , +CMD_PKT_STATUS_TIMEOUT_US ); +if (ret <0 ) { +dev_err (dsi->dev,"failed to read command response\n" ); +return ret; + } + +for (i =0 ; i < msg->rx_len;) { +u32 pld =dsi_read (dsi,DSI_GEN_PLD_DATA ); +while (i < msg->rx_len) { + rx_buf[i] = pld &0xff ; + pld >>=8 ; + i++; + } + } + +return msg->rx_len; +} + +static int dw_mipi_dsi_set_max_return_packet_size (struct dw_mipi_dsi *dsi, +size_t len) +{ +u8 val[] = { len &0xff , (len >>8 ) &0xff }; +struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type =MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE , + .tx_buf = val, + .tx_len =2 , + }; + +if (len >0xffff ) +return -EINVAL ; + +return dw_mipi_dsi_dcs_short_write (dsi, &msg); +} +static ssize_t dw_mipi_dsi_host_transfer (struct mipi_dsi_host *host,const struct mipi_dsi_msg *msg) {
@@ -692,6 +740,12 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,case MIPI_DSI_DCS_LONG_WRITE : ret =dw_mipi_dsi_dcs_long_write (dsi, msg);break ; +case MIPI_DSI_DCS_READ : + ret =dw_mipi_dsi_set_max_return_packet_size (dsi, msg->rx_len); +if (ret <0 ) +return ret; + ret =dw_mipi_dsi_dcs_read (dsi, msg); +break ;default :dev_err (dsi->dev,"unsupported message type 0x%02x\n" , msg->type);
Signature · 1 line
2.11.0.197.gb556de5.dirty
Re: [PATCH v2 26/26] drm/rockchip: dw-mipi-dsi: support read commands
Hi John
Quoted 18 lines · John Keeping
I haven't found any method for getting the length of a response, so this just uses the requested
rx_lenSigned-off-by John Keeping <[email protected]>---
Unchanged in v2--- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)drivers/gpu/drm/rockchip/dw-mipi-dsi.c +0
-0@@ -675,6 +675,54 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,return dw_mipi_dsi_gen_pkt_hdr_write (dsi, hdr_val); }
drivers/gpu/drm/rockchip/dw-mipi-dsi.c static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, · line 687
Quoted 10 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +10
-0+static int dw_mipi_dsi_dcs_read (struct dw_mipi_dsi *dsi, +const struct mipi_dsi_msg *msg) +{ +const u8 *tx_buf = msg->tx_buf; +u8 *rx_buf = msg->rx_buf; +size_t i; +int ret, val; + +dsi_write (dsi,DSI_PCKHDL_CFG ,EN_CRC_RX |EN_ECC_RX |EN_BTA ); +dsi_write (dsi,DSI_GEN_HDR ,GEN_HDATA (tx_buf[0 ]) |GEN_HTYPE (msg->type));
WARNING: line over 80 characters
Quoted 54 lines
drivers/gpu/drm/rockchip/dw-mipi-dsi.c +44
-0+ + ret =readl_poll_timeout (dsi->base +DSI_CMD_PKT_STATUS , + val, !(val &GEN_RD_CMD_BUSY ),1000 , +CMD_PKT_STATUS_TIMEOUT_US ); +if (ret <0 ) { +dev_err (dsi->dev,"failed to read command response\n" ); +return ret; + } + +for (i =0 ; i < msg->rx_len;) { +u32 pld =dsi_read (dsi,DSI_GEN_PLD_DATA ); +while (i < msg->rx_len) { + rx_buf[i] = pld &0xff ; + pld >>=8 ; + i++; + } + } + +return msg->rx_len; +} + +static int dw_mipi_dsi_set_max_return_packet_size (struct dw_mipi_dsi *dsi, +size_t len) +{ +u8 val[] = { len &0xff , (len >>8 ) &0xff }; +struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type =MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE , + .tx_buf = val, + .tx_len =2 , + }; + +if (len >0xffff ) +return -EINVAL ; + +return dw_mipi_dsi_dcs_short_write (dsi, &msg); +} +static ssize_t dw_mipi_dsi_host_transfer (struct mipi_dsi_host *host,const struct mipi_dsi_msg *msg) {@@ -692,6 +740,12 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,case MIPI_DSI_DCS_LONG_WRITE : ret =dw_mipi_dsi_dcs_long_write (dsi, msg);break ; +case MIPI_DSI_DCS_READ : + ret =dw_mipi_dsi_set_max_return_packet_size (dsi, msg->rx_len); +if (ret <0 ) +return ret; + ret =dw_mipi_dsi_dcs_read (dsi, msg); +break ;default :dev_err (dsi->dev,"unsupported message type 0x%02x\n" , msg->type);