From c0f18a398542094db393e04184cdd1991653183a Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Tue, 20 Dec 2016 08:46:23 +0800 Subject: [PATCH] drm/rockchip: mipi: move mode_set/commit to enable ops enable/disable ops is more compatile to drm atomic framework. fix mipi driver crash when resume: [ 195.399833] PC is at drm_mode_vrefresh+0x0/0x78 [ 195.400249] LR is at dw_mipi_dsi_encoder_commit+0x2ec/0x424 [ 195.400749] pc : [] lr : [] pstate: 20000145 [ 195.529911] [] drm_mode_vrefresh+0x0/0x78 [ 195.530421] [] drm_atomic_helper_commit_modeset_enables+0x168/0x190 [ 195.531126] [] rockchip_atomic_commit_complete+0x3c/0x14c [ 195.531753] [] rockchip_drm_atomic_commit+0x7c/0x9c [ 195.532336] [] drm_atomic_commit+0x6c/0x84 [ 195.532849] [] drm_atomic_helper_connector_dpms+0xf4/0x154 [ 195.533481] [] drm_mode_obj_set_property_ioctl+0x148/0x204 [ 195.534113] [] drm_mode_connector_property_set_ioctl+0x40/0x60 [ 195.534778] [] drm_ioctl+0x270/0x3fc [ 195.535249] [] do_vfs_ioctl+0x4d0/0x5bc [ 195.535739] [] SyS_ioctl+0x60/0x88 [ 195.536194] [] el0_svc_naked+0x24/0x28 Change-Id: Ic80f364a4297e7318c3f0316dd4100737ad7ff6e Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 80 ++++++++------------- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 + 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 0539b6e40b23..98c7e1031196 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -297,14 +297,13 @@ struct dw_mipi_dsi { struct clk *pclk; struct clk *phy_cfg_clk; - int dpms_mode; unsigned int lane_mbps; /* per lane */ u32 channel; u32 lanes; u32 format; u16 input_div; u16 feedback_div; - struct drm_display_mode *mode; + struct drm_display_mode mode; const struct dw_mipi_dsi_plat_data *pdata; }; @@ -352,7 +351,7 @@ static void dw_mipi_dsi_wait_for_two_frames(struct dw_mipi_dsi *dsi) { int refresh, two_frames; - refresh = drm_mode_vrefresh(dsi->mode); + refresh = drm_mode_vrefresh(&dsi->mode); two_frames = DIV_ROUND_UP(MSEC_PER_SEC, refresh) * 2; msleep(two_frames); } @@ -502,7 +501,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(dsi->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; @@ -788,8 +787,8 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi, lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8; - frac = lbcc % dsi->mode->clock; - lbcc = lbcc / dsi->mode->clock; + frac = lbcc % dsi->mode.clock; + lbcc = lbcc / dsi->mode.clock; if (frac) lbcc++; @@ -799,7 +798,7 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi, static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi) { u32 htotal, hsa, hbp, lbcc; - struct drm_display_mode *mode = dsi->mode; + struct drm_display_mode *mode = &dsi->mode; htotal = mode->htotal; hsa = mode->hsync_end - mode->hsync_start; @@ -818,7 +817,7 @@ static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi) { u32 vactive, vsa, vfp, vbp; - struct drm_display_mode *mode = dsi->mode; + struct drm_display_mode *mode = &dsi->mode; vactive = mode->vdisplay; vsa = mode->vsync_end - mode->vsync_start; @@ -859,48 +858,14 @@ 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; - - if (dsi->dpms_mode == DRM_MODE_DPMS_ON) - return; - - 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; - } - - pm_runtime_get_sync(dsi->dev); - - 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); + drm_mode_copy(&dsi->mode, adjusted_mode); } static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) { struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); - if (dsi->dpms_mode != DRM_MODE_DPMS_ON) - return; - drm_panel_disable(dsi->panel); if (clk_prepare_enable(dsi->pclk)) { @@ -922,7 +887,6 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) dw_mipi_dsi_disable(dsi); pm_runtime_put(dsi->dev); clk_disable_unprepare(dsi->pclk); - dsi->dpms_mode = DRM_MODE_DPMS_OFF; } static bool dw_mipi_dsi_encoder_mode_fixup(struct drm_encoder *encoder, @@ -932,11 +896,12 @@ static bool dw_mipi_dsi_encoder_mode_fixup(struct drm_encoder *encoder, return true; } -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); const struct dw_mipi_dsi_plat_data *pdata = dsi->pdata; int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder); + int ret; u32 val; if (clk_prepare_enable(dsi->pclk)) { @@ -944,6 +909,26 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) return; } + ret = dw_mipi_dsi_get_lane_bps(dsi); + if (ret < 0) + return; + + pm_runtime_get_sync(dsi->dev); + + 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"); + if (pdata->grf_dsi0_mode_reg) regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg, pdata->grf_dsi0_mode); @@ -963,7 +948,6 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val); dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); - dsi->dpms_mode = DRM_MODE_DPMS_ON; } static int @@ -1001,8 +985,8 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, static struct drm_encoder_helper_funcs dw_mipi_dsi_encoder_helper_funcs = { .mode_fixup = dw_mipi_dsi_encoder_mode_fixup, - .commit = dw_mipi_dsi_encoder_commit, .mode_set = dw_mipi_dsi_encoder_mode_set, + .enable = dw_mipi_dsi_encoder_enable, .disable = dw_mipi_dsi_encoder_disable, .atomic_check = dw_mipi_dsi_encoder_atomic_check, }; @@ -1162,8 +1146,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, struct resource *res; int ret; - dsi->dpms_mode = DRM_MODE_DPMS_OFF; - if (!dsi->panel) return -EPROBE_DEFER; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 245dfc9e6be1..cbd133eb25aa 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -492,6 +492,8 @@ static int update_state(struct drm_device *drm_dev, conn_state); if (ret) return ret; + if (encoder_helper_funcs->mode_set) + encoder_helper_funcs->mode_set(encoder, mode, mode); priv->crtc_funcs[pipe]->loader_protect(crtc, true); } -- 2.34.1