From 81c4389e4835ad14280718f477cf30b64643b721 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 9 May 2020 12:48:10 +0200 Subject: drm/msm/mdp5: Add MDP5 configuration for MSM8x36. This change adds MDP5 configuration for MSM8x36-based SoCs, like MSM8936, 8939 and their APQ variants. The configuration is based on MSM8916's, but adds some notable features, like ad and pp blocks, along with some register changes. changes since v1: - add an ad block - add a second mixer @ 0x47000 - adjust .max_width - write a more descriptive commit message Signed-off-by: Konrad Dybcio Reviewed-by: Shawn Guo Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c index e3c4c250238b..a7df8dbffdc2 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c @@ -342,6 +342,81 @@ static const struct mdp5_cfg_hw msm8x16_config = { .max_clk = 320000000, }; +static const struct mdp5_cfg_hw msm8x36_config = { + .name = "msm8x36", + .mdp = { + .count = 1, + .base = { 0x0 }, + .caps = MDP_CAP_SMP | + 0, + }, + .smp = { + .mmb_count = 8, + .mmb_size = 10240, + .clients = { + [SSPP_VIG0] = 1, [SSPP_DMA0] = 4, + [SSPP_RGB0] = 7, [SSPP_RGB1] = 8, + }, + }, + .ctl = { + .count = 3, + .base = { 0x01000, 0x01200, 0x01400 }, + .flush_hw_mask = 0x4003ffff, + }, + .pipe_vig = { + .count = 1, + .base = { 0x04000 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC | + MDP_PIPE_CAP_DECIMATION, + }, + .pipe_rgb = { + .count = 2, + .base = { 0x14000, 0x16000 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_DECIMATION, + }, + .pipe_dma = { + .count = 1, + .base = { 0x24000 }, + .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP, + }, + .lm = { + .count = 2, + .base = { 0x44000, 0x47000 }, + .instances = { + { .id = 0, .pp = 0, .dspp = 0, + .caps = MDP_LM_CAP_DISPLAY, }, + { .id = 1, .pp = -1, .dspp = -1, + .caps = MDP_LM_CAP_WB, }, + }, + .nb_stages = 8, + .max_width = 2560, + .max_height = 0xFFFF, + }, + .pp = { + .count = 1, + .base = { 0x70000 }, + }, + .ad = { + .count = 1, + .base = { 0x78000 }, + }, + .dspp = { + .count = 1, + .base = { 0x54000 }, + }, + .intf = { + .base = { 0x00000, 0x6a800, 0x6b000 }, + .connect = { + [0] = INTF_DISABLED, + [1] = INTF_DSI, + [2] = INTF_DSI, + }, + }, + .max_clk = 366670000, +}; + static const struct mdp5_cfg_hw msm8x94_config = { .name = "msm8x94", .mdp = { @@ -840,6 +915,7 @@ static const struct mdp5_cfg_handler cfg_handlers_v1[] = { { .revision = 2, .config = { .hw = &msm8x74v2_config } }, { .revision = 3, .config = { .hw = &apq8084_config } }, { .revision = 6, .config = { .hw = &msm8x16_config } }, + { .revision = 8, .config = { .hw = &msm8x36_config } }, { .revision = 9, .config = { .hw = &msm8x94_config } }, { .revision = 7, .config = { .hw = &msm8x96_config } }, { .revision = 11, .config = { .hw = &msm8x76_config } }, -- cgit v1.2.3 From 09b4138ec2878d504c28a35f0c4c9bb4a0b0c5f4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 4 Dec 2019 07:02:20 +0100 Subject: drm/msm/a6xx: Fix a typo in an error message 'in' is duplicated in the error message. Axe one of them. While at it, slighly improve indentation. Signed-off-by: Christophe JAILLET Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index c4e71abbdd53..40cb4535d554 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1011,8 +1011,8 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, if (j == pri_count) { DRM_DEV_ERROR(dev, - "Level %u not found in in the RPMh list\n", - level); + "Level %u not found in the RPMh list\n", + level); DRM_DEV_ERROR(dev, "Available levels:\n"); for (j = 0; j < pri_count; j++) DRM_DEV_ERROR(dev, " %u\n", pri[j]); -- cgit v1.2.3 From 6a523388a2d4a1a00ec4153592be997066fb596e Mon Sep 17 00:00:00 2001 From: Hongbo Yao Date: Wed, 4 Dec 2019 13:45:48 +0800 Subject: drm/msm/dpu: Fix compile warnings Using the following command will get compile warnings: make W=1 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.o ARCH=arm64 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘_dpu_crtc_program_lm_output_roi’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:91:19: warning: variable ‘dpu_crtc’ set but not used [-Wunused-but-set-variable] struct dpu_crtc *dpu_crtc; ^~~~~~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_atomic_begin’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:428:35: warning: variable ‘smmu_state’ set but not used [-Wunused-but-set-variable] struct dpu_crtc_smmu_state_data *smmu_state; ^~~~~~~~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_atomic_flush’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:489:25: warning: variable ‘event_thread’ set but not used [-Wunused-but-set-variable] struct msm_drm_thread *event_thread; ^~~~~~~~~~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_destroy_state’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:565:19: warning: variable ‘dpu_crtc’ set but not used [-Wunused-but-set-variable] struct dpu_crtc *dpu_crtc; ^~~~~~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_duplicate_state’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:664:19: warning: variable ‘dpu_crtc’ set but not used [-Wunused-but-set-variable] struct dpu_crtc *dpu_crtc; ^~~~~~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_disable’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:693:26: warning: variable ‘priv’ set but not used [-Wunused-but-set-variable] struct msm_drm_private *priv; ^~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:691:27: warning: variable ‘mode’ set but not used [-Wunused-but-set-variable] struct drm_display_mode *mode; ^~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_enable’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:766:26: warning: variable ‘priv’ set but not used [-Wunused-but-set-variable] struct msm_drm_private *priv; ^~~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c: In function ‘dpu_crtc_init’: drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:1292:18: warning: variable ‘kms’ set but not used [-Wunused-but-set-variable] struct dpu_kms *kms = NULL; ^~~ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:663: warning: Excess function parameter 'Returns' description in 'dpu_crtc_duplicate_state' Reported-by: Hulk Robot Signed-off-by: Hongbo Yao Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 17448505a9b5..cf3af731a324 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -88,11 +88,9 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer, static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) { - struct dpu_crtc *dpu_crtc; struct dpu_crtc_state *crtc_state; int lm_idx, lm_horiz_position; - dpu_crtc = to_dpu_crtc(crtc); crtc_state = to_dpu_crtc_state(crtc->state); lm_horiz_position = 0; @@ -430,7 +428,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_encoder *encoder; struct drm_device *dev; unsigned long flags; - struct dpu_crtc_smmu_state_data *smmu_state; if (!crtc) { DPU_ERROR("invalid crtc\n"); @@ -448,7 +445,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, dpu_crtc = to_dpu_crtc(crtc); cstate = to_dpu_crtc_state(crtc->state); dev = crtc->dev; - smmu_state = &dpu_crtc->smmu_state; _dpu_crtc_setup_lm_bounds(crtc, crtc->state); @@ -491,7 +487,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_device *dev; struct drm_plane *plane; struct msm_drm_private *priv; - struct msm_drm_thread *event_thread; unsigned long flags; struct dpu_crtc_state *cstate; @@ -513,8 +508,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, return; } - event_thread = &priv->event_thread[crtc->index]; - if (dpu_crtc->event) { DPU_DEBUG("already received dpu_crtc->event\n"); } else { @@ -567,7 +560,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, static void dpu_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct dpu_crtc *dpu_crtc; struct dpu_crtc_state *cstate; if (!crtc || !state) { @@ -575,7 +567,6 @@ static void dpu_crtc_destroy_state(struct drm_crtc *crtc, return; } - dpu_crtc = to_dpu_crtc(crtc); cstate = to_dpu_crtc_state(state); DPU_DEBUG("crtc%d\n", crtc->base.id); @@ -662,11 +653,9 @@ static void dpu_crtc_reset(struct drm_crtc *crtc) /** * dpu_crtc_duplicate_state - state duplicate hook * @crtc: Pointer to drm crtc structure - * @Returns: Pointer to new drm_crtc_state structure */ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) { - struct dpu_crtc *dpu_crtc; struct dpu_crtc_state *cstate, *old_cstate; if (!crtc || !crtc->state) { @@ -674,7 +663,6 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) return NULL; } - dpu_crtc = to_dpu_crtc(crtc); old_cstate = to_dpu_crtc_state(crtc->state); cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL); if (!cstate) { @@ -693,9 +681,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, { struct dpu_crtc *dpu_crtc; struct dpu_crtc_state *cstate; - struct drm_display_mode *mode; struct drm_encoder *encoder; - struct msm_drm_private *priv; unsigned long flags; bool release_bandwidth = false; @@ -705,8 +691,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, } dpu_crtc = to_dpu_crtc(crtc); cstate = to_dpu_crtc_state(crtc->state); - mode = &cstate->base.adjusted_mode; - priv = crtc->dev->dev_private; DRM_DEBUG_KMS("crtc%d\n", crtc->base.id); @@ -768,14 +752,12 @@ static void dpu_crtc_enable(struct drm_crtc *crtc, { struct dpu_crtc *dpu_crtc; struct drm_encoder *encoder; - struct msm_drm_private *priv; bool request_bandwidth; if (!crtc) { DPU_ERROR("invalid crtc\n"); return; } - priv = crtc->dev->dev_private; pm_runtime_get_sync(crtc->dev->dev); -- cgit v1.2.3 From ab723b7a992a19b843f798b183f53f7472f598c8 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Fri, 24 Jan 2020 00:57:10 +0100 Subject: drm/msm: Add syncobj support. This 1) Enables core DRM syncobj support. 2) Adds options to the submission ioctl to wait/signal syncobjs. Just like the wait fence fd, this does inline waits. Using the scheduler would be nice but I believe it is out of scope for this work. Support for timeline syncobjs is implemented and the interface is ready for it, but I'm not enabling it yet until there is some code for turnip to use it. The reset is mostly in there because in the presence of waiting and signalling the same semaphores, resetting them after signalling can become very annoying. v2: - Fixed style issues - Removed a cleanup issue in a failure case - Moved to a copy_from_user per syncobj v3: - Fixed a missing declaration introduced in v2 - Reworked to use ERR_PTR/PTR_ERR - Simplified failure gotos. Used by: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2769 Signed-off-by: Bas Nieuwenhuizen Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 6 +- drivers/gpu/drm/msm/msm_gem_submit.c | 232 ++++++++++++++++++++++++++++++++++- include/uapi/drm/msm_drm.h | 24 +++- 3 files changed, 258 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 29295dee2a2e..f6ce40bf3699 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -37,9 +37,10 @@ * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get * GEM object's debug name * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl + * - 1.6.0 - Syncobj support */ #define MSM_VERSION_MAJOR 1 -#define MSM_VERSION_MINOR 5 +#define MSM_VERSION_MINOR 6 #define MSM_VERSION_PATCHLEVEL 0 static const struct drm_mode_config_funcs mode_config_funcs = { @@ -1002,7 +1003,8 @@ static struct drm_driver msm_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC | - DRIVER_MODESET, + DRIVER_MODESET | + DRIVER_SYNCOBJ, .open = msm_open, .postclose = msm_postclose, .lastclose = drm_fb_helper_lastclose, diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 385d4965a8d0..6630aa817505 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -8,7 +8,9 @@ #include #include +#include #include +#include #include "msm_drv.h" #include "msm_gpu.h" @@ -391,6 +393,186 @@ static void submit_cleanup(struct msm_gem_submit *submit) } } + +struct msm_submit_post_dep { + struct drm_syncobj *syncobj; + uint64_t point; + struct dma_fence_chain *chain; +}; + +static struct drm_syncobj **msm_wait_deps(struct drm_device *dev, + struct drm_file *file, + uint64_t in_syncobjs_addr, + uint32_t nr_in_syncobjs, + size_t syncobj_stride, + struct msm_ringbuffer *ring) +{ + struct drm_syncobj **syncobjs = NULL; + struct drm_msm_gem_submit_syncobj syncobj_desc = {0}; + int ret = 0; + uint32_t i, j; + + syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs), + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + if (!syncobjs) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < nr_in_syncobjs; ++i) { + uint64_t address = in_syncobjs_addr + i * syncobj_stride; + struct dma_fence *fence; + + if (copy_from_user(&syncobj_desc, + u64_to_user_ptr(address), + min(syncobj_stride, sizeof(syncobj_desc)))) { + ret = -EFAULT; + break; + } + + if (syncobj_desc.point && + !drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) { + ret = -EOPNOTSUPP; + break; + } + + if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) { + ret = -EINVAL; + break; + } + + ret = drm_syncobj_find_fence(file, syncobj_desc.handle, + syncobj_desc.point, 0, &fence); + if (ret) + break; + + if (!dma_fence_match_context(fence, ring->fctx->context)) + ret = dma_fence_wait(fence, true); + + dma_fence_put(fence); + if (ret) + break; + + if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) { + syncobjs[i] = + drm_syncobj_find(file, syncobj_desc.handle); + if (!syncobjs[i]) { + ret = -EINVAL; + break; + } + } + } + + if (ret) { + for (j = 0; j <= i; ++j) { + if (syncobjs[j]) + drm_syncobj_put(syncobjs[j]); + } + kfree(syncobjs); + return ERR_PTR(ret); + } + return syncobjs; +} + +static void msm_reset_syncobjs(struct drm_syncobj **syncobjs, + uint32_t nr_syncobjs) +{ + uint32_t i; + + for (i = 0; syncobjs && i < nr_syncobjs; ++i) { + if (syncobjs[i]) + drm_syncobj_replace_fence(syncobjs[i], NULL); + } +} + +static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev, + struct drm_file *file, + uint64_t syncobjs_addr, + uint32_t nr_syncobjs, + size_t syncobj_stride) +{ + struct msm_submit_post_dep *post_deps; + struct drm_msm_gem_submit_syncobj syncobj_desc = {0}; + int ret = 0; + uint32_t i, j; + + post_deps = kmalloc_array(nr_syncobjs, sizeof(*post_deps), + GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); + if (!post_deps) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < nr_syncobjs; ++i) { + uint64_t address = syncobjs_addr + i * syncobj_stride; + + if (copy_from_user(&syncobj_desc, + u64_to_user_ptr(address), + min(syncobj_stride, sizeof(syncobj_desc)))) { + ret = -EFAULT; + break; + } + + post_deps[i].point = syncobj_desc.point; + post_deps[i].chain = NULL; + + if (syncobj_desc.flags) { + ret = -EINVAL; + break; + } + + if (syncobj_desc.point) { + if (!drm_core_check_feature(dev, + DRIVER_SYNCOBJ_TIMELINE)) { + ret = -EOPNOTSUPP; + break; + } + + post_deps[i].chain = + kmalloc(sizeof(*post_deps[i].chain), + GFP_KERNEL); + if (!post_deps[i].chain) { + ret = -ENOMEM; + break; + } + } + + post_deps[i].syncobj = + drm_syncobj_find(file, syncobj_desc.handle); + if (!post_deps[i].syncobj) { + ret = -EINVAL; + break; + } + } + + if (ret) { + for (j = 0; j <= i; ++j) { + kfree(post_deps[j].chain); + if (post_deps[j].syncobj) + drm_syncobj_put(post_deps[j].syncobj); + } + + kfree(post_deps); + return ERR_PTR(ret); + } + + return post_deps; +} + +static void msm_process_post_deps(struct msm_submit_post_dep *post_deps, + uint32_t count, struct dma_fence *fence) +{ + uint32_t i; + + for (i = 0; post_deps && i < count; ++i) { + if (post_deps[i].chain) { + drm_syncobj_add_point(post_deps[i].syncobj, + post_deps[i].chain, + fence, post_deps[i].point); + post_deps[i].chain = NULL; + } else { + drm_syncobj_replace_fence(post_deps[i].syncobj, + fence); + } + } +} + int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file) { @@ -403,6 +585,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct sync_file *sync_file = NULL; struct msm_gpu_submitqueue *queue; struct msm_ringbuffer *ring; + struct msm_submit_post_dep *post_deps = NULL; + struct drm_syncobj **syncobjs_to_reset = NULL; int out_fence_fd = -1; struct pid *pid = get_pid(task_pid(current)); bool has_ww_ticket = false; @@ -411,6 +595,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (!gpu) return -ENXIO; + if (args->pad) + return -EINVAL; + /* for now, we just have 3d pipe.. eventually this would need to * be more clever to dispatch to appropriate gpu module: */ @@ -458,9 +645,29 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, return ret; } + if (args->flags & MSM_SUBMIT_SYNCOBJ_IN) { + syncobjs_to_reset = msm_wait_deps(dev, file, + args->in_syncobjs, + args->nr_in_syncobjs, + args->syncobj_stride, ring); + if (IS_ERR(syncobjs_to_reset)) + return PTR_ERR(syncobjs_to_reset); + } + + if (args->flags & MSM_SUBMIT_SYNCOBJ_OUT) { + post_deps = msm_parse_post_deps(dev, file, + args->out_syncobjs, + args->nr_out_syncobjs, + args->syncobj_stride); + if (IS_ERR(post_deps)) { + ret = PTR_ERR(post_deps); + goto out_post_unlock; + } + } + ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) - return ret; + goto out_post_unlock; if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) { out_fence_fd = get_unused_fd_flags(O_CLOEXEC); @@ -587,6 +794,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, args->fence_fd = out_fence_fd; } + msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); + msm_process_post_deps(post_deps, args->nr_out_syncobjs, + submit->fence); + + out: submit_cleanup(submit); if (has_ww_ticket) @@ -597,5 +809,23 @@ out_unlock: if (ret && (out_fence_fd >= 0)) put_unused_fd(out_fence_fd); mutex_unlock(&dev->struct_mutex); + +out_post_unlock: + if (!IS_ERR_OR_NULL(post_deps)) { + for (i = 0; i < args->nr_out_syncobjs; ++i) { + kfree(post_deps[i].chain); + drm_syncobj_put(post_deps[i].syncobj); + } + kfree(post_deps); + } + + if (!IS_ERR_OR_NULL(syncobjs_to_reset)) { + for (i = 0; i < args->nr_in_syncobjs; ++i) { + if (syncobjs_to_reset[i]) + drm_syncobj_put(syncobjs_to_reset[i]); + } + kfree(syncobjs_to_reset); + } + return ret; } diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h index 0b85ed6a3710..19806eb3a8e8 100644 --- a/include/uapi/drm/msm_drm.h +++ b/include/uapi/drm/msm_drm.h @@ -217,13 +217,28 @@ struct drm_msm_gem_submit_bo { #define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */ #define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */ #define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */ +#define MSM_SUBMIT_SYNCOBJ_IN 0x08000000 /* enable input syncobj */ +#define MSM_SUBMIT_SYNCOBJ_OUT 0x04000000 /* enable output syncobj */ #define MSM_SUBMIT_FLAGS ( \ MSM_SUBMIT_NO_IMPLICIT | \ MSM_SUBMIT_FENCE_FD_IN | \ MSM_SUBMIT_FENCE_FD_OUT | \ MSM_SUBMIT_SUDO | \ + MSM_SUBMIT_SYNCOBJ_IN | \ + MSM_SUBMIT_SYNCOBJ_OUT | \ 0) +#define MSM_SUBMIT_SYNCOBJ_RESET 0x00000001 /* Reset syncobj after wait. */ +#define MSM_SUBMIT_SYNCOBJ_FLAGS ( \ + MSM_SUBMIT_SYNCOBJ_RESET | \ + 0) + +struct drm_msm_gem_submit_syncobj { + __u32 handle; /* in, syncobj handle. */ + __u32 flags; /* in, from MSM_SUBMIT_SYNCOBJ_FLAGS */ + __u64 point; /* in, timepoint for timeline syncobjs. */ +}; + /* Each cmdstream submit consists of a table of buffers involved, and * one or more cmdstream buffers. This allows for conditional execution * (context-restore), and IB buffers needed for per tile/bin draw cmds. @@ -236,7 +251,14 @@ struct drm_msm_gem_submit { __u64 bos; /* in, ptr to array of submit_bo's */ __u64 cmds; /* in, ptr to array of submit_cmd's */ __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */ - __u32 queueid; /* in, submitqueue id */ + __u32 queueid; /* in, submitqueue id */ + __u64 in_syncobjs; /* in, ptr to to array of drm_msm_gem_submit_syncobj */ + __u64 out_syncobjs; /* in, ptr to to array of drm_msm_gem_submit_syncobj */ + __u32 nr_in_syncobjs; /* in, number of entries in in_syncobj */ + __u32 nr_out_syncobjs; /* in, number of entries in out_syncobj. */ + __u32 syncobj_stride; /* in, stride of syncobj arrays. */ + __u32 pad; /*in, reserved for future use, always 0. */ + }; /* The normal way to synchronize with the GPU is just to CPU_PREP on -- cgit v1.2.3 From 20aebe83698feb107d5a66b6cfd1d54459ccdfcf Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 30 Apr 2020 12:24:27 -0700 Subject: drm/msm: Fix undefined "rd_full" link error rd_full should be defined outside the CONFIG_DEBUG_FS region, in order to be able to link the msm driver even when CONFIG_DEBUG_FS is disabled. Fixes: e515af8d4a6f ("drm/msm: devcoredump should dump MSM_SUBMIT_BO_DUMP buffers") Reported-by: Stephen Rothwell Signed-off-by: Bjorn Andersson Reviewed-by: Rob Clark Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_rd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 732f65df5c4f..fea30e7aa9e8 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -29,8 +29,6 @@ * or shader programs (if not emitted inline in cmdstream). */ -#ifdef CONFIG_DEBUG_FS - #include #include #include @@ -47,6 +45,8 @@ bool rd_full = false; MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents"); module_param_named(rd_full, rd_full, bool, 0600); +#ifdef CONFIG_DEBUG_FS + enum rd_sect_type { RD_NONE, RD_TEST, /* ascii text */ -- cgit v1.2.3 From e4b397f6a54c1b653b65c3dbcf3d3a157f580355 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 12 Apr 2020 16:35:09 +0200 Subject: drm/msm: Fix typo Duplicated 'we' Signed-off-by: Christophe JAILLET Reviewed-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index 998bef1190a3..b5fed67c4651 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -959,7 +959,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, if (!ctl) return -EINVAL; - /* don't support LM cursors when we we have source split enabled */ + /* don't support LM cursors when we have source split enabled */ if (mdp5_cstate->pipeline.r_mixer) return -EINVAL; @@ -1030,7 +1030,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) return -EINVAL; } - /* don't support LM cursors when we we have source split enabled */ + /* don't support LM cursors when we have source split enabled */ if (mdp5_cstate->pipeline.r_mixer) return -EINVAL; -- cgit v1.2.3 From e4337877c5d578722c0716f131fb774522013cf5 Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Tue, 7 Apr 2020 18:07:37 +0100 Subject: drm/msm/mdp5: Fix mdp5_init error path for failed mdp5_kms allocation When allocation for mdp5_kms fails, calling mdp5_destroy() leads to undefined behaviour, likely a nullptr exception or use-after-free troubles. Signed-off-by: Roy Spliet Reviewed-by: Abhinav Kumar Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 47b989834af1..c23a2fa13fb9 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -943,7 +943,8 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) return 0; fail: - mdp5_destroy(pdev); + if (mdp5_kms) + mdp5_destroy(pdev); return ret; } -- cgit v1.2.3 From e47616df008b1059c57892fb34883403a6933231 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Tue, 24 Mar 2020 15:31:18 +0530 Subject: drm/msm/dpu: add support for color processing blocks in dpu driver This change adds support to configure dspp blocks in the dpu driver. Macro description of the changes coming in this patch. 1) Add dspp definitions in the hw catalog. 2) Add capability to reserve dspp blocks in the display data path. 3) Attach the reserved block to the encoder. Signed-off-by: Kalyan Thota Tested-by: Fritz Koenig Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 39 ++++++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 39 ++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 26 ++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 3 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 82 ++++++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 69 ++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 58 ++++++++++++++++-- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 + drivers/gpu/drm/msm/msm_drv.h | 1 + 14 files changed, 322 insertions(+), 15 deletions(-) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 1579cf0d828f..42f8aae28b31 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -65,6 +65,7 @@ msm-y := \ disp/dpu1/dpu_hw_lm.o \ disp/dpu1/dpu_hw_pingpong.o \ disp/dpu1/dpu_hw_sspp.o \ + disp/dpu1/dpu_hw_dspp.o \ disp/dpu1/dpu_hw_top.o \ disp/dpu1/dpu_hw_util.o \ disp/dpu1/dpu_hw_vbif.o \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 5174e86124cc..cec3474340e8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -73,12 +73,14 @@ struct dpu_crtc_smmu_state_data { * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC * @hw_lm: LM HW Driver context * @lm_ctl: CTL Path HW driver context + * @lm_dspp: DSPP HW driver context * @mixer_op_mode: mixer blending operation mode * @flush_mask: mixer flush mask for ctl, mixer and pipe */ struct dpu_crtc_mixer { struct dpu_hw_mixer *hw_lm; struct dpu_hw_ctl *lm_ctl; + struct dpu_hw_dspp *hw_dspp; u32 mixer_op_mode; u32 flush_mask; }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index a1b79ee2bd9d..63976dcd2ac8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -20,6 +20,7 @@ #include "dpu_hw_catalog.h" #include "dpu_hw_intf.h" #include "dpu_hw_ctl.h" +#include "dpu_hw_dspp.h" #include "dpu_formats.h" #include "dpu_encoder_phys.h" #include "dpu_crtc.h" @@ -536,6 +537,7 @@ static struct msm_display_topology dpu_encoder_get_topology( * 1 LM, 1 INTF * 2 LM, 1 INTF (stream merge to support high resolution interfaces) * + * Adding color blocks only to primary interface */ if (intf_count == 2) topology.num_lm = 2; @@ -544,6 +546,9 @@ static struct msm_display_topology dpu_encoder_get_topology( else topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1; + if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI) + topology.num_dspp = topology.num_lm; + topology.num_enc = 0; topology.num_intf = intf_count; @@ -959,7 +964,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC]; struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC]; - int num_lm, num_ctl, num_pp; + struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL }; + int num_lm, num_ctl, num_pp, num_dspp; int i, j; if (!drm_enc) { @@ -1008,6 +1014,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl)); num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm)); + num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state, + drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp, + ARRAY_SIZE(hw_dspp)); for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i]) @@ -1020,6 +1029,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]); cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]); + cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]); } cstate->num_mixers = num_lm; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index c567917541e8..19d065ad0b25 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -41,6 +41,8 @@ #define PINGPONG_SDM845_SPLIT_MASK \ (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) +#define DSPP_SC7180_MASK 0 + #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 #define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560 @@ -291,29 +293,30 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = { }, }; -#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair) \ +#define LM_BLK(_name, _id, _base, _fmask, _sblk, _pp, _lmpair, _dspp) \ { \ .name = _name, .id = _id, \ .base = _base, .len = 0x320, \ .features = _fmask, \ .sblk = _sblk, \ .pingpong = _pp, \ - .lm_pair_mask = (1 << _lmpair) \ + .lm_pair_mask = (1 << _lmpair), \ + .dspp = _dspp \ } static const struct dpu_lm_cfg sdm845_lm[] = { LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_0, LM_1), + &sdm845_lm_sblk, PINGPONG_0, LM_1, 0), LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_1, LM_0), + &sdm845_lm_sblk, PINGPONG_1, LM_0, 0), LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_2, LM_5), + &sdm845_lm_sblk, PINGPONG_2, LM_5, 0), LM_BLK("lm_3", LM_3, 0x0, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_MAX, 0), + &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), LM_BLK("lm_4", LM_4, 0x0, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_MAX, 0), + &sdm845_lm_sblk, PINGPONG_MAX, 0, 0), LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK, - &sdm845_lm_sblk, PINGPONG_3, LM_2), + &sdm845_lm_sblk, PINGPONG_3, LM_2, 0), }; /* SC7180 */ @@ -328,11 +331,25 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = { static const struct dpu_lm_cfg sc7180_lm[] = { LM_BLK("lm_0", LM_0, 0x44000, MIXER_SC7180_MASK, - &sc7180_lm_sblk, PINGPONG_0, LM_1), + &sc7180_lm_sblk, PINGPONG_0, LM_1, DSPP_0), LM_BLK("lm_1", LM_1, 0x45000, MIXER_SC7180_MASK, - &sc7180_lm_sblk, PINGPONG_1, LM_0), + &sc7180_lm_sblk, PINGPONG_1, LM_0, 0), }; +/************************************************************* + * DSPP sub blocks config + *************************************************************/ +#define DSPP_BLK(_name, _id, _base) \ + {\ + .name = _name, .id = _id, \ + .base = _base, .len = 0x1800, \ + .features = DSPP_SC7180_MASK, \ + .sblk = NULL, \ + } + +static const struct dpu_dspp_cfg sc7180_dspp[] = { + DSPP_BLK("dspp_0", DSPP_0, 0x54000), +}; /************************************************************* * PINGPONG sub blocks config *************************************************************/ @@ -587,6 +604,8 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg) .sspp = sc7180_sspp, .mixer_count = ARRAY_SIZE(sc7180_lm), .mixer = sc7180_lm, + .dspp_count = ARRAY_SIZE(sc7180_dspp), + .dspp = sc7180_dspp, .pingpong_count = ARRAY_SIZE(sc7180_pp), .pingpong = sc7180_pp, .intf_count = ARRAY_SIZE(sc7180_intf), diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 09df7d87dd43..f7de43838c69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -145,6 +145,17 @@ enum { DPU_MIXER_MAX }; +/** + * DSPP sub-blocks + * @DPU_DSPP_PCC Panel color correction block + * @DPU_DSPP_GC Gamma correction block + */ +enum { + DPU_DSPP_PCC = 0x1, + DPU_DSPP_GC, + DPU_DSPP_MAX +}; + /** * PINGPONG sub-blocks * @DPU_PINGPONG_TE Tear check block @@ -377,6 +388,16 @@ struct dpu_lm_sub_blks { struct dpu_pp_blk gc; }; +/** + * struct dpu_dspp_sub_blks: Information of DSPP block + * @gc : gamma correction block + * @pcc: pixel color correction block + */ +struct dpu_dspp_sub_blks { + struct dpu_pp_blk gc; + struct dpu_pp_blk pcc; +}; + struct dpu_pingpong_sub_blks { struct dpu_pp_blk te; struct dpu_pp_blk te2; @@ -471,9 +492,23 @@ struct dpu_lm_cfg { DPU_HW_BLK_INFO; const struct dpu_lm_sub_blks *sblk; u32 pingpong; + u32 dspp; unsigned long lm_pair_mask; }; +/** + * struct dpu_dspp_cfg - information of DSPP blocks + * @id enum identifying this block + * @base register offset of this block + * @features bit mask identifying sub-blocks/features + * supported by this block + * @sblk sub-blocks information + */ +struct dpu_dspp_cfg { + DPU_HW_BLK_INFO; + const struct dpu_dspp_sub_blks *sblk; +}; + /** * struct dpu_pingpong_cfg - information of PING-PONG blocks * @id enum identifying this block @@ -688,6 +723,9 @@ struct dpu_mdss_cfg { u32 ad_count; + u32 dspp_count; + const struct dpu_dspp_cfg *dspp; + /* Add additional block data structures here */ struct dpu_perf_cfg perf; @@ -716,6 +754,7 @@ struct dpu_mdss_hw_cfg_handler { #define BLK_PINGPONG(s) ((s)->pingpong) #define BLK_INTF(s) ((s)->intf) #define BLK_AD(s) ((s)->ad) +#define BLK_DSPP(s) ((s)->dspp) /** * dpu_hw_catalog_init - dpu hardware catalog init API retrieves diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 831e5f7a9b7f..613ae8f0cfcd 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -272,6 +272,31 @@ static int dpu_hw_ctl_active_get_bitmask_intf(struct dpu_hw_ctl *ctx, return 0; } +static uint32_t dpu_hw_ctl_get_bitmask_dspp(struct dpu_hw_ctl *ctx, + enum dpu_dspp dspp) +{ + uint32_t flushbits = 0; + + switch (dspp) { + case DSPP_0: + flushbits = BIT(13); + break; + case DSPP_1: + flushbits = BIT(14); + break; + case DSPP_2: + flushbits = BIT(15); + break; + case DSPP_3: + flushbits = BIT(21); + break; + default: + return 0; + } + + return flushbits; +} + static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us) { struct dpu_hw_blk_reg_map *c = &ctx->hw; @@ -548,6 +573,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp; ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer; + ops->get_bitmask_dspp = dpu_hw_ctl_get_bitmask_dspp; }; static struct dpu_hw_blk_ops dpu_hw_ops; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h index 09e1263c72e2..ec579b470a80 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h @@ -139,6 +139,9 @@ struct dpu_hw_ctl_ops { uint32_t (*get_bitmask_mixer)(struct dpu_hw_ctl *ctx, enum dpu_lm blk); + uint32_t (*get_bitmask_dspp)(struct dpu_hw_ctl *ctx, + enum dpu_dspp blk); + /** * Query the value of the intf flush mask * No effect on hardware diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c new file mode 100644 index 000000000000..75c82e92bd2a --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + */ + +#include "dpu_hwio.h" +#include "dpu_hw_catalog.h" +#include "dpu_hw_lm.h" +#include "dpu_hw_dspp.h" +#include "dpu_kms.h" + + +static void _setup_dspp_ops(struct dpu_hw_dspp *c, + unsigned long features) +{ + return; +} + +static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp, + const struct dpu_mdss_cfg *m, + void __iomem *addr, + struct dpu_hw_blk_reg_map *b) +{ + int i; + + if (!m || !addr || !b) + return ERR_PTR(-EINVAL); + + for (i = 0; i < m->dspp_count; i++) { + if (dspp == m->dspp[i].id) { + b->base_off = addr; + b->blk_off = m->dspp[i].base; + b->length = m->dspp[i].len; + b->hwversion = m->hwversion; + b->log_mask = DPU_DBG_MASK_DSPP; + return &m->dspp[i]; + } + } + + return ERR_PTR(-EINVAL); +} + +static struct dpu_hw_blk_ops dpu_hw_ops; + +struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, + void __iomem *addr, + const struct dpu_mdss_cfg *m) +{ + struct dpu_hw_dspp *c; + const struct dpu_dspp_cfg *cfg; + + if (!addr || !m) + return ERR_PTR(-EINVAL); + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return ERR_PTR(-ENOMEM); + + cfg = _dspp_offset(idx, m, addr, &c->hw); + if (IS_ERR_OR_NULL(cfg)) { + kfree(c); + return ERR_PTR(-EINVAL); + } + + /* Assign ops */ + c->idx = idx; + c->cap = cfg; + _setup_dspp_ops(c, c->cap->features); + + dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSPP, idx, &dpu_hw_ops); + + return c; +} + +void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp) +{ + if (dspp) + dpu_hw_blk_destroy(&dspp->base); + + kfree(dspp); +} + + diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h new file mode 100644 index 000000000000..09807ea3f0fd --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_HW_DSPP_H +#define _DPU_HW_DSPP_H + +#include "dpu_hw_blk.h" + +struct dpu_hw_dspp; + +/** + * struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions + * Caller must call the init function to get the dspp context for each dspp + * Assumption is these functions will be called after clocks are enabled + */ +struct dpu_hw_dspp_ops { + + void (*dummy)(struct dpu_hw_dspp *ctx); +}; + +/** + * struct dpu_hw_dspp - dspp description + * @base: Hardware block base structure + * @hw: Block hardware details + * @idx: DSPP index + * @cap: Pointer to layer_cfg + * @ops: Pointer to operations possible for this DSPP + */ +struct dpu_hw_dspp { + struct dpu_hw_blk base; + struct dpu_hw_blk_reg_map hw; + + /* dspp */ + int idx; + const struct dpu_dspp_cfg *cap; + + /* Ops */ + struct dpu_hw_dspp_ops ops; +}; + +/** + * dpu_hw_dspp - convert base object dpu_hw_base to container + * @hw: Pointer to base hardware block + * return: Pointer to hardware block container + */ +static inline struct dpu_hw_dspp *to_dpu_hw_dspp(struct dpu_hw_blk *hw) +{ + return container_of(hw, struct dpu_hw_dspp, base); +} + +/** + * dpu_hw_dspp_init - initializes the dspp hw driver object. + * should be called once before accessing every dspp. + * @idx: DSPP index for which driver object is required + * @addr: Mapped register io address of MDP + * @Return: pointer to structure or ERR_PTR + */ +struct dpu_hw_dspp *dpu_hw_dspp_init(enum dpu_dspp idx, + void __iomem *addr, const struct dpu_mdss_cfg *m); + +/** + * dpu_hw_dspp_destroy(): Destroys DSPP driver context + * @dspp: Pointer to DSPP driver context + */ +void dpu_hw_dspp_destroy(struct dpu_hw_dspp *dspp); + +#endif /*_DPU_HW_DSPP_H */ + diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h index 686882132bf6..402dc5832361 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h @@ -95,6 +95,7 @@ enum dpu_hw_blk_type { DPU_HW_BLK_PINGPONG, DPU_HW_BLK_INTF, DPU_HW_BLK_WB, + DPU_HW_BLK_DSPP, DPU_HW_BLK_MAX, }; @@ -425,5 +426,6 @@ struct dpu_mdss_color { #define DPU_DBG_MASK_TOP (1 << 7) #define DPU_DBG_MASK_VBIF (1 << 8) #define DPU_DBG_MASK_ROT (1 << 9) +#define DPU_DBG_MASK_DSPP (1 << 10) #endif /* _DPU_HW_MDSS_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 211f5de99a44..4e32d040f1e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -158,6 +158,7 @@ struct dpu_global_state { uint32_t mixer_to_enc_id[LM_MAX - LM_0]; uint32_t ctl_to_enc_id[CTL_MAX - CTL_0]; uint32_t intf_to_enc_id[INTF_MAX - INTF_0]; + uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0]; }; struct dpu_global_state diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 9b62451b01ee..9b2b5044e8e0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -9,6 +9,7 @@ #include "dpu_hw_ctl.h" #include "dpu_hw_pingpong.h" #include "dpu_hw_intf.h" +#include "dpu_hw_dspp.h" #include "dpu_encoder.h" #include "dpu_trace.h" @@ -174,6 +175,23 @@ int dpu_rm_init(struct dpu_rm *rm, rm->ctl_blks[ctl->id - CTL_0] = &hw->base; } + for (i = 0; i < cat->dspp_count; i++) { + struct dpu_hw_dspp *hw; + const struct dpu_dspp_cfg *dspp = &cat->dspp[i]; + + if (dspp->id < DSPP_0 || dspp->id >= DSPP_MAX) { + DPU_ERROR("skip dspp %d with invalid id\n", dspp->id); + continue; + } + hw = dpu_hw_dspp_init(dspp->id, mmio, cat); + if (IS_ERR_OR_NULL(hw)) { + rc = PTR_ERR(hw); + DPU_ERROR("failed dspp object creation: err %d\n", rc); + goto fail; + } + rm->dspp_blks[dspp->id - DSPP_0] = &hw->base; + } + return 0; fail: @@ -222,12 +240,17 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx, * if lm, and all other hardwired blocks connected to the lm (pp) is * available and appropriate * @pp_idx: output parameter, index of pingpong block attached to the layer - * mixer in rm->pongpong_blks[]. + * mixer in rm->pingpong_blks[]. + * @dspp_idx: output parameter, index of dspp block attached to the layer + * mixer in rm->dspp_blks[]. + * @reqs: input parameter, rm requirements for HW blocks needed in the + * datapath. * @Return: true if lm matches all requirements, false otherwise */ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, struct dpu_global_state *global_state, - uint32_t enc_id, int lm_idx, int *pp_idx) + uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx, + struct dpu_rm_requirements *reqs) { const struct dpu_lm_cfg *lm_cfg; int idx; @@ -251,6 +274,23 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, return false; } *pp_idx = idx; + + if (!reqs->topology.num_dspp) + return true; + + idx = lm_cfg->dspp - DSPP_0; + if (idx < 0 || idx >= ARRAY_SIZE(rm->dspp_blks)) { + DPU_ERROR("failed to get dspp on lm %d\n", lm_cfg->dspp); + return false; + } + + if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) { + DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id, + lm_cfg->dspp); + return false; + } + *dspp_idx = idx; + return true; } @@ -262,6 +302,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, { int lm_idx[MAX_BLOCKS]; int pp_idx[MAX_BLOCKS]; + int dspp_idx[MAX_BLOCKS] = {0}; int i, j, lm_count = 0; if (!reqs->topology.num_lm) { @@ -279,7 +320,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, lm_idx[lm_count] = i; if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, - enc_id, i, &pp_idx[lm_count])) { + enc_id, i, &pp_idx[lm_count], + &dspp_idx[lm_count], reqs)) { continue; } @@ -299,7 +341,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state, enc_id, j, - &pp_idx[lm_count])) { + &pp_idx[lm_count], &dspp_idx[lm_count], + reqs)) { continue; } @@ -316,6 +359,8 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, for (i = 0; i < lm_count; i++) { global_state->mixer_to_enc_id[lm_idx[i]] = enc_id; global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id; + global_state->dspp_to_enc_id[dspp_idx[i]] = + reqs->topology.num_dspp ? enc_id : 0; trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id, pp_idx[i] + PINGPONG_0); @@ -560,6 +605,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, hw_to_enc_id = global_state->intf_to_enc_id; max_blks = ARRAY_SIZE(rm->intf_blks); break; + case DPU_HW_BLK_DSPP: + hw_blks = rm->dspp_blks; + hw_to_enc_id = global_state->dspp_to_enc_id; + max_blks = ARRAY_SIZE(rm->dspp_blks); + break; default: DPU_ERROR("blk type %d not managed by rm\n", type); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 6d2b04f306f0..08726bb1063a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -19,6 +19,7 @@ struct dpu_global_state; * @mixer_blks: array of layer mixer hardware resources * @ctl_blks: array of ctl hardware resources * @intf_blks: array of intf hardware resources + * @dspp_blks: array of dspp hardware resources * @lm_max_width: cached layer mixer maximum width * @rm_lock: resource manager mutex */ @@ -27,6 +28,7 @@ struct dpu_rm { struct dpu_hw_blk *mixer_blks[LM_MAX - LM_0]; struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0]; struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0]; + struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0]; uint32_t lm_max_width; }; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 194d900a460e..0ab49aa781a3 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -105,6 +105,7 @@ struct msm_display_topology { u32 num_lm; u32 num_enc; u32 num_intf; + u32 num_dspp; }; /** -- cgit v1.2.3 From 4259ff7ae509ed880b3a7bb685972c3a3bf4b74b Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Tue, 24 Mar 2020 15:31:19 +0530 Subject: drm/msm/dpu: add support for pcc color block in dpu driver This change adds support for color correction sub block for SC7180 device. Signed-off-by: Kalyan Thota Tested-by: Fritz Koenig Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 77 ++++++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 49 +++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h | 33 ++++++++++- 4 files changed, 164 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index cf3af731a324..e15b42a780e0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,7 @@ #include "dpu_kms.h" #include "dpu_hw_lm.h" #include "dpu_hw_ctl.h" +#include "dpu_hw_dspp.h" #include "dpu_crtc.h" #include "dpu_plane.h" #include "dpu_encoder.h" @@ -40,6 +42,9 @@ /* timeout in ms waiting for frame done */ #define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60 +#define CONVERT_S3_15(val) \ + (((((u64)val) & ~BIT_ULL(63)) >> 17) & GENMASK_ULL(17, 0)) + static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv = crtc->dev->dev_private; @@ -420,6 +425,74 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, drm_mode_debug_printmodeline(adj_mode); } +static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state, + struct dpu_hw_pcc_cfg *cfg) +{ + struct drm_color_ctm *ctm; + + memset(cfg, 0, sizeof(struct dpu_hw_pcc_cfg)); + + ctm = (struct drm_color_ctm *)state->ctm->data; + + if (!ctm) + return; + + cfg->r.r = CONVERT_S3_15(ctm->matrix[0]); + cfg->g.r = CONVERT_S3_15(ctm->matrix[1]); + cfg->b.r = CONVERT_S3_15(ctm->matrix[2]); + + cfg->r.g = CONVERT_S3_15(ctm->matrix[3]); + cfg->g.g = CONVERT_S3_15(ctm->matrix[4]); + cfg->b.g = CONVERT_S3_15(ctm->matrix[5]); + + cfg->r.b = CONVERT_S3_15(ctm->matrix[6]); + cfg->g.b = CONVERT_S3_15(ctm->matrix[7]); + cfg->b.b = CONVERT_S3_15(ctm->matrix[8]); +} + +static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) +{ + struct drm_crtc_state *state = crtc->state; + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); + struct dpu_crtc_mixer *mixer = cstate->mixers; + struct dpu_hw_pcc_cfg cfg; + struct dpu_hw_ctl *ctl; + struct dpu_hw_mixer *lm; + struct dpu_hw_dspp *dspp; + int i; + + + if (!state->color_mgmt_changed) + return; + + for (i = 0; i < cstate->num_mixers; i++) { + ctl = mixer[i].lm_ctl; + lm = mixer[i].hw_lm; + dspp = mixer[i].hw_dspp; + + if (!dspp || !dspp->ops.setup_pcc) + continue; + + if (!state->ctm) { + dspp->ops.setup_pcc(dspp, NULL); + } else { + _dpu_crtc_get_pcc_coeff(state, &cfg); + dspp->ops.setup_pcc(dspp, &cfg); + } + + mixer[i].flush_mask |= ctl->ops.get_bitmask_dspp(ctl, + mixer[i].hw_dspp->idx); + + /* stage config flush mask */ + ctl->ops.update_pending_flush(ctl, mixer[i].flush_mask); + + DPU_DEBUG("lm %d, ctl %d, flush mask 0x%x\n", + mixer[i].hw_lm->idx - DSPP_0, + ctl->idx - CTL_0, + mixer[i].flush_mask); + } +} + static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -471,6 +544,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, _dpu_crtc_blend_setup(crtc); + _dpu_crtc_setup_cp_blocks(crtc); + /* * PP_DONE irq is only used by command mode for now. * It is better to request pending before FLUSH and START trigger @@ -1301,6 +1376,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane, drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs); + drm_crtc_enable_color_mgmt(crtc, 0, true, 0); + /* save user friendly CRTC name for later */ snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 19d065ad0b25..731b4fbbf647 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -41,7 +41,7 @@ #define PINGPONG_SDM845_SPLIT_MASK \ (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) -#define DSPP_SC7180_MASK 0 +#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC) #define DEFAULT_PIXEL_RAM_SIZE (50 * 1024) #define DEFAULT_DPU_LINE_WIDTH 2048 @@ -339,12 +339,17 @@ static const struct dpu_lm_cfg sc7180_lm[] = { /************************************************************* * DSPP sub blocks config *************************************************************/ +static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = { + .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700, + .len = 0x90, .version = 0x10000}, +}; + #define DSPP_BLK(_name, _id, _base) \ {\ .name = _name, .id = _id, \ .base = _base, .len = 0x1800, \ .features = DSPP_SC7180_MASK, \ - .sblk = NULL, \ + .sblk = &sc7180_dspp_sblk \ } static const struct dpu_dspp_cfg sc7180_dspp[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index 75c82e92bd2a..b5189cece3c6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -9,10 +9,57 @@ #include "dpu_kms.h" +/* DSPP_PCC */ +#define PCC_EN BIT(0) +#define PCC_DIS 0 +#define PCC_RED_R_OFF 0x10 +#define PCC_RED_G_OFF 0x1C +#define PCC_RED_B_OFF 0x28 +#define PCC_GREEN_R_OFF 0x14 +#define PCC_GREEN_G_OFF 0x20 +#define PCC_GREEN_B_OFF 0x2C +#define PCC_BLUE_R_OFF 0x18 +#define PCC_BLUE_G_OFF 0x24 +#define PCC_BLUE_B_OFF 0x30 + +void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, + struct dpu_hw_pcc_cfg *cfg) +{ + + u32 base = ctx->cap->sblk->pcc.base; + + if (!ctx || !base) { + DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base); + return; + } + + if (!cfg) { + DRM_DEBUG_DRIVER("disable pcc feature\n"); + DPU_REG_WRITE(&ctx->hw, base, PCC_DIS); + return; + } + + DPU_REG_WRITE(&ctx->hw, base + PCC_RED_R_OFF, cfg->r.r); + DPU_REG_WRITE(&ctx->hw, base + PCC_RED_G_OFF, cfg->r.g); + DPU_REG_WRITE(&ctx->hw, base + PCC_RED_B_OFF, cfg->r.b); + + DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_R_OFF, cfg->g.r); + DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_G_OFF, cfg->g.g); + DPU_REG_WRITE(&ctx->hw, base + PCC_GREEN_B_OFF, cfg->g.b); + + DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_R_OFF, cfg->b.r); + DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_G_OFF, cfg->b.g); + DPU_REG_WRITE(&ctx->hw, base + PCC_BLUE_B_OFF, cfg->b.b); + + DPU_REG_WRITE(&ctx->hw, base, PCC_EN); +} + static void _setup_dspp_ops(struct dpu_hw_dspp *c, unsigned long features) { - return; + if (test_bit(DPU_DSPP_PCC, &features) && + IS_SC7180_TARGET(c->hw.hwversion)) + c->ops.setup_pcc = dpu_setup_dspp_pcc; } static const struct dpu_dspp_cfg *_dspp_offset(enum dpu_dspp dspp, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h index 09807ea3f0fd..7fa189cfcb06 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h @@ -9,14 +9,45 @@ struct dpu_hw_dspp; +/** + * struct dpu_hw_pcc_coeff - PCC coefficient structure for each color + * component. + * @r: red coefficient. + * @g: green coefficient. + * @b: blue coefficient. + */ + +struct dpu_hw_pcc_coeff { + __u32 r; + __u32 g; + __u32 b; +}; + +/** + * struct dpu_hw_pcc - pcc feature structure + * @r: red coefficients. + * @g: green coefficients. + * @b: blue coefficients. + */ +struct dpu_hw_pcc_cfg { + struct dpu_hw_pcc_coeff r; + struct dpu_hw_pcc_coeff g; + struct dpu_hw_pcc_coeff b; +}; + /** * struct dpu_hw_dspp_ops - interface to the dspp hardware driver functions * Caller must call the init function to get the dspp context for each dspp * Assumption is these functions will be called after clocks are enabled */ struct dpu_hw_dspp_ops { + /** + * setup_pcc - setup dspp pcc + * @ctx: Pointer to dspp context + * @cfg: Pointer to configuration + */ + void (*setup_pcc)(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg); - void (*dummy)(struct dpu_hw_dspp *ctx); }; /** -- cgit v1.2.3 From 04d9044f6c577948609c03b4e33b8fbc8b87c4b1 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Wed, 1 Apr 2020 14:18:18 +0530 Subject: drm/msm/dpu: add support for clk and bw scaling for display This change adds support to scale src clk and bandwidth as per composition requirements. Interconnect registration for bw has been moved to mdp device node from mdss to facilitate the scaling. Signed-off-by: Kalyan Thota Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 106 +++++++++++++++++++++---- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 37 ++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 82 +++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 + 8 files changed, 228 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 11f2bebe3869..24874f62de13 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -29,6 +29,73 @@ enum dpu_perf_mode { DPU_PERF_MODE_MAX }; +/** + * @_dpu_core_perf_calc_bw() - to calculate BW per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * Return: returns aggregated BW for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms, + struct drm_crtc *crtc) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + u64 crtc_plane_bw = 0; + u32 bw_factor; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); + + if (!pstate) + continue; + + crtc_plane_bw += pstate->plane_fetch_bw; + } + + bw_factor = kms->catalog->perf.bw_inefficiency_factor; + if (bw_factor) + crtc_plane_bw = mult_frac(crtc_plane_bw, bw_factor, 100); + + return crtc_plane_bw; +} + +/** + * _dpu_core_perf_calc_clk() - to calculate clock per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * @state - pointer to a crtc state + * Return: returns max clk for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms, + struct drm_crtc *crtc, struct drm_crtc_state *state) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + u64 crtc_clk; + u32 clk_factor; + + mode = &state->adjusted_mode; + + crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); + + if (!pstate) + continue; + + crtc_clk = max(pstate->plane_clk, crtc_clk); + } + + clk_factor = kms->catalog->perf.clk_inefficiency_factor; + if (clk_factor) + crtc_clk = mult_frac(crtc_clk, clk_factor, 100); + + return crtc_clk; +} + + static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -67,12 +134,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate = to_dpu_crtc_state(state); memset(perf, 0, sizeof(struct dpu_core_perf_params)); - if (!dpu_cstate->bw_control) { - perf->bw_ctl = kms->catalog->perf.max_bw_high * - 1000ULL; - perf->max_per_pipe_ib = perf->bw_ctl; - perf->core_clk_rate = kms->perf.max_core_clk_rate; - } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { + if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { perf->bw_ctl = 0; perf->max_per_pipe_ib = 0; perf->core_clk_rate = 0; @@ -80,6 +142,10 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, perf->bw_ctl = kms->perf.fix_core_ab_vote; perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote; perf->core_clk_rate = kms->perf.fix_core_clk_rate; + } else { + perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc); + perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib; + perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state); } DPU_DEBUG( @@ -132,11 +198,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n", tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, tmp_cstate->bw_control); - /* - * For bw check only use the bw if the - * atomic property has been already set - */ - if (tmp_cstate->bw_control) + bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } @@ -152,9 +214,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("final threshold bw limit = %d\n", threshold); - if (!dpu_cstate->bw_control) { - DPU_DEBUG("bypass bandwidth check\n"); - } else if (!threshold) { + if (!threshold) { DPU_ERROR("no bandwidth limits specified\n"); return -E2BIG; } else if (bw > threshold) { @@ -175,7 +235,8 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; - int ret = 0; + int i, ret = 0; + u64 avg_bw; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (tmp_crtc->enabled && @@ -186,10 +247,21 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, dpu_cstate->new_perf.max_per_pipe_ib); - DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl); + perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + + DPU_DEBUG("crtc=%d bw=%llu paths:%d\n", + tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl, kms->num_paths); } } + + avg_bw = kms->num_paths ? + perf.bw_ctl / kms->num_paths : 0; + + for (i = 0; i < kms->num_paths; i++) + icc_set_bw(kms->path[i], + Bps_to_icc(avg_bw), (perf.max_per_pipe_ib)); + return ret; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 731b4fbbf647..cc8bf06781c0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -541,7 +541,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { .max_bw_high = 5500000, .min_core_ib = 2400000, .min_llcc_ib = 800000, - .min_dram_ib = 800000, + .min_dram_ib = 1600000, + .min_prefill_lines = 24, .danger_lut_tbl = {0xff, 0xffff, 0x0}, .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc7180_qos_linear), @@ -558,6 +559,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { {.rd_enable = 1, .wr_enable = 1}, {.rd_enable = 1, .wr_enable = 0} }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, }; /************************************************************* diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index f7de43838c69..f2a5fe2d9d62 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -651,6 +651,8 @@ struct dpu_perf_cdp_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines + * @clk_inefficiency_factor DPU src clock inefficiency factor + * @bw_inefficiency_factor DPU axi bus bw inefficiency factor * @safe_lut_tbl: LUT tables for safe signals * @danger_lut_tbl: LUT tables for danger signals * @qos_lut_tbl: LUT tables for QoS signals @@ -675,6 +677,8 @@ struct dpu_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; + u32 clk_inefficiency_factor; + u32 bw_inefficiency_factor; u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ce19f1d39367..10c33cf7a5d7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -303,6 +303,28 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) return 0; } +static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) +{ + struct icc_path *path0; + struct icc_path *path1; + struct drm_device *dev = dpu_kms->dev; + + path0 = of_icc_get(dev->dev, "mdp0-mem"); + path1 = of_icc_get(dev->dev, "mdp1-mem"); + + if (IS_ERR_OR_NULL(path0)) + return PTR_ERR_OR_ZERO(path0); + + dpu_kms->path[0] = path0; + dpu_kms->num_paths = 1; + + if (!IS_ERR_OR_NULL(path1)) { + dpu_kms->path[1] = path1; + dpu_kms->num_paths++; + } + return 0; +} + static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) { return dpu_crtc_vblank(crtc, true); @@ -980,6 +1002,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_vbif_init_memtypes(dpu_kms); + if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) + dpu_kms_parse_data_bus_icc_path(dpu_kms); + pm_runtime_put_sync(&dpu_kms->pdev->dev); return 0; @@ -1085,7 +1110,7 @@ static int dpu_dev_remove(struct platform_device *pdev) static int __maybe_unused dpu_runtime_suspend(struct device *dev) { - int rc = -1; + int i, rc = -1; struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp; @@ -1094,6 +1119,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, 0); + return rc; } @@ -1105,8 +1133,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) struct drm_encoder *encoder; struct drm_device *ddev; struct dss_module_power *mp = &dpu_kms->mp; + int i; ddev = dpu_kms->dev; + + /* Min vote of BW is required before turning on AXI clk */ + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, + dpu_kms->catalog->perf.min_dram_ib); + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) { DPU_ERROR("clock enable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 4e32d040f1e6..94410ca9bd70 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -8,6 +8,8 @@ #ifndef __DPU_KMS_H__ #define __DPU_KMS_H__ +#include + #include #include "msm_drv.h" @@ -137,6 +139,8 @@ struct dpu_kms { * when disabled. */ atomic_t bandwidth_ref; + struct icc_path *path[2]; + u32 num_paths; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 80d3cfc14007..df0a9835bfb1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -8,7 +8,6 @@ #include #include #include "dpu_kms.h" -#include #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base) @@ -315,9 +314,11 @@ int dpu_mdss_init(struct drm_device *dev) } dpu_mdss->mmio_len = resource_size(res); - ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); - if (ret) - return ret; + if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) { + ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); + if (ret) + return ret; + } mp = &dpu_mdss->mp; ret = msm_dss_parse_clock(pdev, mp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 3b9c33e694bf..c2a6e3dacd68 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -131,6 +131,84 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) return to_dpu_kms(priv->kms); } +/** + * _dpu_plane_calc_bw - calculate bandwidth required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated bandwidth in the plane state. + * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) + * Prefill BW Equation: line src bytes * line_time + */ +static void _dpu_plane_calc_bw(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + const struct dpu_format *fmt = NULL; + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + int src_width, src_height, dst_height, fps; + u64 plane_prefill_bw; + u64 plane_bw; + u32 hw_latency_lines; + u32 scale_factor; + int vbp, vpw; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); + + src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect); + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + vbp = mode->vtotal - mode->vsync_end; + vpw = mode->vsync_end - mode->vsync_start; + hw_latency_lines = dpu_kms->catalog->perf.min_prefill_lines; + scale_factor = src_height > dst_height ? + mult_frac(src_height, 1, dst_height) : 1; + + plane_bw = + src_width * mode->vtotal * fps * fmt->bpp * scale_factor; + + plane_prefill_bw = + src_width * hw_latency_lines * fps * fmt->bpp * scale_factor; + + plane_prefill_bw = mult_frac(plane_prefill_bw, mode->vtotal, (vbp+vpw)); + + pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw); +} + + +/** + * _dpu_plane_calc_clk - calculate clock required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated clock in the plane state. + * Clock equation: dst_w * v_total * fps * (src_h / dst_h) + */ +static void _dpu_plane_calc_clk(struct drm_plane *plane) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + int dst_width, src_height, dst_height, fps; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + + pstate->plane_clk = + dst_width * mode->vtotal * fps; + + if (src_height > dst_height) + pstate->plane_clk = mult_frac(pstate->plane_clk, + src_height, dst_height); +} + /** * _dpu_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane @@ -1102,6 +1180,10 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) } _dpu_plane_set_qos_remap(plane); + + _dpu_plane_calc_bw(plane, fb); + + _dpu_plane_calc_clk(plane); } static void _dpu_plane_atomic_disable(struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 456949713e90..ca83b8753d59 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -25,6 +25,8 @@ * @scaler3_cfg: configuration data for scaler3 * @pixel_ext: configuration data for pixel extensions * @cdp_cfg: CDP configuration + * @plane_fetch_bw: calculated BW per plane + * @plane_clk: calculated clk per plane */ struct dpu_plane_state { struct drm_plane_state base; @@ -39,6 +41,8 @@ struct dpu_plane_state { struct dpu_hw_pixel_ext pixel_ext; struct dpu_hw_pipe_cdp_cfg cdp_cfg; + u64 plane_fetch_bw; + u64 plane_clk; }; /** -- cgit v1.2.3 From 71dc6c08e4c53d37e3756502b1793f440f4d4030 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Mon, 4 May 2020 19:01:03 +0530 Subject: drm/msm/dpu: update bandwidth threshold check Maximum allowed bandwidth has no dependency on the type of panel used. Hence, cleanup the code to use max_bw_high as the threshold value for bandwidth checks. Update the maximum allowed bandwidth as 6.8Gbps for SC7180 target. Signed-off-by: Krishna Manikandan Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 23 +---------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++-- 2 files changed, 3 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 24874f62de13..9697abcbec3f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -103,22 +103,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) return to_dpu_kms(priv->kms); } -static bool _dpu_core_video_mode_intf_connected(struct drm_crtc *crtc) -{ - struct drm_crtc *tmp_crtc; - - drm_for_each_crtc(tmp_crtc, crtc->dev) { - if ((dpu_crtc_get_intf_mode(tmp_crtc) == INTF_MODE_VIDEO) && - tmp_crtc->enabled) { - DPU_DEBUG("video interface connected crtc:%d\n", - tmp_crtc->base.id); - return true; - } - } - - return false; -} - static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, struct drm_crtc *crtc, struct drm_crtc_state *state, @@ -160,7 +144,6 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, u32 bw, threshold; u64 bw_sum_of_intfs = 0; enum dpu_crtc_client_type curr_client_type; - bool is_video_mode; struct dpu_crtc_state *dpu_cstate; struct drm_crtc *tmp_crtc; struct dpu_kms *kms; @@ -206,11 +189,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, bw = DIV_ROUND_UP_ULL(bw_sum_of_intfs, 1000); DPU_DEBUG("calculated bandwidth=%uk\n", bw); - is_video_mode = dpu_crtc_get_intf_mode(crtc) == INTF_MODE_VIDEO; - threshold = (is_video_mode || - _dpu_core_video_mode_intf_connected(crtc)) ? - kms->catalog->perf.max_bw_low : - kms->catalog->perf.max_bw_high; + threshold = kms->catalog->perf.max_bw_high; DPU_DEBUG("final threshold bw limit = %d\n", threshold); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index cc8bf06781c0..8f2357d9960a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -537,8 +537,8 @@ static const struct dpu_perf_cfg sdm845_perf_data = { }; static const struct dpu_perf_cfg sc7180_perf_data = { - .max_bw_low = 3900000, - .max_bw_high = 5500000, + .max_bw_low = 6800000, + .max_bw_high = 6800000, .min_core_ib = 2400000, .min_llcc_ib = 800000, .min_dram_ib = 1600000, -- cgit v1.2.3 From eadf79286a4badebc95af7061530bdb50a7e6f38 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 1 May 2020 13:43:26 -0600 Subject: drm/msm: Check for powered down HW in the devfreq callbacks Writing to the devfreq sysfs nodes while the GPU is powered down can result in a system crash (on a5xx) or a nasty GMU error (on a6xx): $ /sys/class/devfreq/5000000.gpu# echo 500000000 > min_freq [ 104.841625] platform 506a000.gmu: [drm:a6xx_gmu_set_oob] *ERROR* Timeout waiting for GMU OOB set GPU_DCVS: 0x0 Despite the fact that we carefully try to suspend the devfreq device when the hardware is powered down there are lots of holes in the governors that don't check for the suspend state and blindly call into the devfreq callbacks that end up triggering hardware reads in the GPU driver. Call pm_runtime_get_if_in_use() in the gpu_busy() and gpu_set_freq() callbacks to skip the hardware access if it isn't active. v3: Only check pm_runtime_get_if_in_use() for == 0 per Eric Anholt v2: Use pm_runtime_get_if_in_use() per Eric Anholt Cc: stable@vger.kernel.org Reviewed-by: Eric Anholt Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 6 ++++++ drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 8 ++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++++++ 3 files changed, 21 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 724024a2243a..662d02289533 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1404,6 +1404,10 @@ static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu) { u64 busy_cycles, busy_time; + /* Only read the gpu busy if the hardware is already active */ + if (pm_runtime_get_if_in_use(&gpu->pdev->dev) == 0) + return 0; + busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO, REG_A5XX_RBBM_PERFCTR_RBBM_0_HI); @@ -1412,6 +1416,8 @@ static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu) gpu->devfreq.busy_cycles = busy_cycles; + pm_runtime_put(&gpu->pdev->dev); + if (WARN_ON(busy_time > ~0LU)) return ~0LU; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 40cb4535d554..b4aa93710409 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -108,6 +108,13 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) struct msm_gpu *gpu = &adreno_gpu->base; int ret; + /* + * This can get called from devfreq while the hardware is idle. Don't + * bring up the power if it isn't already active + */ + if (pm_runtime_get_if_in_use(gmu->dev) == 0) + return; + gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, @@ -134,6 +141,7 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) * for now leave it at max so that the performance is nominal. */ icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216)); + pm_runtime_put(gmu->dev); } void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 68af24150de5..2c09d2c21773 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -810,6 +810,11 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); u64 busy_cycles, busy_time; + + /* Only read the gpu busy if the hardware is already active */ + if (pm_runtime_get_if_in_use(a6xx_gpu->gmu.dev) == 0) + return 0; + busy_cycles = gmu_read64(&a6xx_gpu->gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); @@ -819,6 +824,8 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) gpu->devfreq.busy_cycles = busy_cycles; + pm_runtime_put(a6xx_gpu->gmu.dev); + if (WARN_ON(busy_time > ~0LU)) return ~0LU; -- cgit v1.2.3 From d3b8877e57247c628966b155c02b4ed2e61b88f2 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:13 -0400 Subject: drm/msm: add msm_gem_get_and_pin_iova_range This function allows pinning iova to a specific page range (for a6xx GMU). Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.h | 6 +++++- drivers/gpu/drm/msm/msm_gem.c | 28 +++++++++++++++++++++------- drivers/gpu/drm/msm/msm_gem_vma.c | 6 ++++-- 3 files changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 0ab49aa781a3..108202c35637 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -237,7 +237,8 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc); void msm_crtc_disable_vblank(struct drm_crtc *crtc); int msm_gem_init_vma(struct msm_gem_address_space *aspace, - struct msm_gem_vma *vma, int npages); + struct msm_gem_vma *vma, int npages, + u64 range_start, u64 range_end); void msm_gem_purge_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma); void msm_gem_unmap_vma(struct msm_gem_address_space *aspace, @@ -277,6 +278,9 @@ vm_fault_t msm_gem_fault(struct vm_fault *vmf); uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); int msm_gem_get_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace, uint64_t *iova); +int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj, + struct msm_gem_address_space *aspace, uint64_t *iova, + u64 range_start, u64 range_end); int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, struct msm_gem_address_space *aspace, uint64_t *iova); uint64_t msm_gem_iova(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 5a6a79fbc9d6..d8f56a34c117 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -389,7 +389,8 @@ put_iova(struct drm_gem_object *obj) } static int msm_gem_get_iova_locked(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova) + struct msm_gem_address_space *aspace, uint64_t *iova, + u64 range_start, u64 range_end) { struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_vma *vma; @@ -404,7 +405,8 @@ static int msm_gem_get_iova_locked(struct drm_gem_object *obj, if (IS_ERR(vma)) return PTR_ERR(vma); - ret = msm_gem_init_vma(aspace, vma, obj->size >> PAGE_SHIFT); + ret = msm_gem_init_vma(aspace, vma, obj->size >> PAGE_SHIFT, + range_start, range_end); if (ret) { del_vma(vma); return ret; @@ -443,9 +445,13 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, msm_obj->sgt, obj->size >> PAGE_SHIFT); } -/* get iova and pin it. Should have a matching put */ -int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, - struct msm_gem_address_space *aspace, uint64_t *iova) +/* + * get iova and pin it. Should have a matching put + * limits iova to specified range (in pages) + */ +int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj, + struct msm_gem_address_space *aspace, uint64_t *iova, + u64 range_start, u64 range_end) { struct msm_gem_object *msm_obj = to_msm_bo(obj); u64 local; @@ -453,7 +459,8 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, mutex_lock(&msm_obj->lock); - ret = msm_gem_get_iova_locked(obj, aspace, &local); + ret = msm_gem_get_iova_locked(obj, aspace, &local, + range_start, range_end); if (!ret) ret = msm_gem_pin_iova(obj, aspace); @@ -465,6 +472,13 @@ int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, return ret; } +/* get iova and pin it. Should have a matching put */ +int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, + struct msm_gem_address_space *aspace, uint64_t *iova) +{ + return msm_gem_get_and_pin_iova_range(obj, aspace, iova, 0, U64_MAX); +} + /* * Get an iova but don't pin it. Doesn't need a put because iovas are currently * valid for the life of the object @@ -476,7 +490,7 @@ int msm_gem_get_iova(struct drm_gem_object *obj, int ret; mutex_lock(&msm_obj->lock); - ret = msm_gem_get_iova_locked(obj, aspace, iova); + ret = msm_gem_get_iova_locked(obj, aspace, iova, 0, U64_MAX); mutex_unlock(&msm_obj->lock); return ret; diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 1af5354bcd46..407b7ab82818 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -103,7 +103,8 @@ void msm_gem_close_vma(struct msm_gem_address_space *aspace, /* Initialize a new vma and allocate an iova for it */ int msm_gem_init_vma(struct msm_gem_address_space *aspace, - struct msm_gem_vma *vma, int npages) + struct msm_gem_vma *vma, int npages, + u64 range_start, u64 range_end) { int ret; @@ -111,7 +112,8 @@ int msm_gem_init_vma(struct msm_gem_address_space *aspace, return -EBUSY; spin_lock(&aspace->lock); - ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages); + ret = drm_mm_insert_node_in_range(&aspace->mm, &vma->node, npages, 0, + 0, range_start, range_end, 0); spin_unlock(&aspace->lock); if (ret) -- cgit v1.2.3 From 0b462d7a71c07e96b8f02cbc2d134fdc6e80ef34 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:14 -0400 Subject: drm/msm: add internal MSM_BO_MAP_PRIV flag This flag sets IOMMU_PRIV, which is required for some a6xx GMU objects. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem.c | 3 +++ drivers/gpu/drm/msm/msm_gem.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index d8f56a34c117..6277fde13df9 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -428,6 +428,9 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj, if (!(msm_obj->flags & MSM_BO_GPU_READONLY)) prot |= IOMMU_WRITE; + if (msm_obj->flags & MSM_BO_MAP_PRIV) + prot |= IOMMU_PRIV; + WARN_ON(!mutex_is_locked(&msm_obj->lock)); if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 30584eaf8cc8..972490b14ba5 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -13,6 +13,7 @@ /* Additional internal-use only BO flags: */ #define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */ +#define MSM_BO_MAP_PRIV 0x20000000 /* use IOMMU_PRIV when mapping */ struct msm_gem_address_space { const char *name; -- cgit v1.2.3 From 29ac8979cdf7205bf70ec9be60bd2442acc0422a Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:15 -0400 Subject: drm/msm/a6xx: use msm_gem for GMU memory objects This gives more fine-grained control over how memory is allocated over the DMA api. In particular, it allows using an address range or pinning to a fixed address. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 115 +++++++++++++++++++++++----------- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 9 ++- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 6 +- 3 files changed, 88 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index b4aa93710409..28c825d44f40 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -2,14 +2,16 @@ /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */ #include -#include #include #include #include #include +#include #include "a6xx_gpu.h" #include "a6xx_gmu.xml.h" +#include "msm_gem.h" +#include "msm_mmu.h" static void a6xx_gmu_fault(struct a6xx_gmu *gmu) { @@ -628,7 +630,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) gmu_write(gmu, REG_A6XX_GMU_CM3_BOOT_CONFIG, 0x02); /* Write the iova of the HFI table */ - gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi->iova); + gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi.iova); gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_INFO, 1); gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0, @@ -927,34 +929,77 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) return 0; } -static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo) +static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu) { - if (IS_ERR_OR_NULL(bo)) - return; + msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace, false); + msm_gem_kernel_put(gmu->debug.obj, gmu->aspace, false); + + gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu); + msm_gem_address_space_put(gmu->aspace); +} + +static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, + size_t size, u64 iova) +{ + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct drm_device *dev = a6xx_gpu->base.base.dev; + uint32_t flags = MSM_BO_WC; + u64 range_start, range_end; + int ret; + + size = PAGE_ALIGN(size); + if (!iova) { + /* no fixed address - use GMU's uncached range */ + range_start = 0x60000000; + range_end = 0x80000000; + } else { + /* range for fixed address */ + range_start = iova; + range_end = iova + size; + } + + bo->obj = msm_gem_new(dev, size, flags); + if (IS_ERR(bo->obj)) + return PTR_ERR(bo->obj); - dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova); - kfree(bo); + ret = msm_gem_get_and_pin_iova_range(bo->obj, gmu->aspace, &bo->iova, + range_start >> PAGE_SHIFT, range_end >> PAGE_SHIFT); + if (ret) { + drm_gem_object_put(bo->obj); + return ret; + } + + bo->virt = msm_gem_get_vaddr(bo->obj); + bo->size = size; + + return 0; } -static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, - size_t size) +static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) { - struct a6xx_gmu_bo *bo; + struct iommu_domain *domain; + int ret; - bo = kzalloc(sizeof(*bo), GFP_KERNEL); - if (!bo) - return ERR_PTR(-ENOMEM); + domain = iommu_domain_alloc(&platform_bus_type); + if (!domain) + return -ENODEV; - bo->size = PAGE_ALIGN(size); + domain->geometry.aperture_start = 0x00000000; + domain->geometry.aperture_end = 0x7fffffff; - bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL); + gmu->aspace = msm_gem_address_space_create(gmu->dev, domain, "gmu"); + if (IS_ERR(gmu->aspace)) { + iommu_domain_free(domain); + return PTR_ERR(gmu->aspace); + } - if (!bo->virt) { - kfree(bo); - return ERR_PTR(-ENOMEM); + ret = gmu->aspace->mmu->funcs->attach(gmu->aspace->mmu); + if (ret) { + msm_gem_address_space_put(gmu->aspace); + return ret; } - return bo; + return 0; } /* Return the 'arc-level' for the given frequency */ @@ -1212,7 +1257,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) iounmap(gmu->mmio); gmu->mmio = NULL; - a6xx_gmu_memory_free(gmu, gmu->hfi); + a6xx_gmu_memory_free(gmu); free_irq(gmu->gmu_irq, gmu); free_irq(gmu->hfi_irq, gmu); @@ -1234,15 +1279,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) gmu->dev = &pdev->dev; - /* Pass force_dma false to require the DT to set the dma region */ - ret = of_dma_configure(gmu->dev, node, false); - if (ret) - return ret; - - /* Set the mask after the of_dma_configure() */ - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31)); - if (ret) - return ret; + of_dma_configure(gmu->dev, node, true); /* Fow now, don't do anything fancy until we get our feet under us */ gmu->idle_level = GMU_IDLE_STATE_ACTIVE; @@ -1254,20 +1291,26 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (ret) goto err_put_device; + ret = a6xx_gmu_memory_probe(gmu); + if (ret) + goto err_put_device; + /* Allocate memory for for the HFI queues */ - gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K); - if (IS_ERR(gmu->hfi)) + ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0); + if (ret) goto err_memory; /* Allocate memory for the GMU debug region */ - gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K); - if (IS_ERR(gmu->debug)) + ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0); + if (ret) goto err_memory; /* Map the GMU registers */ gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); - if (IS_ERR(gmu->mmio)) + if (IS_ERR(gmu->mmio)) { + ret = PTR_ERR(gmu->mmio); goto err_memory; + } /* Get the HFI and GMU interrupts */ gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq); @@ -1296,11 +1339,11 @@ err_mmio: iounmap(gmu->mmio); free_irq(gmu->gmu_irq, gmu); free_irq(gmu->hfi_irq, gmu); -err_memory: - a6xx_gmu_memory_free(gmu, gmu->hfi); ret = -ENODEV; +err_memory: + a6xx_gmu_memory_free(gmu); err_put_device: /* Drop reference taken in of_find_device_by_node */ put_device(gmu->dev); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 4af65a36d5ca..cd66a5e1d7e9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -10,9 +10,10 @@ #include "a6xx_hfi.h" struct a6xx_gmu_bo { + struct drm_gem_object *obj; void *virt; size_t size; - dma_addr_t iova; + u64 iova; }; /* @@ -43,6 +44,8 @@ struct a6xx_gmu_bo { struct a6xx_gmu { struct device *dev; + struct msm_gem_address_space *aspace; + void * __iomem mmio; int hfi_irq; @@ -52,8 +55,8 @@ struct a6xx_gmu { int idle_level; - struct a6xx_gmu_bo *hfi; - struct a6xx_gmu_bo *debug; + struct a6xx_gmu_bo hfi; + struct a6xx_gmu_bo debug; int nr_clocks; struct clk_bulk_data *clocks; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index e450e0b97211..b90343d4caf0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -176,8 +176,8 @@ static int a6xx_hfi_send_gmu_init(struct a6xx_gmu *gmu, int boot_state) { struct a6xx_hfi_msg_gmu_init_cmd msg = { 0 }; - msg.dbg_buffer_addr = (u32) gmu->debug->iova; - msg.dbg_buffer_size = (u32) gmu->debug->size; + msg.dbg_buffer_addr = (u32) gmu->debug.iova; + msg.dbg_buffer_size = (u32) gmu->debug.size; msg.boot_state = boot_state; return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_INIT, &msg, sizeof(msg), @@ -385,7 +385,7 @@ static void a6xx_hfi_queue_init(struct a6xx_hfi_queue *queue, void a6xx_hfi_init(struct a6xx_gmu *gmu) { - struct a6xx_gmu_bo *hfi = gmu->hfi; + struct a6xx_gmu_bo *hfi = &gmu->hfi; struct a6xx_hfi_queue_table_header *table = hfi->virt; struct a6xx_hfi_queue_header *headers = hfi->virt + sizeof(*table); u64 offset; -- cgit v1.2.3 From a83366ef19eaac14913ec89789638e32ee656480 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:16 -0400 Subject: drm/msm/a6xx: add A640/A650 to gpulist Add Adreno 640 and 650 GPU info to the gpulist. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_device.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 10 ++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index cb3a6e597d76..1156f72532a4 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -189,6 +189,30 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, .zapfw = "a630_zap.mdt", + }, { + .rev = ADRENO_REV(6, 4, 0, ANY_ID), + .revn = 640, + .name = "A640", + .fw = { + [ADRENO_FW_SQE] = "a630_sqe.fw", + [ADRENO_FW_GMU] = "a640_gmu.bin", + }, + .gmem = SZ_1M, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .init = a6xx_gpu_init, + .zapfw = "a640_zap.mdt", + }, { + .rev = ADRENO_REV(6, 5, 0, ANY_ID), + .revn = 650, + .name = "A650", + .fw = { + [ADRENO_FW_SQE] = "a650_sqe.fw", + [ADRENO_FW_GMU] = "a650_gmu.bin", + }, + .gmem = SZ_1M + SZ_128K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .init = a6xx_gpu_init, + .zapfw = "a650_zap.mdt", }, }; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 1d5c43c22269..a7647eaacc7a 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -197,7 +197,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) *value = adreno_gpu->gmem; return 0; case MSM_PARAM_GMEM_BASE: - *value = 0x100000; + *value = !adreno_is_a650(adreno_gpu) ? 0x100000 : 0; return 0; case MSM_PARAM_CHIP_ID: *value = adreno_gpu->rev.patchid | diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 9ff4e550e7bd..88ae1b2813ef 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -237,6 +237,16 @@ static inline int adreno_is_a630(struct adreno_gpu *gpu) return gpu->revn == 630; } +static inline int adreno_is_a640(struct adreno_gpu *gpu) +{ + return gpu->revn == 640; +} + +static inline int adreno_is_a650(struct adreno_gpu *gpu) +{ + return gpu->revn == 650; +} + int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value); const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname); -- cgit v1.2.3 From 8167e6fa76c8f7174dc9643f60c63bc083b35787 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:17 -0400 Subject: drm/msm/a6xx: HFI v2 for A640 and A650 Add HFI v2 code paths required by Adreno 640 and 650 GPUs. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 66 +++++++++++++++---- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 7 ++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 117 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/msm/adreno/a6xx_hfi.h | 50 ++++++++++++++- 5 files changed, 222 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 28c825d44f40..acffd61c374e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -136,8 +136,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) if (ret) dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret); - gmu->freq = gmu->gpu_freqs[index]; - /* * Eventually we will want to scale the path vote with the frequency but * for now leave it at max so that the performance is nominal. @@ -162,7 +160,12 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) gmu->current_perf_index = perf_index; - __a6xx_gmu_set_freq(gmu, perf_index); + if (gmu->legacy) + __a6xx_gmu_set_freq(gmu, perf_index); + else + a6xx_hfi_set_freq(gmu, perf_index); + + gmu->freq = gmu->gpu_freqs[perf_index]; } unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu) @@ -242,8 +245,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) switch (state) { case GMU_OOB_GPU_SET: - request = GMU_OOB_GPU_SET_REQUEST; - ack = GMU_OOB_GPU_SET_ACK; + if (gmu->legacy) { + request = GMU_OOB_GPU_SET_REQUEST; + ack = GMU_OOB_GPU_SET_ACK; + } else { + request = GMU_OOB_GPU_SET_REQUEST_NEW; + ack = GMU_OOB_GPU_SET_ACK_NEW; + } name = "GPU_SET"; break; case GMU_OOB_BOOT_SLUMBER: @@ -282,6 +290,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) /* Clear a pending OOB state in the GMU */ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { + if (!gmu->legacy) { + WARN_ON(state != GMU_OOB_GPU_SET); + gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, + 1 << GMU_OOB_GPU_SET_CLEAR_NEW); + return; + } + switch (state) { case GMU_OOB_GPU_SET: gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, @@ -304,6 +319,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu) int ret; u32 val; + if (!gmu->legacy) + return 0; + gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val, @@ -323,6 +341,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu) u32 val; int ret; + if (!gmu->legacy) + return; + /* Make sure retention is on */ gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11)); @@ -366,6 +387,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) if (gmu->idle_level < GMU_IDLE_STATE_SPTP) a6xx_sptprac_disable(gmu); + if (!gmu->legacy) { + ret = a6xx_hfi_send_prep_slumber(gmu); + goto out; + } + /* Tell the GMU to get ready to slumber */ gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1); @@ -381,6 +407,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) } } +out: /* Put fence into allow mode */ gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); return ret; @@ -650,9 +677,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) if (ret) return ret; - ret = a6xx_gmu_gfx_rail_on(gmu); - if (ret) - return ret; + if (gmu->legacy) { + ret = a6xx_gmu_gfx_rail_on(gmu); + if (ret) + return ret; + } /* Enable SPTP_PC if the CPU is responsible for it */ if (gmu->idle_level < GMU_IDLE_STATE_SPTP) { @@ -771,7 +800,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) enable_irq(gmu->hfi_irq); /* Set the GPU to the current freq */ - __a6xx_gmu_set_freq(gmu, gmu->current_perf_index); + if (gmu->legacy) + __a6xx_gmu_set_freq(gmu, gmu->current_perf_index); + else + a6xx_hfi_set_freq(gmu, gmu->current_perf_index); /* * "enable" the GX power domain which won't actually do anything but it @@ -1270,6 +1302,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) { + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct platform_device *pdev = of_find_device_by_node(node); int ret; @@ -1295,16 +1328,21 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (ret) goto err_put_device; + if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) { + /* HFI v1, has sptprac */ + gmu->legacy = true; + + /* Allocate memory for the GMU debug region */ + ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0); + if (ret) + goto err_memory; + } + /* Allocate memory for for the HFI queues */ ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0); if (ret) goto err_memory; - /* Allocate memory for the GMU debug region */ - ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0); - if (ret) - goto err_memory; - /* Map the GMU registers */ gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); if (IS_ERR(gmu->mmio)) { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index cd66a5e1d7e9..463e2d5f2bb9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -79,6 +79,7 @@ struct a6xx_gmu { bool initialized; bool hung; + bool legacy; /* a618 or a630 */ }; static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) @@ -159,10 +160,16 @@ enum a6xx_gmu_oob_state { #define GMU_OOB_GPU_SET_ACK 24 #define GMU_OOB_GPU_SET_CLEAR 24 +#define GMU_OOB_GPU_SET_REQUEST_NEW 30 +#define GMU_OOB_GPU_SET_ACK_NEW 31 +#define GMU_OOB_GPU_SET_CLEAR_NEW 31 + void a6xx_hfi_init(struct a6xx_gmu *gmu); int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state); void a6xx_hfi_stop(struct a6xx_gmu *gmu); +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu); +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index); bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu); bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 2c09d2c21773..20528ede63b6 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -566,8 +566,10 @@ out: */ a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); - /* Take the GMU out of its special boot mode */ - a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER); + if (a6xx_gpu->gmu.legacy) { + /* Take the GMU out of its special boot mode */ + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER); + } return ret; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index b90343d4caf0..f9db69e77121 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = { HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE), HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE), HFI_MSG_ID(HFI_H2F_MSG_TEST), + HFI_MSG_ID(HFI_H2F_MSG_START), + HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START), + HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE), + HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER), }; -static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data, - u32 dwords) +static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu, + struct a6xx_hfi_queue *queue, u32 *data, u32 dwords) { struct a6xx_hfi_queue_header *header = queue->header; u32 i, hdr, index = header->read_index; @@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data, index = (index + 1) % header->size; } + if (!gmu->legacy) + index = ALIGN(index, 4) % header->size; + header->read_index = index; return HFI_HEADER_SIZE(hdr); } @@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu, index = (index + 1) % header->size; } + /* Cookify any non used data at the end of the write buffer */ + if (!gmu->legacy) { + for (; index % 4; index = (index + 1) % header->size) + queue->data[index] = 0xfafafafa; + } + header->write_index = index; spin_unlock(&queue->lock); @@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum, struct a6xx_hfi_msg_response resp; /* Get the next packet */ - ret = a6xx_hfi_queue_read(queue, (u32 *) &resp, + ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp, sizeof(resp) >> 2); /* If the queue is empty our response never made it */ @@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version) version, sizeof(*version)); } +static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_msg_perf_table_v1 msg = { 0 }; + int i; + + msg.num_gpu_levels = gmu->nr_gpu_freqs; + msg.num_gmu_levels = gmu->nr_gmu_freqs; + + for (i = 0; i < gmu->nr_gpu_freqs; i++) { + msg.gx_votes[i].vote = gmu->gx_arc_votes[i]; + msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000; + } + + for (i = 0; i < gmu->nr_gmu_freqs; i++) { + msg.cx_votes[i].vote = gmu->cx_arc_votes[i]; + msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000; + } + + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg), + NULL, 0); +} + static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu) { struct a6xx_hfi_msg_perf_table msg = { 0 }; @@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu) for (i = 0; i < gmu->nr_gpu_freqs; i++) { msg.gx_votes[i].vote = gmu->gx_arc_votes[i]; + msg.gx_votes[i].acd = 0xffffffff; msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000; } @@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu) NULL, 0); } -int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) +int a6xx_hfi_send_start(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_msg_start msg = { 0 }; + + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg), + NULL, 0); +} + +int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_msg_core_fw_start msg = { 0 }; + + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg, + sizeof(msg), NULL, 0); +} + +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index) +{ + struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 }; + + msg.ack_type = 1; /* blocking */ + msg.freq = index; + msg.bw = 0; /* TODO: bus scaling */ + + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg, + sizeof(msg), NULL, 0); +} + +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu) +{ + struct a6xx_hfi_prep_slumber_cmd msg = { 0 }; + + /* TODO: should freq and bw fields be non-zero ? */ + + return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg, + sizeof(msg), NULL, 0); +} + +static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state) { int ret; @@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) * the GMU firmware */ - ret = a6xx_hfi_send_perf_table(gmu); + ret = a6xx_hfi_send_perf_table_v1(gmu); if (ret) return ret; @@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) return 0; } +int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) +{ + int ret; + + if (gmu->legacy) + return a6xx_hfi_start_v1(gmu, boot_state); + + + ret = a6xx_hfi_send_perf_table(gmu); + if (ret) + return ret; + + ret = a6xx_hfi_send_bw_table(gmu); + if (ret) + return ret; + + ret = a6xx_hfi_send_core_fw_start(gmu); + if (ret) + return ret; + + /* + * Downstream driver sends this in its "a6xx_hw_init" equivalent, + * but seems to be no harm in sending it here + */ + ret = a6xx_hfi_send_start(gmu); + if (ret) + return ret; + + return 0; +} + void a6xx_hfi_stop(struct a6xx_gmu *gmu) { int i; @@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu) /* GMU response queue */ offset += SZ_4K; a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset, - hfi->iova + offset, 4); + hfi->iova + offset, gmu->legacy ? 4 : 1); } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h index 60d1319fa44f..2bd670ca42d6 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h @@ -51,7 +51,8 @@ struct a6xx_hfi_queue { /* HFI message types */ #define HFI_MSG_CMD 0 -#define HFI_MSG_ACK 2 +#define HFI_MSG_ACK 1 +#define HFI_MSG_ACK_V1 2 #define HFI_F2H_MSG_ACK 126 @@ -94,7 +95,13 @@ struct perf_level { u32 freq; }; -struct a6xx_hfi_msg_perf_table { +struct perf_gx_level { + u32 vote; + u32 acd; + u32 freq; +}; + +struct a6xx_hfi_msg_perf_table_v1 { u32 header; u32 num_gpu_levels; u32 num_gmu_levels; @@ -103,6 +110,15 @@ struct a6xx_hfi_msg_perf_table { struct perf_level cx_votes[4]; }; +struct a6xx_hfi_msg_perf_table { + u32 header; + u32 num_gpu_levels; + u32 num_gmu_levels; + + struct perf_gx_level gx_votes[16]; + struct perf_level cx_votes[4]; +}; + #define HFI_H2F_MSG_BW_TABLE 3 struct a6xx_hfi_msg_bw_table { @@ -124,4 +140,34 @@ struct a6xx_hfi_msg_test { u32 header; }; +#define HFI_H2F_MSG_START 10 + +struct a6xx_hfi_msg_start { + u32 header; +}; + +#define HFI_H2F_MSG_CORE_FW_START 14 + +struct a6xx_hfi_msg_core_fw_start { + u32 header; + u32 handle; +}; + +#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30 + +struct a6xx_hfi_gx_bw_perf_vote_cmd { + u32 header; + u32 ack_type; + u32 freq; + u32 bw; +}; + +#define HFI_H2F_MSG_PREPARE_SLUMBER 33 + +struct a6xx_hfi_prep_slumber_cmd { + u32 header; + u32 bw; + u32 freq; +}; + #endif -- cgit v1.2.3 From c6ed04f856a4ebbbd8276ea871d8c98590abb0d0 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:18 -0400 Subject: drm/msm/a6xx: A640/A650 GMU firmware path Newer GPUs have different GMU firmware path. v3: updated a6xx_gmu_fw_load based on feedback, including gmu_write_bulk, and removed extra whitespace change Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 138 ++++++++++++++++++++++++++---- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 10 +++ drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 6 ++ 3 files changed, 138 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index acffd61c374e..749cec7c090e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -579,6 +579,8 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) { /* Disable GMU WB/RB buffer */ gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1); + gmu_write(gmu, REG_A6XX_GMU_ICACHE_CONFIG, 0x1); + gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1); gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400); @@ -608,14 +610,95 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE); } +struct block_header { + u32 addr; + u32 size; + u32 type; + u32 value; + u32 data[]; +}; + +/* this should be a general kernel helper */ +static int in_range(u32 addr, u32 start, u32 size) +{ + return addr >= start && addr < start + size; +} + +static bool fw_block_mem(struct a6xx_gmu_bo *bo, const struct block_header *blk) +{ + if (!in_range(blk->addr, bo->iova, bo->size)) + return false; + + memcpy(bo->virt + blk->addr - bo->iova, blk->data, blk->size); + return true; +} + +static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu) +{ + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + const struct firmware *fw_image = adreno_gpu->fw[ADRENO_FW_GMU]; + const struct block_header *blk; + u32 reg_offset; + + u32 itcm_base = 0x00000000; + u32 dtcm_base = 0x00040000; + + if (adreno_is_a650(adreno_gpu)) + dtcm_base = 0x10004000; + + if (gmu->legacy) { + /* Sanity check the size of the firmware that was loaded */ + if (fw_image->size > 0x8000) { + DRM_DEV_ERROR(gmu->dev, + "GMU firmware is bigger than the available region\n"); + return -EINVAL; + } + + gmu_write_bulk(gmu, REG_A6XX_GMU_CM3_ITCM_START, + (u32*) fw_image->data, fw_image->size); + return 0; + } + + + for (blk = (const struct block_header *) fw_image->data; + (const u8*) blk < fw_image->data + fw_image->size; + blk = (const struct block_header *) &blk->data[blk->size >> 2]) { + if (blk->size == 0) + continue; + + if (in_range(blk->addr, itcm_base, SZ_16K)) { + reg_offset = (blk->addr - itcm_base) >> 2; + gmu_write_bulk(gmu, + REG_A6XX_GMU_CM3_ITCM_START + reg_offset, + blk->data, blk->size); + } else if (in_range(blk->addr, dtcm_base, SZ_16K)) { + reg_offset = (blk->addr - dtcm_base) >> 2; + gmu_write_bulk(gmu, + REG_A6XX_GMU_CM3_DTCM_START + reg_offset, + blk->data, blk->size); + } else if (!fw_block_mem(&gmu->icache, blk) && + !fw_block_mem(&gmu->dcache, blk) && + !fw_block_mem(&gmu->dummy, blk)) { + DRM_DEV_ERROR(gmu->dev, + "failed to match fw block (addr=%.8x size=%d data[0]=%.8x)\n", + blk->addr, blk->size, blk->data[0]); + } + } + + return 0; +} + static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) { static bool rpmh_init; struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; - int i, ret; + int ret; u32 chipid; - u32 *image; + + if (adreno_is_a650(adreno_gpu)) + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 1); if (state == GMU_WARM_BOOT) { ret = a6xx_rpmh_start(gmu); @@ -626,13 +709,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) "GMU firmware is not loaded\n")) return -ENOENT; - /* Sanity check the size of the firmware that was loaded */ - if (adreno_gpu->fw[ADRENO_FW_GMU]->size > 0x8000) { - DRM_DEV_ERROR(gmu->dev, - "GMU firmware is bigger than the available region\n"); - return -EINVAL; - } - /* Turn on register retention */ gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1); @@ -646,11 +722,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) return ret; } - image = (u32 *) adreno_gpu->fw[ADRENO_FW_GMU]->data; - - for (i = 0; i < adreno_gpu->fw[ADRENO_FW_GMU]->size >> 2; i++) - gmu_write(gmu, REG_A6XX_GMU_CM3_ITCM_START + i, - image[i]); + ret = a6xx_gmu_fw_load(gmu); + if (ret) + return ret; } gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0); @@ -783,6 +857,13 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ? GMU_WARM_BOOT : GMU_COLD_BOOT; + /* + * Warm boot path does not work on newer GPUs + * Presumably this is because icache/dcache regions must be restored + */ + if (!gmu->legacy) + status = GMU_COLD_BOOT; + ret = a6xx_gmu_fw_start(gmu, status); if (ret) goto out; @@ -965,6 +1046,9 @@ static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu) { msm_gem_kernel_put(gmu->hfi.obj, gmu->aspace, false); msm_gem_kernel_put(gmu->debug.obj, gmu->aspace, false); + msm_gem_kernel_put(gmu->icache.obj, gmu->aspace, false); + msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace, false); + msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace, false); gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu); msm_gem_address_space_put(gmu->aspace); @@ -982,12 +1066,14 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, size = PAGE_ALIGN(size); if (!iova) { /* no fixed address - use GMU's uncached range */ - range_start = 0x60000000; + range_start = 0x60000000 + PAGE_SIZE; /* skip dummy page */ range_end = 0x80000000; } else { /* range for fixed address */ range_start = iova; range_end = iova + size; + /* use IOMMU_PRIV for icache/dcache */ + flags |= MSM_BO_MAP_PRIV; } bo->obj = msm_gem_new(dev, size, flags); @@ -1328,7 +1414,27 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (ret) goto err_put_device; - if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) { + /* Allocate memory for the GMU dummy page */ + ret = a6xx_gmu_memory_alloc(gmu, &gmu->dummy, SZ_4K, 0x60000000); + if (ret) + goto err_memory; + + if (adreno_is_a650(adreno_gpu)) { + ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache, + SZ_16M - SZ_16K, 0x04000); + if (ret) + goto err_memory; + } else if (adreno_is_a640(adreno_gpu)) { + ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache, + SZ_256K - SZ_16K, 0x04000); + if (ret) + goto err_memory; + + ret = a6xx_gmu_memory_alloc(gmu, &gmu->dcache, + SZ_256K - SZ_16K, 0x44000); + if (ret) + goto err_memory; + } else { /* HFI v1, has sptprac */ gmu->legacy = true; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 463e2d5f2bb9..c6d8c0d1f90b 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -57,6 +57,9 @@ struct a6xx_gmu { struct a6xx_gmu_bo hfi; struct a6xx_gmu_bo debug; + struct a6xx_gmu_bo icache; + struct a6xx_gmu_bo dcache; + struct a6xx_gmu_bo dummy; int nr_clocks; struct clk_bulk_data *clocks; @@ -92,6 +95,13 @@ static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value) return msm_writel(value, gmu->mmio + (offset << 2)); } +static inline void +gmu_write_bulk(struct a6xx_gmu *gmu, u32 offset, const u32 *data, u32 size) +{ + memcpy_toio(gmu->mmio + (offset << 2), data, size); + wmb(); +} + static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or) { u32 val = gmu_read(gmu, reg); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h index 1cc1c135236b..eb2cd41dae6e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h @@ -101,6 +101,10 @@ static inline uint32_t A6XX_HFI_IRQ_OOB_MASK(uint32_t val) #define REG_A6XX_GMU_DCVS_RETURN 0x000023ff +#define REG_A6XX_GMU_ICACHE_CONFIG 0x00004c00 + +#define REG_A6XX_GMU_DCACHE_CONFIG 0x00004c01 + #define REG_A6XX_GMU_SYS_BUS_CONFIG 0x00004c0f #define REG_A6XX_GMU_CM3_SYSRESET 0x00005000 @@ -199,6 +203,8 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE 0x000050ec +#define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF 0x000050f0 + #define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE 0x000051f0 #define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL 0x00005157 -- cgit v1.2.3 From 02ef80c54e7cd70fe1f422b0315fd1534033e382 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:19 -0400 Subject: drm/msm/a6xx: update pdc/rscc GMU registers for A640/A650 Update the gmu_pdc registers for A640 and A650. Some of the RSCC registers on A650 are in a separate region. Note this also changes the address of these registers: RSCC_TCS1_DRV0_STATUS RSCC_TCS2_DRV0_STATUS RSCC_TCS3_DRV0_STATUS Based on the values in msm-4.14 and msm-4.19 kernels. v3: replaced adreno_is_a650 around ->rscc with checks for "rscc" resource Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 90 +++++++++++++++++++------------ drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 10 ++++ drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 38 ++++++------- 3 files changed, 85 insertions(+), 53 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 749cec7c090e..48d2e8defe59 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -429,7 +429,7 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu) return ret; } - ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val, + ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val, !val, 100, 10000); if (ret) { @@ -455,7 +455,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1); - ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, + ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, val, val & (1 << 16), 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n"); @@ -478,32 +478,48 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) struct platform_device *pdev = to_platform_device(gmu->dev); void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc"); void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq"); + uint32_t pdc_address_offset; if (!pdcptr || !seqptr) goto err; + if (adreno_is_a618(adreno_gpu) || adreno_is_a640(adreno_gpu)) + pdc_address_offset = 0x30090; + else if (adreno_is_a650(adreno_gpu)) + pdc_address_offset = 0x300a0; + else + pdc_address_offset = 0x30080; + /* Disable SDE clock gating */ - gmu_write(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); + gmu_write_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ - gmu_write(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000); - gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); - gmu_write(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); - gmu_write(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); - gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); - gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); + gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000); + gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); + gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); + gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Load RSC sequencer uCode for sleep and wakeup */ - gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0); - gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7); - gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1); - gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2); - gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8); + if (adreno_is_a650(adreno_gpu)) { + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xeaaae5a0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xe1a1ebab); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e0a581); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xecac82e2); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020edad); + } else { + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2); + gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8); + } /* Load PDC sequencer uCode for power up and power down sequence */ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1); @@ -524,10 +540,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0); pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108); - if (adreno_is_a618(adreno_gpu)) - pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30090); - else - pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080); + pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, pdc_address_offset); pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0); pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7); @@ -539,17 +552,12 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108); pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000); - if (adreno_is_a618(adreno_gpu)) + if (adreno_is_a618(adreno_gpu) || adreno_is_a650(adreno_gpu)) pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2); else pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3); - - pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108); - if (adreno_is_a618(adreno_gpu)) - pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30090); - else - pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080); + pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, pdc_address_offset); pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3); /* Setup GPU PDC */ @@ -796,13 +804,13 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu) u32 val; /* Make sure there are no outstanding RPMh votes */ - gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val, + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val, (val & 1), 100, 10000); - gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val, + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val, (val & 1), 100, 10000); - gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val, + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val, (val & 1), 100, 10000); - gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val, + gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val, (val & 1), 100, 1000); } @@ -1361,6 +1369,7 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev, void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) { struct a6xx_gmu *gmu = &a6xx_gpu->gmu; + struct platform_device *pdev = to_platform_device(gmu->dev); if (!gmu->initialized) return; @@ -1373,7 +1382,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) } iounmap(gmu->mmio); + if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) + iounmap(gmu->rscc); gmu->mmio = NULL; + gmu->rscc = NULL; a6xx_gmu_memory_free(gmu); @@ -1456,6 +1468,14 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_memory; } + if (adreno_is_a650(adreno_gpu)) { + gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc"); + if (IS_ERR(gmu->rscc)) + goto err_mmio; + } else { + gmu->rscc = gmu->mmio + 0x23000; + } + /* Get the HFI and GMU interrupts */ gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq); gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq); @@ -1481,6 +1501,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) err_mmio: iounmap(gmu->mmio); + if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) + iounmap(gmu->rscc); free_irq(gmu->gmu_irq, gmu); free_irq(gmu->hfi_irq, gmu); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index c6d8c0d1f90b..e16c16bb65bf 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -47,6 +47,7 @@ struct a6xx_gmu { struct msm_gem_address_space *aspace; void * __iomem mmio; + void * __iomem rscc; int hfi_irq; int gmu_irq; @@ -125,6 +126,15 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi) readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \ interval, timeout) +static inline void gmu_write_rscc(struct a6xx_gmu *gmu, u32 offset, u32 value) +{ + return msm_writel(value, gmu->rscc + (offset << 2)); +} + +#define gmu_poll_timeout_rscc(gmu, addr, val, cond, interval, timeout) \ + readl_poll_timeout((gmu)->rscc + ((addr) << 2), val, cond, \ + interval, timeout) + /* * These are the available OOB (out of band requests) to the GMU where "out of * band" means that the CPU talks to the GMU directly and not through HFI. diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h index eb2cd41dae6e..b4357ea550ec 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h @@ -336,8 +336,6 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GMU_AO_SPARE_CNTL 0x00009316 -#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00008c04 - #define REG_A6XX_GMU_RSCC_CONTROL_REQ 0x00009307 #define REG_A6XX_GMU_RSCC_CONTROL_ACK 0x00009308 @@ -350,39 +348,41 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GPU_CC_GX_DOMAIN_MISC 0x00009d42 -#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR 0x00008c08 +#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00000004 + +#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR 0x00000008 -#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00008c09 +#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00000009 -#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI 0x00008c0a +#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI 0x0000000a -#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x00008c0b +#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x0000000b -#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x00008c0d +#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x0000000d -#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x00008c0e +#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x0000000e -#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00008c82 +#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00000082 -#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00008c83 +#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00000083 -#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00008c89 +#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00000089 -#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x00008c8c +#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x0000008c -#define REG_A6XX_RSCC_OVERRIDE_START_ADDR 0x00008d00 +#define REG_A6XX_RSCC_OVERRIDE_START_ADDR 0x00000100 -#define REG_A6XX_RSCC_SEQ_BUSY_DRV0 0x00008d01 +#define REG_A6XX_RSCC_SEQ_BUSY_DRV0 0x00000101 -#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0 0x00008d80 +#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0 0x00000180 -#define REG_A6XX_RSCC_TCS0_DRV0_STATUS 0x00008f46 +#define REG_A6XX_RSCC_TCS0_DRV0_STATUS 0x00000346 -#define REG_A6XX_RSCC_TCS1_DRV0_STATUS 0x000090ae +#define REG_A6XX_RSCC_TCS1_DRV0_STATUS 0x000003ee -#define REG_A6XX_RSCC_TCS2_DRV0_STATUS 0x00009216 +#define REG_A6XX_RSCC_TCS2_DRV0_STATUS 0x00000496 -#define REG_A6XX_RSCC_TCS3_DRV0_STATUS 0x0000937e +#define REG_A6XX_RSCC_TCS3_DRV0_STATUS 0x0000053e #endif /* A6XX_GMU_XML */ -- cgit v1.2.3 From ad4968d51dd3a22a5a85728fec76bb8711c9c995 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:20 -0400 Subject: drm/msm/a6xx: enable GMU log This is required for a650 to work. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 15 +++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 + drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 4 ++++ 3 files changed, 20 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 48d2e8defe59..8c07850728bc 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -209,6 +209,12 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) u32 val; gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); + + /* Set the log wptr index + * note: downstream saves the value in poweroff and restores it here + */ + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0); + gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val, @@ -752,6 +758,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid); + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG, + gmu->log.iova | (gmu->log.size / SZ_4K - 1)); + /* Set up the lowest idle level on the GMU */ a6xx_gmu_power_config(gmu); @@ -1057,6 +1066,7 @@ static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu) msm_gem_kernel_put(gmu->icache.obj, gmu->aspace, false); msm_gem_kernel_put(gmu->dcache.obj, gmu->aspace, false); msm_gem_kernel_put(gmu->dummy.obj, gmu->aspace, false); + msm_gem_kernel_put(gmu->log.obj, gmu->aspace, false); gmu->aspace->mmu->funcs->detach(gmu->aspace->mmu); msm_gem_address_space_put(gmu->aspace); @@ -1461,6 +1471,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (ret) goto err_memory; + /* Allocate memory for the GMU log region */ + ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_4K, 0); + if (ret) + goto err_memory; + /* Map the GMU registers */ gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu"); if (IS_ERR(gmu->mmio)) { diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index e16c16bb65bf..47df4745db50 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -61,6 +61,7 @@ struct a6xx_gmu { struct a6xx_gmu_bo icache; struct a6xx_gmu_bo dcache; struct a6xx_gmu_bo dummy; + struct a6xx_gmu_bo log; int nr_clocks; struct clk_bulk_data *clocks; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h index b4357ea550ec..176ae94d9fe6 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h @@ -205,6 +205,10 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF 0x000050f0 +#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG 0x00005100 + +#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP 0x00005101 + #define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE 0x000051f0 #define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL 0x00005157 -- cgit v1.2.3 From 24e6938ec604b7dc0306c972c1aa029ff03bb36a Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 23 Apr 2020 17:09:21 -0400 Subject: drm/msm/a6xx: update a6xx_hw_init for A640 and A650 Adreno 640 and 650 GPUs need some registers set differently. Signed-off-by: Jonathan Marek Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx.xml.h | 14 +++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 +++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h index ed78fee2a262..47840b73cdda 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h @@ -1047,6 +1047,8 @@ enum a6xx_tex_type { #define REG_A6XX_CP_MISC_CNTL 0x00000840 +#define REG_A6XX_CP_APRIV_CNTL 0x00000844 + #define REG_A6XX_CP_ROQ_THRESHOLDS_1 0x000008c1 #define REG_A6XX_CP_ROQ_THRESHOLDS_2 0x000008c2 @@ -1764,6 +1766,8 @@ static inline uint32_t A6XX_CP_PROTECT_REG_MASK_LEN(uint32_t val) #define REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL 0x00000010 +#define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL 0x00000011 + #define REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL 0x0000001f #define REG_A6XX_RBBM_INT_CLEAR_CMD 0x00000037 @@ -2418,6 +2422,16 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val) #define REG_A6XX_TPL1_NC_MODE_CNTL 0x0000b604 +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0 0x0000b608 + +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1 0x0000b609 + +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2 0x0000b60a + +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3 0x0000b60b + +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4 0x0000b60c + #define REG_A6XX_TPL1_PERFCTR_TP_SEL_0 0x0000b610 #define REG_A6XX_TPL1_PERFCTR_TP_SEL_1 0x0000b611 diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 20528ede63b6..6f335ae179c8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -414,7 +414,17 @@ static int a6xx_hw_init(struct msm_gpu *gpu) a6xx_set_hwcg(gpu, true); /* VBIF/GBIF start*/ - gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3); + if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620); + gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620); + gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620); + gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); + gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620); + gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3); + } else { + gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3); + } + if (adreno_is_a630(adreno_gpu)) gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009); @@ -429,25 +439,35 @@ static int a6xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000); gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff); - /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ - gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO, - REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000); + if (!adreno_is_a650(adreno_gpu)) { + /* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */ + gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO, + REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000); - gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO, - REG_A6XX_UCHE_GMEM_RANGE_MAX_HI, - 0x00100000 + adreno_gpu->gmem - 1); + gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO, + REG_A6XX_UCHE_GMEM_RANGE_MAX_HI, + 0x00100000 + adreno_gpu->gmem - 1); + } gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4); - gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0); + if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140); + else + gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0); gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c); /* Setting the mem pool size */ gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128); /* Setting the primFifo thresholds default values */ - gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11)); + if (adreno_is_a650(adreno_gpu)) + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300000); + else if (adreno_is_a640(adreno_gpu)) + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200000); + else + gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11)); /* Set the AHB default slave response to "ERROR" */ gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1); @@ -471,6 +491,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1); + /* Set weights for bicubic filtering */ + if (adreno_is_a650(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0); + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1, + 0x3fe05ff4); + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2, + 0x3fa0ebee); + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3, + 0x3f5193ed); + gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4, + 0x3f0243f0); + } + /* Protect registers from the CP */ gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, 0x00000003); @@ -508,6 +541,11 @@ static int a6xx_hw_init(struct msm_gpu *gpu) A6XX_PROTECT_RDONLY(0x980, 0x4)); gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0)); + if (adreno_is_a650(adreno_gpu)) { + gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, + (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1)); + } + /* Enable interrupts */ gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK); -- cgit v1.2.3 From dc0fa5eb765d881977bab7568245f653407481be Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 9 May 2020 20:38:45 +0800 Subject: drm/msm/a4xx: add adreno a405 support It adds support for adreno a405 found on MSM8939. The adreno_is_a430() check in adreno_submit() needs an extension to cover a405. The downstream driver suggests it should cover the whole a4xx generation. That's why it gets changed to adreno_is_a4xx(), while a420 is not tested though. Signed-off-by: Shawn Guo Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 29 +++++++++++++++++------------ drivers/gpu/drm/msm/adreno/adreno_device.c | 11 +++++++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 5 +++++ 4 files changed, 34 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 253d8d85daad..70de59751188 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -66,19 +66,22 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu) } } - for (i = 0; i < 4; i++) { - gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i), - 0x00000922); - } + /* No CCU for A405 */ + if (!adreno_is_a405(adreno_gpu)) { + for (i = 0; i < 4; i++) { + gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i), + 0x00000922); + } - for (i = 0; i < 4; i++) { - gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i), - 0x00000000); - } + for (i = 0; i < 4; i++) { + gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i), + 0x00000000); + } - for (i = 0; i < 4; i++) { - gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i), - 0x00000001); + for (i = 0; i < 4; i++) { + gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i), + 0x00000001); + } } gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222); @@ -137,7 +140,9 @@ static int a4xx_hw_init(struct msm_gpu *gpu) uint32_t *ptr, len; int i, ret; - if (adreno_is_a420(adreno_gpu)) { + if (adreno_is_a405(adreno_gpu)) { + gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); + } else if (adreno_is_a420(adreno_gpu)) { gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F); gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4); gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001); diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 1156f72532a4..7732f03d9e3a 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -92,6 +92,17 @@ static const struct adreno_info gpulist[] = { .gmem = SZ_1M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a3xx_gpu_init, + }, { + .rev = ADRENO_REV(4, 0, 5, ANY_ID), + .revn = 405, + .name = "A405", + .fw = { + [ADRENO_FW_PM4] = "a420_pm4.fw", + [ADRENO_FW_PFP] = "a420_pfp.fw", + }, + .gmem = SZ_256K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .init = a4xx_gpu_init, }, { .rev = ADRENO_REV(4, 2, 0, ANY_ID), .revn = 420, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index a7647eaacc7a..ff7f441932b8 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -459,7 +459,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, break; /* fall-thru */ case MSM_SUBMIT_CMD_BUF: - OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ? + OUT_PKT3(ring, adreno_is_a4xx(adreno_gpu) ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2); OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); OUT_RING(ring, submit->cmd[i].size); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 88ae1b2813ef..dea97c8317e0 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -202,6 +202,11 @@ static inline bool adreno_is_a4xx(struct adreno_gpu *gpu) return (gpu->revn >= 400) && (gpu->revn < 500); } +static inline int adreno_is_a405(struct adreno_gpu *gpu) +{ + return gpu->revn == 405; +} + static inline int adreno_is_a420(struct adreno_gpu *gpu) { return gpu->revn == 420; -- cgit v1.2.3 From d3b68ddf1d38366d3dd5afae21f167aaf5161d32 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 9 May 2020 20:38:46 +0800 Subject: drm/msm/a4xx: add a405_registers for a405 device A405 device has a different set of registers than a4xx_registers. It has no VMIDMT or XPU registers, and VBIF registers are different. Let's add a405_registers for a405 device. As adreno_is_a405() works only after adreno_gpu_init() gets called, the assignments get moved down after adreno_gpu_init(). Signed-off-by: Shawn Guo Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 70de59751188..9e244982974e 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -445,6 +445,52 @@ static const unsigned int a4xx_registers[] = { ~0 /* sentinel */ }; +static const unsigned int a405_registers[] = { + /* RBBM */ + 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026, + 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066, + 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF, + /* CP */ + 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B, + 0x0578, 0x058F, + /* VSC */ + 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51, + /* GRAS */ + 0x0C80, 0x0C81, 0x0C88, 0x0C8F, + /* RB */ + 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2, + /* PC */ + 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23, + /* VFD */ + 0x0E40, 0x0E4A, + /* VPC */ + 0x0E60, 0x0E61, 0x0E63, 0x0E68, + /* UCHE */ + 0x0E80, 0x0E84, 0x0E88, 0x0E95, + /* GRAS CTX 0 */ + 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E, + /* PC CTX 0 */ + 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7, + /* VFD CTX 0 */ + 0x2200, 0x2204, 0x2208, 0x22A9, + /* GRAS CTX 1 */ + 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E, + /* PC CTX 1 */ + 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7, + /* VFD CTX 1 */ + 0x2600, 0x2604, 0x2608, 0x26A9, + /* VBIF version 0x20050000*/ + 0x3000, 0x3007, 0x302C, 0x302C, 0x3030, 0x3030, 0x3034, 0x3036, + 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040, 0x3049, 0x3049, + 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068, 0x306C, 0x306D, + 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094, 0x3098, 0x3098, + 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8, 0x30D0, 0x30D0, + 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100, 0x3108, 0x3108, + 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120, 0x3124, 0x3125, + 0x3129, 0x3129, 0x340C, 0x340C, 0x3410, 0x3410, + ~0 /* sentinel */ +}; + static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu) { struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL); @@ -568,13 +614,14 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) gpu->perfcntrs = NULL; gpu->num_perfcntrs = 0; - adreno_gpu->registers = a4xx_registers; - adreno_gpu->reg_offsets = a4xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) goto fail; + adreno_gpu->registers = adreno_is_a405(adreno_gpu) ? a405_registers : + a4xx_registers; + adreno_gpu->reg_offsets = a4xx_register_offsets; + /* if needed, allocate gmem: */ if (adreno_is_a4xx(adreno_gpu)) { ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu, -- cgit v1.2.3 From d9aeccec85ec39c4da90cc4b899cbd1961416a0d Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 21 May 2020 16:30:19 +0800 Subject: drm/msm/a6xx: a6xx_hfi_send_start() can be static Fixes: 8167e6fa76c8 ("drm/msm/a6xx: HFI v2 for A640 and A650") Signed-off-by: kbuild test robot Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index f9db69e77121..9921e632f1ca 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -342,7 +342,7 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu) NULL, 0); } -int a6xx_hfi_send_start(struct a6xx_gmu *gmu) +static int a6xx_hfi_send_start(struct a6xx_gmu *gmu) { struct a6xx_hfi_msg_start msg = { 0 }; @@ -350,7 +350,7 @@ int a6xx_hfi_send_start(struct a6xx_gmu *gmu) NULL, 0); } -int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) +static int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu) { struct a6xx_hfi_msg_core_fw_start msg = { 0 }; -- cgit v1.2.3 From 7d4eedb03fc754625e0e0c482f42bfeabce685ce Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 21 May 2020 15:11:13 +0800 Subject: drm/msm/dpu: dpu_setup_dspp_pcc() can be static Fixes: 4259ff7ae509 ("drm/msm/dpu: add support for pcc color block in dpu driver") Signed-off-by: kbuild test robot Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c index b5189cece3c6..a7a24539921f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c @@ -22,7 +22,7 @@ #define PCC_BLUE_G_OFF 0x24 #define PCC_BLUE_B_OFF 0x30 -void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, +static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, struct dpu_hw_pcc_cfg *cfg) { -- cgit v1.2.3 From 52da6d513183cf543df6efc95bf504aee0da70d6 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 22 May 2020 16:03:14 -0600 Subject: drm/msm: Attach the IOMMU device during initialization Everywhere an IOMMU object is created by msm_gpu_create_address_space the IOMMU device is attached immediately after. Instead of carrying around the infrastructure to do the attach from the device specific code do it directly in the msm_iommu_init() function. This gets it out of the way for more aggressive cleanups that follow. Reviewed-by: Rob Clark Signed-off-by: Jordan Crouse Tested-by: Shawn Guo [squash in rebase fixups and fix for unused fxn] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 7 ------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 8 -------- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 4 ---- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 7 ------- drivers/gpu/drm/msm/msm_gem_vma.c | 23 +++++++++++++++++++---- drivers/gpu/drm/msm/msm_gpu.c | 11 +---------- drivers/gpu/drm/msm/msm_gpummu.c | 6 ------ drivers/gpu/drm/msm/msm_iommu.c | 15 +++++++-------- drivers/gpu/drm/msm/msm_mmu.h | 1 - 9 files changed, 27 insertions(+), 55 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 8c07850728bc..0c72ae84e279 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1114,7 +1114,6 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) { struct iommu_domain *domain; - int ret; domain = iommu_domain_alloc(&platform_bus_type); if (!domain) @@ -1129,12 +1128,6 @@ static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) return PTR_ERR(gmu->aspace); } - ret = gmu->aspace->mmu->funcs->attach(gmu->aspace->mmu); - if (ret) { - msm_gem_address_space_put(gmu->aspace); - return ret; - } - return 0; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 10c33cf7a5d7..c5150c67a3b8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -794,7 +794,6 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) { struct iommu_domain *domain; struct msm_gem_address_space *aspace; - int ret; domain = iommu_domain_alloc(&platform_bus_type); if (!domain) @@ -810,13 +809,6 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) return PTR_ERR(aspace); } - ret = aspace->mmu->funcs->attach(aspace->mmu); - if (ret) { - DPU_ERROR("failed to attach iommu %d\n", ret); - msm_gem_address_space_put(aspace); - return ret; - } - dpu_kms->base.aspace = aspace; return 0; } diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index dda05436f716..9dba37c6344f 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -518,10 +518,6 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) } kms->aspace = aspace; - - ret = aspace->mmu->funcs->attach(aspace->mmu); - if (ret) - goto fail; } else { DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys " "contig buffers for scanout\n"); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index c23a2fa13fb9..fe18656848ce 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -644,13 +644,6 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) } kms->aspace = aspace; - - ret = aspace->mmu->funcs->attach(aspace->mmu); - if (ret) { - DRM_DEV_ERROR(&pdev->dev, "failed to attach iommu: %d\n", - ret); - goto fail; - } } else { DRM_DEV_INFO(&pdev->dev, "no iommu, fallback to phys contig buffers for scanout\n"); diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 407b7ab82818..72fc1980fff6 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -133,8 +133,8 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, const char *name) { struct msm_gem_address_space *aspace; - u64 size = domain->geometry.aperture_end - - domain->geometry.aperture_start; + u64 start = domain->geometry.aperture_start; + u64 size = domain->geometry.aperture_end - start; aspace = kzalloc(sizeof(*aspace), GFP_KERNEL); if (!aspace) @@ -143,9 +143,18 @@ msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, spin_lock_init(&aspace->lock); aspace->name = name; aspace->mmu = msm_iommu_new(dev, domain); + if (IS_ERR(aspace->mmu)) { + int ret = PTR_ERR(aspace->mmu); - drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT), - size >> PAGE_SHIFT); + kfree(aspace); + return ERR_PTR(ret); + } + + /* + * Attaching the IOMMU device changes the aperture values so use the + * cached values instead + */ + drm_mm_init(&aspace->mm, start >> PAGE_SHIFT, size >> PAGE_SHIFT); kref_init(&aspace->kref); @@ -166,6 +175,12 @@ msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu, spin_lock_init(&aspace->lock); aspace->name = name; aspace->mmu = msm_gpummu_new(dev, gpu); + if (IS_ERR(aspace->mmu)) { + int ret = PTR_ERR(aspace->mmu); + + kfree(aspace); + return ERR_PTR(ret); + } drm_mm_init(&aspace->mm, (va_start >> PAGE_SHIFT), size >> PAGE_SHIFT); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 615c5cda5389..b6f0d7204da9 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -826,7 +826,6 @@ msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, uint64_t va_start, uint64_t va_end) { struct msm_gem_address_space *aspace; - int ret; /* * Setup IOMMU.. eventually we will (I think) do this once per context @@ -851,17 +850,9 @@ msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, va_start, va_end); } - if (IS_ERR(aspace)) { + if (IS_ERR(aspace)) DRM_DEV_ERROR(gpu->dev->dev, "failed to init mmu: %ld\n", PTR_ERR(aspace)); - return ERR_CAST(aspace); - } - - ret = aspace->mmu->funcs->attach(aspace->mmu); - if (ret) { - msm_gem_address_space_put(aspace); - return ERR_PTR(ret); - } return aspace; } diff --git a/drivers/gpu/drm/msm/msm_gpummu.c b/drivers/gpu/drm/msm/msm_gpummu.c index 34980d8eb7ad..0ad0f848560a 100644 --- a/drivers/gpu/drm/msm/msm_gpummu.c +++ b/drivers/gpu/drm/msm/msm_gpummu.c @@ -21,11 +21,6 @@ struct msm_gpummu { #define GPUMMU_PAGE_SIZE SZ_4K #define TABLE_SIZE (sizeof(uint32_t) * GPUMMU_VA_RANGE / GPUMMU_PAGE_SIZE) -static int msm_gpummu_attach(struct msm_mmu *mmu) -{ - return 0; -} - static void msm_gpummu_detach(struct msm_mmu *mmu) { } @@ -85,7 +80,6 @@ static void msm_gpummu_destroy(struct msm_mmu *mmu) } static const struct msm_mmu_funcs funcs = { - .attach = msm_gpummu_attach, .detach = msm_gpummu_detach, .map = msm_gpummu_map, .unmap = msm_gpummu_unmap, diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index ad58cfe5998e..544c51955717 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -23,13 +23,6 @@ static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, return 0; } -static int msm_iommu_attach(struct msm_mmu *mmu) -{ - struct msm_iommu *iommu = to_msm_iommu(mmu); - - return iommu_attach_device(iommu->domain, mmu->dev); -} - static void msm_iommu_detach(struct msm_mmu *mmu) { struct msm_iommu *iommu = to_msm_iommu(mmu); @@ -66,7 +59,6 @@ static void msm_iommu_destroy(struct msm_mmu *mmu) } static const struct msm_mmu_funcs funcs = { - .attach = msm_iommu_attach, .detach = msm_iommu_detach, .map = msm_iommu_map, .unmap = msm_iommu_unmap, @@ -76,6 +68,7 @@ static const struct msm_mmu_funcs funcs = { struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) { struct msm_iommu *iommu; + int ret; iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) @@ -85,5 +78,11 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) msm_mmu_init(&iommu->base, dev, &funcs); iommu_set_fault_handler(domain, msm_fault_handler, iommu); + ret = iommu_attach_device(iommu->domain, dev); + if (ret) { + kfree(iommu); + return ERR_PTR(ret); + } + return &iommu->base; } diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index 67a623f14319..bae9e8e67ec1 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -10,7 +10,6 @@ #include struct msm_mmu_funcs { - int (*attach)(struct msm_mmu *mmu); void (*detach)(struct msm_mmu *mmu); int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt, unsigned len, int prot); -- cgit v1.2.3 From ccac7ce373c1b5175bcf733fe6223129b8975788 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 22 May 2020 16:03:15 -0600 Subject: drm/msm: Refactor address space initialization Refactor how address space initialization works. Instead of having the address space function create the MMU object (and thus require separate but equal functions for gpummu and iommu) use a single function and pass the MMU struct in. Make the generic code cleaner by using target specific functions to create the address space so a2xx can do its own thing in its own space. For all the other targets use a generic helper to initialize IOMMU but leave the door open for newer targets to use customization if they need it. Reviewed-by: Rob Clark Signed-off-by: Jordan Crouse Tested-by: Shawn Guo [squash in rebase fixups] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 16 ++++++++++ drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 7 ++--- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 + drivers/gpu/drm/msm/adreno/adreno_gpu.c | 23 ++++++++++---- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 8 +++++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 10 +++---- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 14 +++++---- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 4 --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 11 +++++-- drivers/gpu/drm/msm/msm_drv.h | 8 ++--- drivers/gpu/drm/msm/msm_gem_vma.c | 51 ++++---------------------------- drivers/gpu/drm/msm/msm_gpu.c | 40 ++----------------------- drivers/gpu/drm/msm/msm_gpu.h | 4 +-- drivers/gpu/drm/msm/msm_iommu.c | 3 ++ 17 files changed, 85 insertions(+), 118 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 1f83bc18d500..60f6472a3e58 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -401,6 +401,21 @@ static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu) return state; } +static struct msm_gem_address_space * +a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) +{ + struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu); + struct msm_gem_address_space *aspace; + + aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, + SZ_16M + 0xfff * SZ_64K); + + if (IS_ERR(aspace) && !IS_ERR(mmu)) + mmu->funcs->destroy(mmu); + + return aspace; +} + /* Register offset defines for A2XX - copy of A3XX */ static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE), @@ -429,6 +444,7 @@ static const struct adreno_gpu_funcs funcs = { #endif .gpu_state_get = a2xx_gpu_state_get, .gpu_state_put = adreno_gpu_state_put, + .create_address_space = a2xx_create_address_space, }, }; diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index b67f88872726..0a5ea9f56cb8 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -441,6 +441,7 @@ static const struct adreno_gpu_funcs funcs = { #endif .gpu_state_get = a3xx_gpu_state_get, .gpu_state_put = adreno_gpu_state_put, + .create_address_space = adreno_iommu_create_address_space, }, }; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 9e244982974e..b9b26b2bf9c5 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -583,6 +583,7 @@ static const struct adreno_gpu_funcs funcs = { #endif .gpu_state_get = a4xx_gpu_state_get, .gpu_state_put = adreno_gpu_state_put, + .create_address_space = adreno_iommu_create_address_space, }, .get_timestamp = a4xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 662d02289533..d95970a73fb4 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1445,6 +1445,7 @@ static const struct adreno_gpu_funcs funcs = { .gpu_busy = a5xx_gpu_busy, .gpu_state_get = a5xx_gpu_state_get, .gpu_state_put = a5xx_gpu_state_put, + .create_address_space = adreno_iommu_create_address_space, }, .get_timestamp = a5xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 0c72ae84e279..c5e21b53c4d0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1114,15 +1114,14 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo, static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) { struct iommu_domain *domain; + struct msm_mmu *mmu; domain = iommu_domain_alloc(&platform_bus_type); if (!domain) return -ENODEV; - domain->geometry.aperture_start = 0x00000000; - domain->geometry.aperture_end = 0x7fffffff; - - gmu->aspace = msm_gem_address_space_create(gmu->dev, domain, "gmu"); + mmu = msm_iommu_new(gmu->dev, domain); + gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x7fffffff); if (IS_ERR(gmu->aspace)) { iommu_domain_free(domain); return PTR_ERR(gmu->aspace); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 6f335ae179c8..a1589e040c57 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -893,6 +893,7 @@ static const struct adreno_gpu_funcs funcs = { #if defined(CONFIG_DRM_MSM_GPU_STATE) .gpu_state_get = a6xx_gpu_state_get, .gpu_state_put = a6xx_gpu_state_put, + .create_address_space = adreno_iommu_create_address_space, #endif }, .get_timestamp = a6xx_get_timestamp, diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index ff7f441932b8..89673c7ed473 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -185,6 +185,23 @@ int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid) return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid); } +struct msm_gem_address_space * +adreno_iommu_create_address_space(struct msm_gpu *gpu, + struct platform_device *pdev) +{ + struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type); + struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu); + struct msm_gem_address_space *aspace; + + aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, + 0xfffffff); + + if (IS_ERR(aspace) && !IS_ERR(mmu)) + mmu->funcs->destroy(mmu); + + return aspace; +} + int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -988,12 +1005,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; - adreno_gpu_config.va_start = SZ_16M; - adreno_gpu_config.va_end = 0xffffffff; - /* maximum range of a2xx mmu */ - if (adreno_is_a2xx(adreno_gpu)) - adreno_gpu_config.va_end = SZ_16M + 0xfff * SZ_64K; - adreno_gpu_config.nr_rings = nr_rings; adreno_get_pwrlevels(&pdev->dev, gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index dea97c8317e0..2f5d2c3acc3a 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -287,6 +287,14 @@ void adreno_gpu_state_destroy(struct msm_gpu_state *state); int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state); int adreno_gpu_state_put(struct msm_gpu_state *state); +/* + * Common helper function to initialize the default address space for arm-smmu + * attached targets + */ +struct msm_gem_address_space * +adreno_iommu_create_address_space(struct msm_gpu *gpu, + struct platform_device *pdev); + /* * For a5xx and a6xx targets load the zap shader that is used to pull the GPU * out of secure mode diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c5150c67a3b8..a5da7aacddba 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -794,18 +794,18 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) { struct iommu_domain *domain; struct msm_gem_address_space *aspace; + struct msm_mmu *mmu; domain = iommu_domain_alloc(&platform_bus_type); if (!domain) return 0; - domain->geometry.aperture_start = 0x1000; - domain->geometry.aperture_end = 0xffffffff; + mmu = msm_iommu_new(dpu_kms->dev->dev, domain); + aspace = msm_gem_address_space_create(mmu, "dpu1", + 0x1000, 0xfffffff); - aspace = msm_gem_address_space_create(dpu_kms->dev->dev, - domain, "dpu1"); if (IS_ERR(aspace)) { - iommu_domain_free(domain); + mmu->funcs->destroy(mmu); return PTR_ERR(aspace); } diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 9dba37c6344f..08897184b1d9 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -510,9 +510,15 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev) mdelay(16); if (config->iommu) { - aspace = msm_gem_address_space_create(&pdev->dev, - config->iommu, "mdp4"); + struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, + config->iommu); + + aspace = msm_gem_address_space_create(mmu, + "mdp4", 0x1000, 0xffffffff); + if (IS_ERR(aspace)) { + if (!IS_ERR(mmu)) + mmu->funcs->destroy(mmu); ret = PTR_ERR(aspace); goto fail; } @@ -565,10 +571,6 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev) /* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */ config.max_clk = 266667000; config.iommu = iommu_domain_alloc(&platform_bus_type); - if (config.iommu) { - config.iommu->geometry.aperture_start = 0x1000; - config.iommu->geometry.aperture_end = 0xffffffff; - } return &config; } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c index a7df8dbffdc2..25a13a2a57a9 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c @@ -1017,10 +1017,6 @@ static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev) static struct mdp5_cfg_platform config = {}; config.iommu = iommu_domain_alloc(&platform_bus_type); - if (config.iommu) { - config.iommu->geometry.aperture_start = 0x1000; - config.iommu->geometry.aperture_end = 0xffffffff; - } return &config; } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index fe18656848ce..54631fbd9389 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -632,13 +632,20 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) mdelay(16); if (config->platform.iommu) { + struct msm_mmu *mmu; + iommu_dev = &pdev->dev; if (!dev_iommu_fwspec_get(iommu_dev)) iommu_dev = iommu_dev->parent; - aspace = msm_gem_address_space_create(iommu_dev, - config->platform.iommu, "mdp5"); + mmu = msm_iommu_new(iommu_dev, config->platform.iommu); + + aspace = msm_gem_address_space_create(mmu, "mdp5", + 0x1000, 0xffffffff); + if (IS_ERR(aspace)) { + if (!IS_ERR(mmu)) + mmu->funcs->destroy(mmu); ret = PTR_ERR(aspace); goto fail; } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 108202c35637..e2d6a6056418 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -252,12 +252,8 @@ void msm_gem_close_vma(struct msm_gem_address_space *aspace, void msm_gem_address_space_put(struct msm_gem_address_space *aspace); struct msm_gem_address_space * -msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, - const char *name); - -struct msm_gem_address_space * -msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu, - const char *name, uint64_t va_start, uint64_t va_end); +msm_gem_address_space_create(struct msm_mmu *mmu, const char *name, + u64 va_start, u64 size); int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 72fc1980fff6..5f6a11211b64 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -127,46 +127,14 @@ int msm_gem_init_vma(struct msm_gem_address_space *aspace, return 0; } - struct msm_gem_address_space * -msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, - const char *name) +msm_gem_address_space_create(struct msm_mmu *mmu, const char *name, + u64 va_start, u64 size) { struct msm_gem_address_space *aspace; - u64 start = domain->geometry.aperture_start; - u64 size = domain->geometry.aperture_end - start; - - aspace = kzalloc(sizeof(*aspace), GFP_KERNEL); - if (!aspace) - return ERR_PTR(-ENOMEM); - spin_lock_init(&aspace->lock); - aspace->name = name; - aspace->mmu = msm_iommu_new(dev, domain); - if (IS_ERR(aspace->mmu)) { - int ret = PTR_ERR(aspace->mmu); - - kfree(aspace); - return ERR_PTR(ret); - } - - /* - * Attaching the IOMMU device changes the aperture values so use the - * cached values instead - */ - drm_mm_init(&aspace->mm, start >> PAGE_SHIFT, size >> PAGE_SHIFT); - - kref_init(&aspace->kref); - - return aspace; -} - -struct msm_gem_address_space * -msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu, - const char *name, uint64_t va_start, uint64_t va_end) -{ - struct msm_gem_address_space *aspace; - u64 size = va_end - va_start; + if (IS_ERR(mmu)) + return ERR_CAST(mmu); aspace = kzalloc(sizeof(*aspace), GFP_KERNEL); if (!aspace) @@ -174,16 +142,9 @@ msm_gem_address_space_create_a2xx(struct device *dev, struct msm_gpu *gpu, spin_lock_init(&aspace->lock); aspace->name = name; - aspace->mmu = msm_gpummu_new(dev, gpu); - if (IS_ERR(aspace->mmu)) { - int ret = PTR_ERR(aspace->mmu); - - kfree(aspace); - return ERR_PTR(ret); - } + aspace->mmu = mmu; - drm_mm_init(&aspace->mm, (va_start >> PAGE_SHIFT), - size >> PAGE_SHIFT); + drm_mm_init(&aspace->mm, va_start >> PAGE_SHIFT, size >> PAGE_SHIFT); kref_init(&aspace->kref); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index b6f0d7204da9..a22d30622306 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -821,42 +821,6 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) return 0; } -static struct msm_gem_address_space * -msm_gpu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev, - uint64_t va_start, uint64_t va_end) -{ - struct msm_gem_address_space *aspace; - - /* - * Setup IOMMU.. eventually we will (I think) do this once per context - * and have separate page tables per context. For now, to keep things - * simple and to get something working, just use a single address space: - */ - if (!adreno_is_a2xx(to_adreno_gpu(gpu))) { - struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type); - if (!iommu) - return NULL; - - iommu->geometry.aperture_start = va_start; - iommu->geometry.aperture_end = va_end; - - DRM_DEV_INFO(gpu->dev->dev, "%s: using IOMMU\n", gpu->name); - - aspace = msm_gem_address_space_create(&pdev->dev, iommu, "gpu"); - if (IS_ERR(aspace)) - iommu_domain_free(iommu); - } else { - aspace = msm_gem_address_space_create_a2xx(&pdev->dev, gpu, "gpu", - va_start, va_end); - } - - if (IS_ERR(aspace)) - DRM_DEV_ERROR(gpu->dev->dev, "failed to init mmu: %ld\n", - PTR_ERR(aspace)); - - return aspace; -} - int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, const char *name, struct msm_gpu_config *config) @@ -929,8 +893,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, msm_devfreq_init(gpu); - gpu->aspace = msm_gpu_create_address_space(gpu, pdev, - config->va_start, config->va_end); + + gpu->aspace = gpu->funcs->create_address_space(gpu, pdev); if (gpu->aspace == NULL) DRM_DEV_INFO(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index be5bc2e8425c..d496b68e58a9 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -21,8 +21,6 @@ struct msm_gpu_state; struct msm_gpu_config { const char *ioname; - uint64_t va_start; - uint64_t va_end; unsigned int nr_rings; }; @@ -64,6 +62,8 @@ struct msm_gpu_funcs { int (*gpu_state_put)(struct msm_gpu_state *state); unsigned long (*gpu_get_freq)(struct msm_gpu *gpu); void (*gpu_set_freq)(struct msm_gpu *gpu, unsigned long freq); + struct msm_gem_address_space *(*create_address_space) + (struct msm_gpu *gpu, struct platform_device *pdev); }; struct msm_gpu { diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 544c51955717..e773ef8c7203 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -70,6 +70,9 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) struct msm_iommu *iommu; int ret; + if (!domain) + return ERR_PTR(-ENODEV); + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From fb212ad6cc58c0fd8c0f76578d4392f71e595bd5 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 22 May 2020 16:03:16 -0600 Subject: drm/msm: Update the MMU helper function APIs Instead of using a bare unsigned type for the length value for map/unmap functions pass in a size_t to more correctly match up with the underlying APIs. Signed-off-by: Jordan Crouse Tested-by: Shawn Guo Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gpummu.c | 4 ++-- drivers/gpu/drm/msm/msm_iommu.c | 4 ++-- drivers/gpu/drm/msm/msm_mmu.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_gpummu.c b/drivers/gpu/drm/msm/msm_gpummu.c index 0ad0f848560a..310a31b05faa 100644 --- a/drivers/gpu/drm/msm/msm_gpummu.c +++ b/drivers/gpu/drm/msm/msm_gpummu.c @@ -26,7 +26,7 @@ static void msm_gpummu_detach(struct msm_mmu *mmu) } static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova, - struct sg_table *sgt, unsigned len, int prot) + struct sg_table *sgt, size_t len, int prot) { struct msm_gpummu *gpummu = to_msm_gpummu(mmu); unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE; @@ -54,7 +54,7 @@ static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova, return 0; } -static int msm_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len) +static int msm_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len) { struct msm_gpummu *gpummu = to_msm_gpummu(mmu); unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE; diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index e773ef8c7203..3a381a9674c9 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -31,7 +31,7 @@ static void msm_iommu_detach(struct msm_mmu *mmu) } static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, - struct sg_table *sgt, unsigned len, int prot) + struct sg_table *sgt, size_t len, int prot) { struct msm_iommu *iommu = to_msm_iommu(mmu); size_t ret; @@ -42,7 +42,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, return (ret == len) ? 0 : -EINVAL; } -static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len) +static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len) { struct msm_iommu *iommu = to_msm_iommu(mmu); diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index bae9e8e67ec1..3a534ee59bf6 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -12,8 +12,8 @@ struct msm_mmu_funcs { void (*detach)(struct msm_mmu *mmu); int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt, - unsigned len, int prot); - int (*unmap)(struct msm_mmu *mmu, uint64_t iova, unsigned len); + size_t len, int prot); + int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len); void (*destroy)(struct msm_mmu *mmu); }; -- cgit v1.2.3 From d9e19d7966a31ae70edfe0cb7cb044e20343a0c9 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Fri, 22 May 2020 18:29:08 -0400 Subject: drm/msm/a6xx: skip HFI set freq if GMU is powered down Also skip the newly added HFI set freq path if the GMU is powered down, which was missing because of patches crossing paths. Signed-off-by: Jonathan Marek Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index c5e21b53c4d0..096be97ce9f9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -110,13 +110,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) struct msm_gpu *gpu = &adreno_gpu->base; int ret; - /* - * This can get called from devfreq while the hardware is idle. Don't - * bring up the power if it isn't already active - */ - if (pm_runtime_get_if_in_use(gmu->dev) == 0) - return; - gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, @@ -141,7 +134,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) * for now leave it at max so that the performance is nominal. */ icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216)); - pm_runtime_put(gmu->dev); } void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) @@ -159,13 +151,21 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) break; gmu->current_perf_index = perf_index; + gmu->freq = gmu->gpu_freqs[perf_index]; + + /* + * This can get called from devfreq while the hardware is idle. Don't + * bring up the power if it isn't already active + */ + if (pm_runtime_get_if_in_use(gmu->dev) == 0) + return; if (gmu->legacy) __a6xx_gmu_set_freq(gmu, perf_index); else a6xx_hfi_set_freq(gmu, perf_index); - gmu->freq = gmu->gpu_freqs[perf_index]; + pm_runtime_put(gmu->dev); } unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu) -- cgit v1.2.3 From 1cb2c4a2c89b2004a36399860c85a1af9b3fcba7 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 1 Jun 2020 20:54:50 -0700 Subject: Revert "drm/msm/dpu: add support for clk and bw scaling for display" This is causing multiple armv7 missing do_div() errors, so lets drop it for now. This reverts commit 04d9044f6c577948609c03b4e33b8fbc8b87c4b1. Cc: Kalyan Thota Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 106 ++++--------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 37 +-------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 - drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 82 ------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 - 8 files changed, 23 insertions(+), 228 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 9697abcbec3f..7c230f719ad3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -29,73 +29,6 @@ enum dpu_perf_mode { DPU_PERF_MODE_MAX }; -/** - * @_dpu_core_perf_calc_bw() - to calculate BW per crtc - * @kms - pointer to the dpu_kms - * @crtc - pointer to a crtc - * Return: returns aggregated BW for all planes in crtc. - */ -static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms, - struct drm_crtc *crtc) -{ - struct drm_plane *plane; - struct dpu_plane_state *pstate; - u64 crtc_plane_bw = 0; - u32 bw_factor; - - drm_atomic_crtc_for_each_plane(plane, crtc) { - pstate = to_dpu_plane_state(plane->state); - - if (!pstate) - continue; - - crtc_plane_bw += pstate->plane_fetch_bw; - } - - bw_factor = kms->catalog->perf.bw_inefficiency_factor; - if (bw_factor) - crtc_plane_bw = mult_frac(crtc_plane_bw, bw_factor, 100); - - return crtc_plane_bw; -} - -/** - * _dpu_core_perf_calc_clk() - to calculate clock per crtc - * @kms - pointer to the dpu_kms - * @crtc - pointer to a crtc - * @state - pointer to a crtc state - * Return: returns max clk for all planes in crtc. - */ -static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms, - struct drm_crtc *crtc, struct drm_crtc_state *state) -{ - struct drm_plane *plane; - struct dpu_plane_state *pstate; - struct drm_display_mode *mode; - u64 crtc_clk; - u32 clk_factor; - - mode = &state->adjusted_mode; - - crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); - - drm_atomic_crtc_for_each_plane(plane, crtc) { - pstate = to_dpu_plane_state(plane->state); - - if (!pstate) - continue; - - crtc_clk = max(pstate->plane_clk, crtc_clk); - } - - clk_factor = kms->catalog->perf.clk_inefficiency_factor; - if (clk_factor) - crtc_clk = mult_frac(crtc_clk, clk_factor, 100); - - return crtc_clk; -} - - static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -118,7 +51,12 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate = to_dpu_crtc_state(state); memset(perf, 0, sizeof(struct dpu_core_perf_params)); - if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { + if (!dpu_cstate->bw_control) { + perf->bw_ctl = kms->catalog->perf.max_bw_high * + 1000ULL; + perf->max_per_pipe_ib = perf->bw_ctl; + perf->core_clk_rate = kms->perf.max_core_clk_rate; + } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { perf->bw_ctl = 0; perf->max_per_pipe_ib = 0; perf->core_clk_rate = 0; @@ -126,10 +64,6 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, perf->bw_ctl = kms->perf.fix_core_ab_vote; perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote; perf->core_clk_rate = kms->perf.fix_core_clk_rate; - } else { - perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc); - perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib; - perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state); } DPU_DEBUG( @@ -181,7 +115,11 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n", tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, tmp_cstate->bw_control); - + /* + * For bw check only use the bw if the + * atomic property has been already set + */ + if (tmp_cstate->bw_control) bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } @@ -193,7 +131,9 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("final threshold bw limit = %d\n", threshold); - if (!threshold) { + if (!dpu_cstate->bw_control) { + DPU_DEBUG("bypass bandwidth check\n"); + } else if (!threshold) { DPU_ERROR("no bandwidth limits specified\n"); return -E2BIG; } else if (bw > threshold) { @@ -214,8 +154,7 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; - int i, ret = 0; - u64 avg_bw; + int ret = 0; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (tmp_crtc->enabled && @@ -226,21 +165,10 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, dpu_cstate->new_perf.max_per_pipe_ib); - perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; - - DPU_DEBUG("crtc=%d bw=%llu paths:%d\n", - tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl, kms->num_paths); + DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl); } } - - avg_bw = kms->num_paths ? - perf.bw_ctl / kms->num_paths : 0; - - for (i = 0; i < kms->num_paths; i++) - icc_set_bw(kms->path[i], - Bps_to_icc(avg_bw), (perf.max_per_pipe_ib)); - return ret; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 8f2357d9960a..29d4fde3172b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -541,8 +541,7 @@ static const struct dpu_perf_cfg sc7180_perf_data = { .max_bw_high = 6800000, .min_core_ib = 2400000, .min_llcc_ib = 800000, - .min_dram_ib = 1600000, - .min_prefill_lines = 24, + .min_dram_ib = 800000, .danger_lut_tbl = {0xff, 0xffff, 0x0}, .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc7180_qos_linear), @@ -559,8 +558,6 @@ static const struct dpu_perf_cfg sc7180_perf_data = { {.rd_enable = 1, .wr_enable = 1}, {.rd_enable = 1, .wr_enable = 0} }, - .clk_inefficiency_factor = 105, - .bw_inefficiency_factor = 120, }; /************************************************************* diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index f2a5fe2d9d62..f7de43838c69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -651,8 +651,6 @@ struct dpu_perf_cdp_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines - * @clk_inefficiency_factor DPU src clock inefficiency factor - * @bw_inefficiency_factor DPU axi bus bw inefficiency factor * @safe_lut_tbl: LUT tables for safe signals * @danger_lut_tbl: LUT tables for danger signals * @qos_lut_tbl: LUT tables for QoS signals @@ -677,8 +675,6 @@ struct dpu_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; - u32 clk_inefficiency_factor; - u32 bw_inefficiency_factor; u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index a5da7aacddba..b8615d4fe8a3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -303,28 +303,6 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) return 0; } -static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) -{ - struct icc_path *path0; - struct icc_path *path1; - struct drm_device *dev = dpu_kms->dev; - - path0 = of_icc_get(dev->dev, "mdp0-mem"); - path1 = of_icc_get(dev->dev, "mdp1-mem"); - - if (IS_ERR_OR_NULL(path0)) - return PTR_ERR_OR_ZERO(path0); - - dpu_kms->path[0] = path0; - dpu_kms->num_paths = 1; - - if (!IS_ERR_OR_NULL(path1)) { - dpu_kms->path[1] = path1; - dpu_kms->num_paths++; - } - return 0; -} - static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) { return dpu_crtc_vblank(crtc, true); @@ -994,9 +972,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_vbif_init_memtypes(dpu_kms); - if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) - dpu_kms_parse_data_bus_icc_path(dpu_kms); - pm_runtime_put_sync(&dpu_kms->pdev->dev); return 0; @@ -1102,7 +1077,7 @@ static int dpu_dev_remove(struct platform_device *pdev) static int __maybe_unused dpu_runtime_suspend(struct device *dev) { - int i, rc = -1; + int rc = -1; struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp; @@ -1111,9 +1086,6 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); - for (i = 0; i < dpu_kms->num_paths; i++) - icc_set_bw(dpu_kms->path[i], 0, 0); - return rc; } @@ -1125,15 +1097,8 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) struct drm_encoder *encoder; struct drm_device *ddev; struct dss_module_power *mp = &dpu_kms->mp; - int i; ddev = dpu_kms->dev; - - /* Min vote of BW is required before turning on AXI clk */ - for (i = 0; i < dpu_kms->num_paths; i++) - icc_set_bw(dpu_kms->path[i], 0, - dpu_kms->catalog->perf.min_dram_ib); - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) { DPU_ERROR("clock enable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 94410ca9bd70..4e32d040f1e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -8,8 +8,6 @@ #ifndef __DPU_KMS_H__ #define __DPU_KMS_H__ -#include - #include #include "msm_drv.h" @@ -139,8 +137,6 @@ struct dpu_kms { * when disabled. */ atomic_t bandwidth_ref; - struct icc_path *path[2]; - u32 num_paths; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index df0a9835bfb1..80d3cfc14007 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -8,6 +8,7 @@ #include #include #include "dpu_kms.h" +#include #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base) @@ -314,11 +315,9 @@ int dpu_mdss_init(struct drm_device *dev) } dpu_mdss->mmio_len = resource_size(res); - if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) { - ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); - if (ret) - return ret; - } + ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); + if (ret) + return ret; mp = &dpu_mdss->mp; ret = msm_dss_parse_clock(pdev, mp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index c2a6e3dacd68..3b9c33e694bf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -131,84 +131,6 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) return to_dpu_kms(priv->kms); } -/** - * _dpu_plane_calc_bw - calculate bandwidth required for a plane - * @Plane: Pointer to drm plane. - * Result: Updates calculated bandwidth in the plane state. - * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) - * Prefill BW Equation: line src bytes * line_time - */ -static void _dpu_plane_calc_bw(struct drm_plane *plane, - struct drm_framebuffer *fb) -{ - struct dpu_plane *pdpu = to_dpu_plane(plane); - struct dpu_plane_state *pstate; - struct drm_display_mode *mode; - const struct dpu_format *fmt = NULL; - struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); - int src_width, src_height, dst_height, fps; - u64 plane_prefill_bw; - u64 plane_bw; - u32 hw_latency_lines; - u32 scale_factor; - int vbp, vpw; - - pstate = to_dpu_plane_state(plane->state); - mode = &plane->state->crtc->mode; - - fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); - - src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect); - src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); - dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); - fps = drm_mode_vrefresh(mode); - vbp = mode->vtotal - mode->vsync_end; - vpw = mode->vsync_end - mode->vsync_start; - hw_latency_lines = dpu_kms->catalog->perf.min_prefill_lines; - scale_factor = src_height > dst_height ? - mult_frac(src_height, 1, dst_height) : 1; - - plane_bw = - src_width * mode->vtotal * fps * fmt->bpp * scale_factor; - - plane_prefill_bw = - src_width * hw_latency_lines * fps * fmt->bpp * scale_factor; - - plane_prefill_bw = mult_frac(plane_prefill_bw, mode->vtotal, (vbp+vpw)); - - pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw); -} - - -/** - * _dpu_plane_calc_clk - calculate clock required for a plane - * @Plane: Pointer to drm plane. - * Result: Updates calculated clock in the plane state. - * Clock equation: dst_w * v_total * fps * (src_h / dst_h) - */ -static void _dpu_plane_calc_clk(struct drm_plane *plane) -{ - struct dpu_plane *pdpu = to_dpu_plane(plane); - struct dpu_plane_state *pstate; - struct drm_display_mode *mode; - int dst_width, src_height, dst_height, fps; - - pstate = to_dpu_plane_state(plane->state); - mode = &plane->state->crtc->mode; - - src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); - dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect); - dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); - fps = drm_mode_vrefresh(mode); - - pstate->plane_clk = - dst_width * mode->vtotal * fps; - - if (src_height > dst_height) - pstate->plane_clk = mult_frac(pstate->plane_clk, - src_height, dst_height); -} - /** * _dpu_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane @@ -1180,10 +1102,6 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) } _dpu_plane_set_qos_remap(plane); - - _dpu_plane_calc_bw(plane, fb); - - _dpu_plane_calc_clk(plane); } static void _dpu_plane_atomic_disable(struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index ca83b8753d59..456949713e90 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -25,8 +25,6 @@ * @scaler3_cfg: configuration data for scaler3 * @pixel_ext: configuration data for pixel extensions * @cdp_cfg: CDP configuration - * @plane_fetch_bw: calculated BW per plane - * @plane_clk: calculated clk per plane */ struct dpu_plane_state { struct drm_plane_state base; @@ -41,8 +39,6 @@ struct dpu_plane_state { struct dpu_hw_pixel_ext pixel_ext; struct dpu_hw_pipe_cdp_cfg cdp_cfg; - u64 plane_fetch_bw; - u64 plane_clk; }; /** -- cgit v1.2.3