diff options
author | Dave Airlie <airlied@redhat.com> | 2017-08-25 09:29:45 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-08-25 09:29:45 +1000 |
commit | cfcfb65ad15a1b43cf5cd434c57966fae03db96b (patch) | |
tree | 258c989daae3f81843f6c15468b8ba4d4abecffb /drivers/gpu | |
parent | 7c0059dd832cc686bf0febefdcf8295cdd93007f (diff) | |
parent | d1f08d82176246c6d8a2f1dc26be3638ed4a6083 (diff) |
Merge tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux into drm-next
Updates for 4.14.. I have some further patches from Jordan to add
multiple priority levels and pre-emption, but those will probably be
for 4.15 to give me time for the mesa parts.
* tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux:
drm/msm/mdp5: mark runtime_pm functions as __maybe_unused
drm/msm: remove unused variable
drm/msm/mdp5: make helper function static
drm/msm: make msm_framebuffer_init() static
drm/msm: add helper to allocate stolen fb
drm/msm: don't track fbdev's gem object separately
drm/msm: add modeset module param
drm/msm/mdp5: add tracking for clk enable-count
drm/msm: remove unused define
drm/msm: Add a helper function for in-kernel buffer allocations
drm/msm: Attach the GPU MMU when it is created
drm/msm: Add A5XX hardware fault detection
drm/msm: Remove uneeded platform dev members
drm/msm/mdp5: Set up runtime PM for MDSS
drm/msm/mdp5: Write to SMP registers even if allocations don't change
drm/msm/mdp5: Don't use mode_set helper funcs for encoders and CRTCs
drm/msm/dsi: Implement RPM suspend/resume callbacks
drm/msm/dsi: Set up runtime PM for DSI
drm/msm/hdmi: Set up runtime PM for HDMI
drm/msm/mdp5: Use runtime PM get/put API instead of toggling clocks
Diffstat (limited to 'drivers/gpu')
31 files changed, 574 insertions, 273 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 0e3828ed1e46..7791313405b5 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -486,8 +486,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) adreno_gpu = &a3xx_gpu->base; gpu = &adreno_gpu->base; - a3xx_gpu->pdev = pdev; - gpu->perfcntrs = perfcntrs; gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h index 85ff66cbddd6..ab60dc9e344e 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h @@ -28,7 +28,6 @@ struct a3xx_gpu { struct adreno_gpu base; - struct platform_device *pdev; /* if OCMEM is used for GMEM: */ uint32_t ocmem_base; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 19abf229b08d..58341ef6f15b 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -568,8 +568,6 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) adreno_gpu = &a4xx_gpu->base; gpu = &adreno_gpu->base; - a4xx_gpu->pdev = pdev; - gpu->perfcntrs = NULL; gpu->num_perfcntrs = 0; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.h b/drivers/gpu/drm/msm/adreno/a4xx_gpu.h index 01247204ac92..f757184328a3 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.h @@ -23,7 +23,6 @@ struct a4xx_gpu { struct adreno_gpu base; - struct platform_device *pdev; /* if OCMEM is used for GMEM: */ uint32_t ocmem_base; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index f9eae03aa1dc..17c59d839e6f 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -284,28 +284,14 @@ static int a5xx_me_init(struct msm_gpu *gpu) static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova) { - struct drm_device *drm = gpu->dev; struct drm_gem_object *bo; void *ptr; - bo = msm_gem_new_locked(drm, fw->size - 4, MSM_BO_UNCACHED); - if (IS_ERR(bo)) - return bo; + ptr = msm_gem_kernel_new_locked(gpu->dev, fw->size - 4, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova); - ptr = msm_gem_get_vaddr(bo); - if (!ptr) { - drm_gem_object_unreference(bo); - return ERR_PTR(-ENOMEM); - } - - if (iova) { - int ret = msm_gem_get_iova(bo, gpu->aspace, iova); - - if (ret) { - drm_gem_object_unreference(bo); - return ERR_PTR(ret); - } - } + if (IS_ERR(ptr)) + return ERR_CAST(ptr); memcpy(ptr, &fw->data[4], fw->size - 4); @@ -372,8 +358,7 @@ static int a5xx_zap_shader_init(struct msm_gpu *gpu) { static bool loaded; struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); - struct platform_device *pdev = a5xx_gpu->pdev; + struct platform_device *pdev = gpu->pdev; int ret; /* @@ -410,6 +395,7 @@ static int a5xx_zap_shader_init(struct msm_gpu *gpu) A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \ A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \ A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ + A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT | \ A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP) @@ -812,6 +798,27 @@ static void a5xx_gpmu_err_irq(struct msm_gpu *gpu) dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n"); } +static void a5xx_fault_detect_irq(struct msm_gpu *gpu) +{ + struct drm_device *dev = gpu->dev; + struct msm_drm_private *priv = dev->dev_private; + + dev_err(dev->dev, "gpu fault fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", + gpu->funcs->last_fence(gpu), + gpu_read(gpu, REG_A5XX_RBBM_STATUS), + gpu_read(gpu, REG_A5XX_CP_RB_RPTR), + gpu_read(gpu, REG_A5XX_CP_RB_WPTR), + gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI), + gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ), + gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI), + gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ)); + + /* Turn off the hangcheck timer to keep it from bothering us */ + del_timer(&gpu->hangcheck_timer); + + queue_work(priv->wq, &gpu->recover_work); +} + #define RBBM_ERROR_MASK \ (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \ A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \ @@ -838,6 +845,9 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR) a5xx_cp_err_irq(gpu); + if (status & A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT) + a5xx_fault_detect_irq(gpu); + if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS) a5xx_uche_err_irq(gpu); @@ -1015,7 +1025,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) adreno_gpu = &a5xx_gpu->base; gpu = &adreno_gpu->base; - a5xx_gpu->pdev = pdev; adreno_gpu->registers = a5xx_registers; adreno_gpu->reg_offsets = a5xx_register_offsets; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index 1137092241d5..e94451685bf8 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -23,7 +23,6 @@ struct a5xx_gpu { struct adreno_gpu base; - struct platform_device *pdev; struct drm_gem_object *pm4_bo; uint64_t pm4_iova; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 87af6eea0483..04aab1dcae2b 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -294,16 +294,10 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) */ bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2; - a5xx_gpu->gpmu_bo = msm_gem_new_locked(drm, bosize, MSM_BO_UNCACHED); - if (IS_ERR(a5xx_gpu->gpmu_bo)) - goto err; - - if (msm_gem_get_iova(a5xx_gpu->gpmu_bo, gpu->aspace, - &a5xx_gpu->gpmu_iova)) - goto err; - - ptr = msm_gem_get_vaddr(a5xx_gpu->gpmu_bo); - if (!ptr) + ptr = msm_gem_kernel_new_locked(drm, bosize, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, + &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova); + if (IS_ERR(ptr)) goto err; while (cmds_size > 0) { diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 7414c6bbd582..c8b4ac254bb5 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -337,11 +337,6 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); } -static const char *iommu_ports[] = { - "gfx3d_user", "gfx3d_priv", - "gfx3d1_user", "gfx3d1_priv", -}; - int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs) { @@ -373,15 +368,15 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.ringsz = RB_SIZE; + pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base, adreno_gpu->info->name, &adreno_gpu_config); if (ret) return ret; - pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(&pdev->dev); - ret = request_firmware(&adreno_gpu->pm4, adreno_gpu->info->pm4fw, drm->dev); if (ret) { dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n", @@ -396,37 +391,17 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, return ret; } - if (gpu->aspace && gpu->aspace->mmu) { - struct msm_mmu *mmu = gpu->aspace->mmu; - ret = mmu->funcs->attach(mmu, iommu_ports, - ARRAY_SIZE(iommu_ports)); - if (ret) - return ret; - } + adreno_gpu->memptrs = msm_gem_kernel_new(drm, + sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, + &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); - adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs), - MSM_BO_UNCACHED); - if (IS_ERR(adreno_gpu->memptrs_bo)) { - ret = PTR_ERR(adreno_gpu->memptrs_bo); - adreno_gpu->memptrs_bo = NULL; - dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); - return ret; - } - - adreno_gpu->memptrs = msm_gem_get_vaddr(adreno_gpu->memptrs_bo); if (IS_ERR(adreno_gpu->memptrs)) { - dev_err(drm->dev, "could not vmap memptrs\n"); - return -ENOMEM; - } - - ret = msm_gem_get_iova(adreno_gpu->memptrs_bo, gpu->aspace, - &adreno_gpu->memptrs_iova); - if (ret) { - dev_err(drm->dev, "could not map memptrs: %d\n", ret); - return ret; + ret = PTR_ERR(adreno_gpu->memptrs); + adreno_gpu->memptrs = NULL; + dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); } - return 0; + return ret; } void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) @@ -446,10 +421,4 @@ void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) release_firmware(adreno_gpu->pfp); msm_gpu_cleanup(gpu); - - if (gpu->aspace) { - gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu, - iommu_ports, ARRAY_SIZE(iommu_ports)); - msm_gem_address_space_put(gpu->aspace); - } } diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 311c1c1e7d6c..98742d7af6dc 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -161,12 +161,17 @@ static const struct of_device_id dt_match[] = { {} }; +static const struct dev_pm_ops dsi_pm_ops = { + SET_RUNTIME_PM_OPS(msm_dsi_runtime_suspend, msm_dsi_runtime_resume, NULL) +}; + static struct platform_driver dsi_driver = { .probe = dsi_dev_probe, .remove = dsi_dev_remove, .driver = { .name = "msm_dsi", .of_match_table = dt_match, + .pm = &dsi_pm_ops, }, }; diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 9e6017387efb..2302046197a8 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -179,6 +179,8 @@ void msm_dsi_host_destroy(struct mipi_dsi_host *host); int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, struct drm_device *dev); int msm_dsi_host_init(struct msm_dsi *msm_dsi); +int msm_dsi_runtime_suspend(struct device *dev); +int msm_dsi_runtime_resume(struct device *dev); /* dsi phy */ struct msm_dsi_phy; diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index c7b612c3d771..dbb31a014419 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -135,7 +135,6 @@ struct msm_dsi_host { struct completion video_comp; struct mutex dev_mutex; struct mutex cmd_mutex; - struct mutex clk_mutex; spinlock_t intr_lock; /* Protect interrupt ctrl register */ u32 err_work_state; @@ -221,6 +220,8 @@ static const struct msm_dsi_cfg_handler *dsi_get_config( goto put_gdsc; } + pm_runtime_get_sync(dev); + ret = regulator_enable(gdsc_reg); if (ret) { pr_err("%s: unable to enable gdsc\n", __func__); @@ -247,6 +248,7 @@ disable_clks: clk_disable_unprepare(ahb_clk); disable_gdsc: regulator_disable(gdsc_reg); + pm_runtime_put_autosuspend(dev); put_clk: clk_put(ahb_clk); put_gdsc: @@ -455,6 +457,34 @@ static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host) clk_disable_unprepare(msm_host->bus_clks[i]); } +int msm_dsi_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dsi *msm_dsi = platform_get_drvdata(pdev); + struct mipi_dsi_host *host = msm_dsi->host; + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + if (!msm_host->cfg_hnd) + return 0; + + dsi_bus_clk_disable(msm_host); + + return 0; +} + +int msm_dsi_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct msm_dsi *msm_dsi = platform_get_drvdata(pdev); + struct mipi_dsi_host *host = msm_dsi->host; + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + if (!msm_host->cfg_hnd) + return 0; + + return dsi_bus_clk_enable(msm_host); +} + static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host) { int ret; @@ -596,35 +626,6 @@ static void dsi_link_clk_disable(struct msm_dsi_host *msm_host) } } -static int dsi_clk_ctrl(struct msm_dsi_host *msm_host, bool enable) -{ - int ret = 0; - - mutex_lock(&msm_host->clk_mutex); - if (enable) { - ret = dsi_bus_clk_enable(msm_host); - if (ret) { - pr_err("%s: Can not enable bus clk, %d\n", - __func__, ret); - goto unlock_ret; - } - ret = dsi_link_clk_enable(msm_host); - if (ret) { - pr_err("%s: Can not enable link clk, %d\n", - __func__, ret); - dsi_bus_clk_disable(msm_host); - goto unlock_ret; - } - } else { - dsi_link_clk_disable(msm_host); - dsi_bus_clk_disable(msm_host); - } - -unlock_ret: - mutex_unlock(&msm_host->clk_mutex); - return ret; -} - static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host) { struct drm_display_mode *mode = msm_host->mode; @@ -1699,6 +1700,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) } msm_host->pdev = pdev; + msm_dsi->host = &msm_host->base; ret = dsi_host_parse_dt(msm_host); if (ret) { @@ -1713,6 +1715,8 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) goto fail; } + pm_runtime_enable(&pdev->dev); + msm_host->cfg_hnd = dsi_get_config(msm_host); if (!msm_host->cfg_hnd) { ret = -EINVAL; @@ -1753,7 +1757,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) init_completion(&msm_host->video_comp); mutex_init(&msm_host->dev_mutex); mutex_init(&msm_host->cmd_mutex); - mutex_init(&msm_host->clk_mutex); spin_lock_init(&msm_host->intr_lock); /* setup workqueue */ @@ -1761,7 +1764,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) INIT_WORK(&msm_host->err_work, dsi_err_worker); INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker); - msm_dsi->host = &msm_host->base; msm_dsi->id = msm_host->id; DBG("Dsi Host %d initialized", msm_host->id); @@ -1783,9 +1785,10 @@ void msm_dsi_host_destroy(struct mipi_dsi_host *host) msm_host->workqueue = NULL; } - mutex_destroy(&msm_host->clk_mutex); mutex_destroy(&msm_host->cmd_mutex); mutex_destroy(&msm_host->dev_mutex); + + pm_runtime_disable(&msm_host->pdev->dev); } int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, @@ -1881,7 +1884,8 @@ int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt */ - dsi_clk_ctrl(msm_host, 1); + pm_runtime_get_sync(&msm_host->pdev->dev); + dsi_link_clk_enable(msm_host); /* TODO: vote for bus bandwidth */ @@ -1911,7 +1915,8 @@ void msm_dsi_host_xfer_restore(struct mipi_dsi_host *host, /* TODO: unvote for bus bandwidth */ - dsi_clk_ctrl(msm_host, 0); + dsi_link_clk_disable(msm_host); + pm_runtime_put_autosuspend(&msm_host->pdev->dev); } int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host, @@ -2160,8 +2165,11 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host) * and only turned on before MDP START. * This part of code should be enabled once mdp driver support it. */ - /* if (msm_panel->mode == MSM_DSI_CMD_MODE) - dsi_clk_ctrl(msm_host, 0); */ + /* if (msm_panel->mode == MSM_DSI_CMD_MODE) { + * dsi_link_clk_disable(msm_host); + * pm_runtime_put_autosuspend(&msm_host->pdev->dev); + * } + */ return 0; } @@ -2217,9 +2225,11 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto unlock_ret; } - ret = dsi_clk_ctrl(msm_host, 1); + pm_runtime_get_sync(&msm_host->pdev->dev); + ret = dsi_link_clk_enable(msm_host); if (ret) { - pr_err("%s: failed to enable clocks. ret=%d\n", __func__, ret); + pr_err("%s: failed to enable link clocks. ret=%d\n", + __func__, ret); goto fail_disable_reg; } @@ -2243,7 +2253,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, return 0; fail_disable_clk: - dsi_clk_ctrl(msm_host, 0); + dsi_link_clk_disable(msm_host); + pm_runtime_put_autosuspend(&msm_host->pdev->dev); fail_disable_reg: dsi_host_regulator_disable(msm_host); unlock_ret: @@ -2268,7 +2279,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) pinctrl_pm_select_sleep_state(&msm_host->pdev->dev); - dsi_clk_ctrl(msm_host, 0); + dsi_link_clk_disable(msm_host); + pm_runtime_put_autosuspend(&msm_host->pdev->dev); dsi_host_regulator_disable(msm_host); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 0c2eb9c9a1fc..7c9bf91bc22b 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -373,7 +373,7 @@ static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) static void dsi_phy_disable_resource(struct msm_dsi_phy *phy) { clk_disable_unprepare(phy->ahb_clk); - pm_runtime_put_sync(&phy->pdev->dev); + pm_runtime_put_autosuspend(&phy->pdev->dev); } static const struct of_device_id dsi_phy_dt_match[] = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index a968cad509c2..17e069a133a4 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -239,6 +239,8 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) hdmi->pwr_clks[i] = clk; } + pm_runtime_enable(&pdev->dev); + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); hdmi->i2c = msm_hdmi_i2c_init(hdmi); diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 13ac822dee5d..7e357077ed26 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -35,6 +35,8 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) const struct hdmi_platform_config *config = hdmi->config; int i, ret; + pm_runtime_get_sync(&hdmi->pdev->dev); + for (i = 0; i < config->pwr_reg_cnt; i++) { ret = regulator_enable(hdmi->pwr_regs[i]); if (ret) { @@ -84,6 +86,8 @@ static void power_off(struct drm_bridge *bridge) config->pwr_reg_names[i], ret); } } + + pm_runtime_put_autosuspend(&hdmi->pdev->dev); } #define AVI_IFRAME_LINE_NUMBER 1 diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index 71536d9c7fe8..c0848dfedd50 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c @@ -137,6 +137,36 @@ err: return ret; } +static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) +{ + const struct hdmi_platform_config *config = hdmi->config; + struct device *dev = &hdmi->pdev->dev; + int i, ret; + + if (enable) { + for (i = 0; i < config->hpd_clk_cnt; i++) { + if (config->hpd_freq && config->hpd_freq[i]) { + ret = clk_set_rate(hdmi->hpd_clks[i], + config->hpd_freq[i]); + if (ret) + dev_warn(dev, + "failed to set clk %s (%d)\n", + config->hpd_clk_names[i], ret); + } + + ret = clk_prepare_enable(hdmi->hpd_clks[i]); + if (ret) { + dev_err(dev, + "failed to enable hpd clk: %s (%d)\n", + config->hpd_clk_names[i], ret); + } + } + } else { + for (i = config->hpd_clk_cnt - 1; i >= 0; i--) + clk_disable_unprepare(hdmi->hpd_clks[i]); + } +} + static int hpd_enable(struct hdmi_connector *hdmi_connector) { struct hdmi *hdmi = hdmi_connector->hdmi; @@ -167,22 +197,8 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) goto fail; } - for (i = 0; i < config->hpd_clk_cnt; i++) { - if (config->hpd_freq && config->hpd_freq[i]) { - ret = clk_set_rate(hdmi->hpd_clks[i], - config->hpd_freq[i]); - if (ret) - dev_warn(dev, "failed to set clk %s (%d)\n", - config->hpd_clk_names[i], ret); - } - - ret = clk_prepare_enable(hdmi->hpd_clks[i]); - if (ret) { - dev_err(dev, "failed to enable hpd clk: %s (%d)\n", - config->hpd_clk_names[i], ret); - goto fail; - } - } + pm_runtime_get_sync(dev); + enable_hpd_clocks(hdmi, true); msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); @@ -225,8 +241,8 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector) msm_hdmi_set_mode(hdmi, false); - for (i = 0; i < config->hpd_clk_cnt; i++) - clk_disable_unprepare(hdmi->hpd_clks[i]); + enable_hpd_clocks(hdmi, false); + pm_runtime_put_autosuspend(dev); ret = gpio_config(hdmi, false); if (ret) @@ -285,7 +301,16 @@ void msm_hdmi_connector_irq(struct drm_connector *connector) static enum drm_connector_status detect_reg(struct hdmi *hdmi) { - uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); + uint32_t hpd_int_status; + + pm_runtime_get_sync(&hdmi->pdev->dev); + enable_hpd_clocks(hdmi, true); + + hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); + + enable_hpd_clocks(hdmi, false); + pm_runtime_put_autosuspend(&hdmi->pdev->dev); + return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ? connector_status_connected : connector_status_disconnected; } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c index aa7402e03f67..60790df91bfa 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c @@ -192,6 +192,7 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, { struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder); struct mdp5_kms *mdp5_kms; + struct device *dev; int intf_num; u32 data = 0; @@ -214,14 +215,16 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, /* Smart Panel, Sync mode */ data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL; + dev = &mdp5_kms->pdev->dev; + /* Make sure clocks are on when connectors calling this function. */ - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(dev); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, MDP5_SPLIT_DPL_LOWER_SMART_PANEL); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); - mdp5_disable(mdp5_kms); + pm_runtime_put_autosuspend(dev); return 0; } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 3a81e26629c7..6fcb58ab718c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -415,6 +415,7 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc, struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); struct mdp5_kms *mdp5_kms = get_kms(crtc); + struct device *dev = &mdp5_kms->pdev->dev; DBG("%s", crtc->name); @@ -425,7 +426,7 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc, mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done); mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err); - mdp5_disable(mdp5_kms); + pm_runtime_put_autosuspend(dev); mdp5_crtc->enabled = false; } @@ -436,13 +437,17 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc, struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); struct mdp5_kms *mdp5_kms = get_kms(crtc); + struct device *dev = &mdp5_kms->pdev->dev; DBG("%s", crtc->name); if (WARN_ON(mdp5_crtc->enabled)) return; - mdp5_enable(mdp5_kms); + pm_runtime_get_sync(dev); + + mdp5_crtc_mode_set_nofb(crtc); + mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err); if (mdp5_cstate->cmd_mode) @@ -533,7 +538,7 @@ static bool is_fullscreen(struct drm_crtc_state *cstate, ((pstate->crtc_y + pstate->crtc_h) >= cstate->mode.vdisplay); } -enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc, +static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc, struct drm_crtc_state *new_crtc_state, struct drm_plane_state *bpstate) { @@ -727,6 +732,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline; struct drm_device *dev = crtc->dev; struct mdp5_kms *mdp5_kms = get_kms(crtc); + struct platform_device *pdev = mdp5_kms->pdev; struct msm_kms *kms = &mdp5_kms->base.base; struct drm_gem_object *cursor_bo, *old_bo = NULL; < |