From 08f87f769b595151be1afeff53e144f543faa614 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 06 Dec 2023 09:51:13 +0000 Subject: [PATCH] add dts config --- kernel/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 291 ++++++++++++++++++++++++---------------------------------- 1 files changed, 121 insertions(+), 170 deletions(-) diff --git a/kernel/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/kernel/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 25691b7..9baaaef 100644 --- a/kernel/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/kernel/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -1,31 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <linux/delay.h> +#include <linux/interconnect.h> #include <linux/of_irq.h> + +#include <drm/drm_debugfs.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_vblank.h> #include "msm_drv.h" #include "msm_gem.h" #include "msm_mmu.h" #include "mdp5_kms.h" - -static const char *iommu_ports[] = { - "mdp_0", -}; static int mdp5_hw_init(struct msm_kms *kms) { @@ -144,46 +136,58 @@ state->mdp5_kms = mdp5_kms; - drm_atomic_private_obj_init(&mdp5_kms->glob_state, + drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state, &state->base, &mdp5_global_state_funcs); return 0; } +static void mdp5_enable_commit(struct msm_kms *kms) +{ + struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + pm_runtime_get_sync(&mdp5_kms->pdev->dev); +} + +static void mdp5_disable_commit(struct msm_kms *kms) +{ + struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + pm_runtime_put_sync(&mdp5_kms->pdev->dev); +} + static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); - struct device *dev = &mdp5_kms->pdev->dev; struct mdp5_global_state *global_state; global_state = mdp5_get_existing_global_state(mdp5_kms); - - pm_runtime_get_sync(dev); if (mdp5_kms->smp) mdp5_smp_prepare_commit(mdp5_kms->smp, &global_state->smp); } -static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) +static void mdp5_flush_commit(struct msm_kms *kms, unsigned crtc_mask) +{ + /* TODO */ +} + +static void mdp5_wait_flush(struct msm_kms *kms, unsigned crtc_mask) { struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); - struct device *dev = &mdp5_kms->pdev->dev; - struct mdp5_global_state *global_state; + struct drm_crtc *crtc; - drm_atomic_helper_wait_for_vblanks(mdp5_kms->dev, state); + for_each_crtc_mask(mdp5_kms->dev, crtc, crtc_mask) + mdp5_crtc_wait_for_commit_done(crtc); +} + +static void mdp5_complete_commit(struct msm_kms *kms, unsigned crtc_mask) +{ + struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + struct mdp5_global_state *global_state; global_state = mdp5_get_existing_global_state(mdp5_kms); if (mdp5_kms->smp) mdp5_smp_complete_commit(mdp5_kms->smp, &global_state->smp); - - pm_runtime_put_sync(dev); -} - -static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms, - struct drm_crtc *crtc) -{ - mdp5_crtc_wait_for_commit_done(crtc); } static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, @@ -225,8 +229,7 @@ mdp5_pipe_destroy(mdp5_kms->hwpipes[i]); if (aspace) { - aspace->mmu->funcs->detach(aspace->mmu, - iommu_ports, ARRAY_SIZE(iommu_ports)); + aspace->mmu->funcs->detach(aspace->mmu); msm_gem_address_space_put(aspace); } } @@ -256,17 +259,9 @@ static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) { - struct drm_device *dev = minor->dev; - int ret; - - ret = drm_debugfs_create_files(mdp5_debugfs_list, - ARRAY_SIZE(mdp5_debugfs_list), - minor->debugfs_root, minor); - - if (ret) { - dev_err(dev->dev, "could not install mdp5_debugfs_list\n"); - return ret; - } + drm_debugfs_create_files(mdp5_debugfs_list, + ARRAY_SIZE(mdp5_debugfs_list), + minor->debugfs_root, minor); return 0; } @@ -281,9 +276,12 @@ .irq = mdp5_irq, .enable_vblank = mdp5_enable_vblank, .disable_vblank = mdp5_disable_vblank, + .flush_commit = mdp5_flush_commit, + .enable_commit = mdp5_enable_commit, + .disable_commit = mdp5_disable_commit, .prepare_commit = mdp5_prepare_commit, + .wait_flush = mdp5_wait_flush, .complete_commit = mdp5_complete_commit, - .wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done, .get_format = mdp_get_format, .round_pixclk = mdp5_round_pixclk, .set_split_display = mdp5_set_split_display, @@ -303,6 +301,10 @@ mdp5_kms->enable_count--; WARN_ON(mdp5_kms->enable_count < 0); + if (mdp5_kms->tbu_rt_clk) + clk_disable_unprepare(mdp5_kms->tbu_rt_clk); + if (mdp5_kms->tbu_clk) + clk_disable_unprepare(mdp5_kms->tbu_clk); clk_disable_unprepare(mdp5_kms->ahb_clk); clk_disable_unprepare(mdp5_kms->axi_clk); clk_disable_unprepare(mdp5_kms->core_clk); @@ -323,6 +325,10 @@ clk_prepare_enable(mdp5_kms->core_clk); if (mdp5_kms->lut_clk) clk_prepare_enable(mdp5_kms->lut_clk); + if (mdp5_kms->tbu_clk) + clk_prepare_enable(mdp5_kms->tbu_clk); + if (mdp5_kms->tbu_rt_clk) + clk_prepare_enable(mdp5_kms->tbu_rt_clk); return 0; } @@ -337,7 +343,7 @@ encoder = mdp5_encoder_init(dev, intf, ctl); if (IS_ERR(encoder)) { - dev_err(dev->dev, "failed to construct encoder\n"); + DRM_DEV_ERROR(dev->dev, "failed to construct encoder\n"); return encoder; } @@ -418,7 +424,7 @@ int dsi_id = get_dsi_id_from_intf(hw_cfg, intf->num); if ((dsi_id >= ARRAY_SIZE(priv->dsi)) || (dsi_id < 0)) { - dev_err(dev->dev, "failed to find dsi from intf %d\n", + DRM_DEV_ERROR(dev->dev, "failed to find dsi from intf %d\n", intf->num); ret = -EINVAL; break; @@ -443,7 +449,7 @@ break; } default: - dev_err(dev->dev, "unknown intf: %d\n", intf->type); + DRM_DEV_ERROR(dev->dev, "unknown intf: %d\n", intf->type); ret = -EINVAL; break; } @@ -455,13 +461,10 @@ { struct drm_device *dev = mdp5_kms->dev; struct msm_drm_private *priv = dev->dev_private; - const struct mdp5_cfg_hw *hw_cfg; unsigned int num_crtcs; int i, ret, pi = 0, ci = 0; struct drm_plane *primary[MAX_BASES] = { NULL }; struct drm_plane *cursor[MAX_BASES] = { NULL }; - - hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); /* * Construct encoders and modeset initialize connector devices @@ -500,7 +503,7 @@ plane = mdp5_plane_init(dev, type); if (IS_ERR(plane)) { ret = PTR_ERR(plane); - dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret); + DRM_DEV_ERROR(dev->dev, "failed to construct plane %d (%d)\n", i, ret); goto fail; } priv->planes[priv->num_planes++] = plane; @@ -517,7 +520,7 @@ crtc = mdp5_crtc_init(dev, primary[i], cursor[i], i); if (IS_ERR(crtc)) { ret = PTR_ERR(crtc); - dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); + DRM_DEV_ERROR(dev->dev, "failed to construct crtc %d (%d)\n", i, ret); goto fail; } priv->crtcs[priv->num_crtcs++] = crtc; @@ -552,7 +555,7 @@ *major = FIELD(version, MDP5_HW_VERSION_MAJOR); *minor = FIELD(version, MDP5_HW_VERSION_MINOR); - dev_info(dev, "MDP5 version v%d.%d", *major, *minor); + DRM_DEV_INFO(dev, "MDP5 version v%d.%d", *major, *minor); } static int get_clk(struct platform_device *pdev, struct clk **clkp, @@ -561,7 +564,7 @@ struct device *dev = &pdev->dev; struct clk *clk = msm_clk_get(pdev, name); if (IS_ERR(clk) && mandatory) { - dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk)); + DRM_DEV_ERROR(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk)); return PTR_ERR(clk); } if (IS_ERR(clk)) @@ -570,98 +573,6 @@ *clkp = clk; return 0; -} - -static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_encoder *encoder; - - drm_for_each_encoder(encoder, dev) - if (encoder->crtc == crtc) - return encoder; - - return NULL; -} - -static bool mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe, - bool in_vblank_irq, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) -{ - struct msm_drm_private *priv = dev->dev_private; - struct drm_crtc *crtc; - struct drm_encoder *encoder; - int line, vsw, vbp, vactive_start, vactive_end, vfp_end; - - crtc = priv->crtcs[pipe]; - if (!crtc) { - DRM_ERROR("Invalid crtc %d\n", pipe); - return false; - } - - encoder = get_encoder_from_crtc(crtc); - if (!encoder) { - DRM_ERROR("no encoder found for crtc %d\n", pipe); - return false; - } - - vsw = mode->crtc_vsync_end - mode->crtc_vsync_start; - vbp = mode->crtc_vtotal - mode->crtc_vsync_end; - - /* - * the line counter is 1 at the start of the VSYNC pulse and VTOTAL at - * the end of VFP. Translate the porch values relative to the line - * counter positions. - */ - - vactive_start = vsw + vbp + 1; - - vactive_end = vactive_start + mode->crtc_vdisplay; - - /* last scan line before VSYNC */ - vfp_end = mode->crtc_vtotal; - - if (stime) - *stime = ktime_get(); - - line = mdp5_encoder_get_linecount(encoder); - - if (line < vactive_start) { - line -= vactive_start; - } else if (line > vactive_end) { - line = line - vfp_end - vactive_start; - } else { - line -= vactive_start; - } - - *vpos = line; - *hpos = 0; - - if (etime) - *etime = ktime_get(); - - return true; -} - -static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int pipe) -{ - struct msm_drm_private *priv = dev->dev_private; - struct drm_crtc *crtc; - struct drm_encoder *encoder; - - if (pipe >= priv->num_crtcs) - return 0; - - crtc = priv->crtcs[pipe]; - if (!crtc) - return 0; - - encoder = get_encoder_from_crtc(crtc); - if (!encoder) - return 0; - - return mdp5_encoder_get_framecount(encoder); } struct msm_kms *mdp5_kms_init(struct drm_device *dev) @@ -673,6 +584,7 @@ struct msm_kms *kms; struct msm_gem_address_space *aspace; int irq, i, ret; + struct device *iommu_dev; /* priv->kms would have been populated by the MDP5 driver */ kms = priv->kms; @@ -686,9 +598,9 @@ pdev = mdp5_kms->pdev; irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (irq < 0) { - ret = irq; - dev_err(&pdev->dev, "failed to get irq: %d\n", ret); + if (!irq) { + ret = -EINVAL; + DRM_DEV_ERROR(&pdev->dev, "failed to get irq\n"); goto fail; } @@ -712,24 +624,27 @@ mdelay(16); if (config->platform.iommu) { - aspace = msm_gem_address_space_create(&pdev->dev, - config->platform.iommu, "mdp5"); + struct msm_mmu *mmu; + + iommu_dev = &pdev->dev; + if (!dev_iommu_fwspec_get(iommu_dev)) + iommu_dev = iommu_dev->parent; + + mmu = msm_iommu_new(iommu_dev, config->platform.iommu); + + aspace = msm_gem_address_space_create(mmu, "mdp5", + 0x1000, 0x100000000 - 0x1000); + if (IS_ERR(aspace)) { + if (!IS_ERR(mmu)) + mmu->funcs->destroy(mmu); ret = PTR_ERR(aspace); goto fail; } kms->aspace = aspace; - - ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports, - ARRAY_SIZE(iommu_ports)); - if (ret) { - dev_err(&pdev->dev, "failed to attach iommu: %d\n", - ret); - goto fail; - } } else { - dev_info(&pdev->dev, + DRM_DEV_INFO(&pdev->dev, "no iommu, fallback to phys contig buffers for scanout\n"); aspace = NULL; } @@ -738,7 +653,7 @@ ret = modeset_init(mdp5_kms); if (ret) { - dev_err(&pdev->dev, "modeset_init failed: %d\n", ret); + DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret); goto fail; } @@ -747,10 +662,7 @@ dev->mode_config.max_width = 0xffff; dev->mode_config.max_height = 0xffff; - dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; - dev->driver->get_scanout_position = mdp5_get_scanoutpos; - dev->driver->get_vblank_counter = mdp5_get_vblank_counter; - dev->max_vblank_count = 0xffffffff; + dev->max_vblank_count = 0; /* max_vblank_count is set on each CRTC */ dev->vblank_disable_immediate = true; return kms; @@ -795,7 +707,7 @@ hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps); if (IS_ERR(hwpipe)) { ret = PTR_ERR(hwpipe); - dev_err(dev->dev, "failed to construct pipe for %s (%d)\n", + DRM_DEV_ERROR(dev->dev, "failed to construct pipe for %s (%d)\n", pipe2name(pipes[i]), ret); return ret; } @@ -867,7 +779,7 @@ mixer = mdp5_mixer_init(&hw_cfg->lm.instances[i]); if (IS_ERR(mixer)) { ret = PTR_ERR(mixer); - dev_err(dev->dev, "failed to construct LM%d (%d)\n", + DRM_DEV_ERROR(dev->dev, "failed to construct LM%d (%d)\n", i, ret); return ret; } @@ -897,7 +809,7 @@ intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) { - dev_err(dev->dev, "failed to construct INTF%d\n", i); + DRM_DEV_ERROR(dev->dev, "failed to construct INTF%d\n", i); return -ENOMEM; } @@ -958,6 +870,8 @@ /* optional clocks: */ get_clk(pdev, &mdp5_kms->lut_clk, "lut", false); + get_clk(pdev, &mdp5_kms->tbu_clk, "tbu", false); + get_clk(pdev, &mdp5_kms->tbu_rt_clk, "tbu_rt", false); /* we need to set a default rate before enabling. Set a safe * rate first, then figure out hw revision, and then set a @@ -1049,9 +963,46 @@ .unbind = mdp5_unbind, }; +static int mdp5_setup_interconnect(struct platform_device *pdev) +{ + struct icc_path *path0 = of_icc_get(&pdev->dev, "mdp0-mem"); + struct icc_path *path1 = of_icc_get(&pdev->dev, "mdp1-mem"); + struct icc_path *path_rot = of_icc_get(&pdev->dev, "rotator-mem"); + + if (IS_ERR(path0)) + return PTR_ERR(path0); + + if (!path0) { + /* no interconnect support is not necessarily a fatal + * condition, the platform may simply not have an + * interconnect driver yet. But warn about it in case + * bootloader didn't setup bus clocks high enough for + * scanout. + */ + dev_warn(&pdev->dev, "No interconnect support may cause display underflows!\n"); + return 0; + } + + icc_set_bw(path0, 0, MBps_to_icc(6400)); + + if (!IS_ERR_OR_NULL(path1)) + icc_set_bw(path1, 0, MBps_to_icc(6400)); + if (!IS_ERR_OR_NULL(path_rot)) + icc_set_bw(path_rot, 0, MBps_to_icc(6400)); + + return 0; +} + static int mdp5_dev_probe(struct platform_device *pdev) { + int ret; + DBG(""); + + ret = mdp5_setup_interconnect(pdev); + if (ret) + return ret; + return component_add(&pdev->dev, &mdp5_ops); } -- Gitblit v1.6.2