diff options
-rw-r--r-- | Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml | 6 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml | 333 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/msm_disp_snapshot.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_debugfs.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 89 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_fbdev.c | 173 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem_submit.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_io_utils.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_mdss.c | 198 | ||||
-rw-r--r-- | include/uapi/drm/msm_drm.h | 4 |
11 files changed, 630 insertions, 206 deletions
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml index 4c6929e2534c..f26eb5643aed 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml @@ -54,7 +54,7 @@ patternProperties: type: object properties: compatible: - const: qcom,dsi-phy-5nm-8450 + const: qcom,sm8450-dsi-phy-5nm required: - compatible @@ -254,7 +254,7 @@ examples: }; dsi0_phy: phy@ae94400 { - compatible = "qcom,dsi-phy-5nm-8450"; + compatible = "qcom,sm8450-dsi-phy-5nm"; reg = <0x0ae94400 0x200>, <0x0ae94600 0x280>, <0x0ae94900 0x260>; @@ -325,7 +325,7 @@ examples: }; dsi1_phy: phy@ae96400 { - compatible = "qcom,dsi-phy-5nm-8450"; + compatible = "qcom,sm8450-dsi-phy-5nm"; reg = <0x0ae96400 0x200>, <0x0ae96600 0x280>, <0x0ae96900 0x260>; diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml new file mode 100644 index 000000000000..887be33ba108 --- /dev/null +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8550-mdss.yaml @@ -0,0 +1,333 @@ +# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/msm/qcom,sm8550-mdss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8550 Display MDSS + +maintainers: + - Neil Armstrong <[email protected]> + +description: + SM8550 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like + DPU display controller, DSI and DP interfaces etc. + +$ref: /schemas/display/msm/mdss-common.yaml# + +properties: + compatible: + const: qcom,sm8550-mdss + + clocks: + items: + - description: Display MDSS AHB + - description: Display AHB + - description: Display hf AXI + - description: Display core + + iommus: + maxItems: 1 + + interconnects: + maxItems: 2 + + interconnect-names: + maxItems: 2 + +patternProperties: + "^display-controller@[0-9a-f]+$": + type: object + properties: + compatible: + const: qcom,sm8550-dpu + + "^dsi@[0-9a-f]+$": + type: object + properties: + compatible: + items: + - const: qcom,sm8550-dsi-ctrl + - const: qcom,mdss-dsi-ctrl + + "^phy@[0-9a-f]+$": + type: object + properties: + compatible: + const: qcom,sm8550-dsi-phy-4nm + +required: + - compatible + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,sm8550-dispcc.h> + #include <dt-bindings/clock/qcom,sm8550-gcc.h> + #include <dt-bindings/clock/qcom,rpmh.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interconnect/qcom,sm8550-rpmh.h> + #include <dt-bindings/power/qcom-rpmpd.h> + + display-subsystem@ae00000 { + compatible = "qcom,sm8550-mdss"; + reg = <0x0ae00000 0x1000>; + reg-names = "mdss"; + + interconnects = <&mmss_noc MASTER_MDP 0 &gem_noc SLAVE_LLCC 0>, + <&mc_virt MASTER_LLCC 0 &mc_virt SLAVE_EBI1 0>; + interconnect-names = "mdp0-mem", "mdp1-mem"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc MDSS_GDSC>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "nrt_bus", "core"; + + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu 0x1c00 0x2>; + + #address-cells = <1>; + #size-cells = <1>; + ranges; + + display-controller@ae01000 { + compatible = "qcom,sm8550-dpu"; + reg = <0x0ae01000 0x8f000>, + <0x0aeb0000 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&gcc GCC_DISP_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <19200000>; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd SM8550_MMCX>; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + }; + + mdp_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200000000 { + opp-hz = /bits/ 64 <200000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-325000000 { + opp-hz = /bits/ 64 <325000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-375000000 { + opp-hz = /bits/ 64 <375000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + + opp-514000000 { + opp-hz = /bits/ 64 <514000000>; + required-opps = <&rpmhpd_opp_nom>; + }; + }; + }; + + dsi@ae94000 { + compatible = "qcom,sm8550-dsi-ctrl", "qcom,mdss-dsi-ctrl"; + reg = <0x0ae94000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <4>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>, + <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK>, + <&dispcc DISP_CC_MDSS_ESC0_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, + <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>; + assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SM8550_MMCX>; + + phys = <&dsi0_phy>; + phy-names = "dsi"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi0_in: endpoint { + remote-endpoint = <&dpu_intf1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi0_out: endpoint { + }; + }; + }; + + dsi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-187500000 { + opp-hz = /bits/ 64 <187500000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-358000000 { + opp-hz = /bits/ 64 <358000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; + + dsi0_phy: phy@ae94400 { + compatible = "qcom,sm8550-dsi-phy-4nm"; + reg = <0x0ae95000 0x200>, + <0x0ae95200 0x280>, + <0x0ae95500 0x400>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "ref"; + }; + + dsi@ae96000 { + compatible = "qcom,sm8550-dsi-ctrl", "qcom,mdss-dsi-ctrl"; + reg = <0x0ae96000 0x400>; + reg-names = "dsi_ctrl"; + + interrupt-parent = <&mdss>; + interrupts = <5>; + + clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>, + <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>, + <&dispcc DISP_CC_MDSS_PCLK1_CLK>, + <&dispcc DISP_CC_MDSS_ESC1_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&gcc GCC_DISP_HF_AXI_CLK>; + clock-names = "byte", + "byte_intf", + "pixel", + "core", + "iface", + "bus"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>, + <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>; + assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>; + + operating-points-v2 = <&dsi_opp_table>; + power-domains = <&rpmhpd SM8550_MMCX>; + + phys = <&dsi1_phy>; + phy-names = "dsi"; + + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi1_in: endpoint { + remote-endpoint = <&dpu_intf2_out>; + }; + }; + + port@1 { + reg = <1>; + dsi1_out: endpoint { + }; + }; + }; + }; + + dsi1_phy: phy@ae96400 { + compatible = "qcom,sm8550-dsi-phy-4nm"; + reg = <0x0ae97000 0x200>, + <0x0ae97200 0x280>, + <0x0ae97500 0x400>; + reg-names = "dsi_phy", + "dsi_phy_lane", + "dsi_pll"; + + #clock-cells = <1>; + #phy-cells = <0>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "ref"; + }; + }; +... diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c index b73031cd48e4..e75b97127c0d 100644 --- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c +++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot.c @@ -129,9 +129,6 @@ void msm_disp_snapshot_destroy(struct drm_device *drm_dev) } priv = drm_dev->dev_private; - if (!priv->kms) - return; - kms = priv->kms; if (kms->dump_worker) diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c index d6ecff0ab618..9c0e633a3a61 100644 --- a/drivers/gpu/drm/msm/msm_debugfs.c +++ b/drivers/gpu/drm/msm/msm_debugfs.c @@ -10,6 +10,7 @@ #include <linux/fault-inject.h> #include <drm/drm_debugfs.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_file.h> #include <drm/drm_framebuffer.h> @@ -241,12 +242,11 @@ static int msm_fb_show(struct seq_file *m, void *arg) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct msm_drm_private *priv = dev->dev_private; struct drm_framebuffer *fb, *fbdev_fb = NULL; - if (priv->fbdev) { + if (dev->fb_helper && dev->fb_helper->fb) { seq_printf(m, "fbcon "); - fbdev_fb = priv->fbdev->fb; + fbdev_fb = dev->fb_helper->fb; msm_framebuffer_describe(fbdev_fb, m); } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index ecf42f40f289..b4cfa44a8a5c 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -8,10 +8,12 @@ #include <linux/dma-mapping.h> #include <linux/fault-inject.h> #include <linux/kthread.h> +#include <linux/of_address.h> #include <linux/sched/mm.h> #include <linux/uaccess.h> #include <uapi/linux/sched/types.h> +#include <drm/drm_aperture.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> @@ -52,9 +54,10 @@ #define MSM_VERSION_MINOR 10 #define MSM_VERSION_PATCHLEVEL 0 +static void msm_deinit_vram(struct drm_device *ddev); + static const struct drm_mode_config_funcs mode_config_funcs = { .fb_create = msm_framebuffer_create, - .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = msm_atomic_check, .atomic_commit = drm_atomic_helper_commit, }; @@ -63,12 +66,6 @@ static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = { .atomic_commit_tail = msm_atomic_commit_tail, }; -#ifdef CONFIG_DRM_FBDEV_EMULATION -static bool fbdev = true; -MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer"); -module_param(fbdev, bool, 0600); -#endif - static char *vram = "16m"; MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU)"); module_param(vram, charp, 0); @@ -151,9 +148,6 @@ static void msm_irq_uninstall(struct drm_device *dev) struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; - if (!priv->kms) - return; - kms->funcs->irq_uninstall(kms); if (kms->irq_requested) free_irq(kms->irq, dev); @@ -241,12 +235,8 @@ static int msm_drm_uninit(struct device *dev) msm_perf_debugfs_cleanup(priv); msm_rd_debugfs_cleanup(priv); -#ifdef CONFIG_DRM_FBDEV_EMULATION - if (fbdev && priv->fbdev) - msm_fbdev_free(ddev); -#endif - - msm_disp_snapshot_destroy(ddev); + if (kms) + msm_disp_snapshot_destroy(ddev); drm_mode_config_cleanup(ddev); @@ -254,30 +244,27 @@ static int msm_drm_uninit(struct device *dev) drm_bridge_remove(priv->bridges[i]); priv->num_bridges = 0; - pm_runtime_get_sync(dev); - msm_irq_uninstall(ddev); - pm_runtime_put_sync(dev); + if (kms) { + pm_runtime_get_sync(dev); + msm_irq_uninstall(ddev); + pm_runtime_put_sync(dev); + } if (kms && kms->funcs) kms->funcs->destroy(kms); - if (priv->vram.paddr) { - unsigned long attrs = DMA_ATTR_NO_KERNEL_MAPPING; - drm_mm_takedown(&priv->vram.mm); - dma_free_attrs(dev, priv->vram.size, NULL, - priv->vram.paddr, attrs); - } + msm_deinit_vram(ddev); component_unbind_all(dev, ddev); ddev->dev_private = NULL; + drm_dev_put(ddev); + destroy_workqueue(priv->wq); return 0; } -#include <linux/of_address.h> - struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev) { struct msm_gem_address_space *aspace; @@ -402,6 +389,19 @@ static int msm_init_vram(struct drm_device *dev) return ret; } +static void msm_deinit_vram(struct drm_device *ddev) +{ + struct msm_drm_private *priv = ddev->dev_private; + unsigned long attrs = DMA_ATTR_NO_KERNEL_MAPPING; + + if (!priv->vram.paddr) + return; + + drm_mm_takedown(&priv->vram.mm); + dma_free_attrs(ddev->dev, priv->vram.size, NULL, priv->vram.paddr, + attrs); +} + static int msm_drm_init(struct device *dev, const struct drm_driver *drv) { struct msm_drm_private *priv = dev_get_drvdata(dev); @@ -421,8 +421,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) priv->dev = ddev; priv->wq = alloc_ordered_workqueue("msm", 0); - if (!priv->wq) - return -ENOMEM; + if (!priv->wq) { + ret = -ENOMEM; + goto err_put_dev; + } INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); @@ -445,12 +447,17 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) ret = msm_init_vram(ddev); if (ret) - goto err_drm_dev_put; + goto err_cleanup_mode_config; /* Bind all our sub-components: */ ret = component_bind_all(dev, ddev); if (ret) - goto err_drm_dev_put; + goto err_deinit_vram; + + /* the fw fb could be anywhere in memory */ + ret = drm_aperture_remove_framebuffers(false, drv); + if (ret) + goto err_msm_uninit; dma_set_max_seg_size(dev, UINT_MAX); @@ -530,23 +537,30 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) } drm_mode_config_reset(ddev); -#ifdef CONFIG_DRM_FBDEV_EMULATION - if (kms && fbdev) - priv->fbdev = msm_fbdev_init(ddev); -#endif - ret = msm_debugfs_late_init(ddev); if (ret) goto err_msm_uninit; drm_kms_helper_poll_init(ddev); + if (kms) + msm_fbdev_setup(ddev); + return 0; err_msm_uninit: msm_drm_uninit(dev); -err_drm_dev_put: + + return ret; + +err_deinit_vram: + msm_deinit_vram(ddev); +err_cleanup_mode_config: + drm_mode_config_cleanup(ddev); + destroy_workqueue(priv->wq); +err_put_dev: drm_dev_put(ddev); + return ret; } @@ -1070,7 +1084,6 @@ static const struct drm_driver msm_driver = { DRIVER_SYNCOBJ, .open = msm_open, .postclose = msm_postclose, - .lastclose = drm_fb_helper_lastclose, .dumb_create = msm_gem_dumb_create, .dumb_map_offset = msm_gem_dumb_map_offset, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index aefee23adea1..e13a8cbd61c9 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -29,7 +29,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_fb_helper.h> #include <drm/display/drm_dsc.h> #include <drm/msm_drm.h> #include <drm/drm_gem.h> @@ -129,8 +128,6 @@ struct msm_drm_private { bool is_a2xx; bool has_cached_coherent; - struct drm_fb_helper *fbdev; - struct msm_rd_state *rd; /* debugfs to dump all submits */ struct msm_rd_state *hangrd; /* debugfs to dump hanging submits */ struct msm_perf_state *perf; @@ -307,8 +304,13 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, struct drm_framebuffer * msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format); -struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); -void msm_fbdev_free(struct drm_device *dev); +#ifdef CONFIG_DRM_FBDEV_EMULATION +void msm_fbdev_setup(struct drm_device *dev); +#else +static inline void msm_fbdev_setup(struct drm_device *dev) +{ +} +#endif struct hdmi; #ifdef CONFIG_DRM_MSM_HDMI @@ -549,7 +551,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); } - return clamp(remaining_jiffies, 0LL, (s64)INT_MAX); + return clamp(remaining_jiffies, 1LL, (s64)INT_MAX); } /* Driver helpers */ diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index d26aa52217ce..2ebc86381e1c 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -4,8 +4,8 @@ * Author: Rob Clark <[email protected]> */ -#include <drm/drm_aperture.h> -#include <drm/drm_crtc.h> +#include <drm/drm_drv.h> +#include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> @@ -15,18 +15,40 @@ #include "msm_gem.h" #include "msm_kms.h" -static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma); +static bool fbdev = true; +MODULE_PARM_DESC(fbdev, "Enable fbdev compat layer"); +module_param(fbdev, bool, 0600); /* * fbdev funcs, to implement legacy fbdev interface on top of drm driver */ -#define to_msm_fbdev(x) container_of(x, struct msm_fbdev, base) +static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; + struct drm_gem_object *bo = msm_framebuffer_bo(helper->fb, 0); -struct msm_fbdev { - struct drm_fb_helper base; - struct drm_framebuffer *fb; -}; + return drm_gem_prime_mmap(bo, vma); +} + +static void msm_fbdev_fb_destroy(struct fb_info *info) +{ + struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; + struct drm_framebuffer *fb = helper->fb; + struct drm_gem_object *bo = msm_framebuffer_bo(fb, 0); + + DBG(); + + drm_fb_helper_fini(helper); + + /* this will free the backing object */ + msm_gem_put_vaddr(bo); + drm_framebuffer_remove(fb); + + drm_client_release(&helper->client); + drm_fb_helper_unprepare(helper); + kfree(helper); +} static const struct fb_ops msm_fb_ops = { .owner = THIS_MODULE, @@ -41,21 +63,12 @@ static const struct fb_ops msm_fb_ops = { .fb_copyarea = drm_fb_helper_sys_copyarea, .fb_imageblit = drm_fb_helper_sys_imageblit, .fb_mmap = msm_fbdev_mmap, + .fb_destroy = msm_fbdev_fb_destroy, }; -static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; - struct msm_fbdev *fbdev = to_msm_fbdev(helper); - struct drm_gem_object *bo = msm_framebuffer_bo(fbdev->fb, 0); - - return drm_gem_prime_mmap(bo, vma); -} - static int msm_fbdev_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { - struct msm_fbdev *fbdev = to_msm_fbdev(helper); struct drm_device *dev = helper->dev; struct msm_drm_private *priv = dev->dev_private; struct drm_framebuffer *fb = NULL; @@ -102,7 +115,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, DBG("fbi=%p, dev=%p", fbi, dev); - fbdev->fb = fb; helper->fb = fb; fbi->fbops = &msm_fb_ops; @@ -119,7 +131,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, fbi->fix.smem_len = bo->size; DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); - DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height); + DBG("allocated %dx%d fb", fb->width, fb->height); return 0; @@ -132,73 +144,98 @@ static const struct drm_fb_helper_funcs msm_fb_helper_funcs = { .fb_probe = msm_fbdev_create, }; -/* initialize fbdev helper */ -struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) +/* + * struct drm_client + */ + +static void msm_fbdev_client_unregister(struct drm_client_dev *client) { - struct msm_drm_private *priv = dev->dev_private; - struct msm_fbdev *fbdev; - struct drm_fb_helper *helper; - int ret; + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + + if (fb_helper->info) { + drm_fb_helper_unregister_info(fb_helper); + } else { + drm_client_release(&fb_helper->client); + drm_fb_helper_unprepare(fb_helper); + kfree(fb_helper); + } +} - fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); - if (!fbdev) - return NULL; +static int msm_fbdev_client_restore(struct drm_client_dev *client) +{ + drm_fb_helper_lastclose(client->dev); - helper = &fbdev->base; + return 0; +} - drm_fb_helper_prepare(dev, helper, 32, &msm_fb_helper_funcs); +static int msm_fbdev_client_hotplug(struct drm_client_dev *client) +{ + struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); + struct drm_device *dev = client->dev; + int ret; - ret = drm_fb_helper_init(dev, helper); - if (ret) { - DRM_DEV_ERROR(dev->dev, "could not init fbdev: ret=%d\n", ret); - goto fail; - } + if (dev->fb_helper) + return drm_fb_helper_hotplug_event(dev->fb_helper); - /* the fw fb could be anywhere in memory */ - ret = drm_aperture_remove_framebuffers(false, dev->driver); + ret = drm_fb_helper_init(dev, fb_helper); if (ret) - goto fini; + goto err_drm_err; - ret = drm_fb_helper_initial_config(helper); - if (ret) - goto fini; + if (!drm_drv_uses_atomic_modeset(dev)) + drm_helper_disable_unused_functions(dev); - priv->fbdev = helper; + ret = drm_fb_helper_initial_config(fb_helper); + if (ret) + goto err_drm_fb_helper_fini; - return helper; + return 0; -fini: - drm_fb_helper_fini(helper); -fail: - drm_fb_helper_unprepare(helper); - kfree(fbdev); - return NULL; +err_drm_fb_helper_fini: + drm_fb_helper_fini(fb_helper); +err_drm_err: + drm_err(dev, "Failed to setup fbdev emulation (ret=%d)\n", ret); + return ret; } -void msm_fbdev_free(struct drm_device *dev) -{ - struct msm_drm_private *priv = dev->dev_private; - struct drm_fb_helper *helper = priv->fbdev; - struct msm_fbdev *fbdev; +static const struct drm_client_funcs msm_fbdev_client_funcs = { + .owner = THIS_MODULE, + .unregister = msm_fbdev_client_unregister, + .restore = msm_fbdev_client_restore, + .hotplug = msm_fbdev_client_hotplug, +}; - DBG(); +/* initialize fbdev helper */ +void msm_fbdev_setup(struct drm_device *dev) +{ + struct drm_fb_helper *helper; + int ret; - drm_fb_helper_unregister_info(helper); + if (!fbdev) + return; - drm_fb_helper_fini(helper); + drm_WARN(dev, !dev->registered, "Device has not been registered.\n"); + drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n"); - fbdev = to_msm_fbdev(priv->fbdev); + helper = kzalloc(sizeof(*helper), GFP_KERNEL); + if (!helper) + return; + drm_fb_helper_prepare(dev, helper, 32, &msm_fb_helper_funcs); - /* this will free the backing object */ - if (fbdev->fb) { - struct drm_gem_object *bo = - msm_framebuffer_bo(fbdev->fb, 0); - msm_gem_put_vaddr(bo); - drm_framebuffer_remove(fbdev->fb); + ret = drm_client_init(dev, &helper->client, "fbdev", &msm_fbdev_client_funcs); + if (ret) { + drm_err(dev, "Failed to register client: %d\n", ret); + goto err_drm_fb_helper_unprepare; } - drm_fb_helper_unprepare(helper); - kfree(fbdev); + ret = msm_fbdev_client_hotplug(&helper->client); + if (ret) + drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); + + drm_client_register(&helper->client); - priv->fbdev = NULL; + return; + +err_drm_fb_helper_unprepare: + drm_fb_helper_unprepare(helper); + kfree(helper); } diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 89375c2e422b..aff18c2f600a 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -573,7 +573,6 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit, 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), @@ -593,12 +592,8 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit, break; } - ret = drm_syncobj_find_fence(file, syncobj_desc.handle, - syncobj_desc.point, 0, &fence); - if (ret) - break; - - ret = drm_sched_job_add_dependency(&submit->base, fence); + ret = drm_sched_job_add_syncobj_dependency(&submit->base, file, + syncobj_desc.handle, syncobj_desc.point); if (ret) break; diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c index d02cd29ce829..59d2788c4510 100644 --- a/drivers/gpu/drm/msm/msm_io_utils.c +++ b/drivers/gpu/drm/msm/msm_io_utils.c @@ -6,6 +6,7 @@ */ #include <linux/interconnect.h> +#include <linux/io.h> #include "msm_drv.h" diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 02646e4bb4cd..e8c93731aaa1 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -16,9 +16,6 @@ #include "msm_drv.h" #include "msm_kms.h" -/* for DPU_HW_* defines */ -#include "disp/dpu1/dpu_hw_catalog.h" - #define HW_REV 0x0 #define HW_INTR_STATUS 0x0010 @@ -29,6 +26,16 @@ #define MIN_IB_BW 400000000UL /* Min ib vote 400MB */ +struct msm_mdss_data { + u32 ubwc_version; + /* can be read from register 0x58 */ + u32 ubwc_dec_version; + u32 ubwc_swizzle; + u32 ubwc_static; + u32 highest_bank_bit; + u32 macrotile_mode; +}; + struct msm_mdss { struct device *dev; @@ -40,6 +47,7 @@ struct msm_mdss { unsigned long enabled_mask; struct irq_domain *domain; } irq_controller; + const struct msm_mdss_data *mdss_data; struct icc_path *path[2]; u32 num_paths; }; @@ -182,46 +190,40 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss) #define UBWC_3_0 0x30000000 #define UBWC_4_0 0x40000000 -static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss, - u32 ubwc_static) +static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss) { - writel_relaxed(ubwc_static, msm_mdss->mmio + UBWC_STATIC); + const struct msm_mdss_data *data = msm_mdss->mdss_data; + + writel_relaxed(data->ubwc_static, msm_mdss->mmio + UBWC_STATIC); } -static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss, - unsigned int ubwc_version, - u32 ubwc_swizzle, - u32 highest_bank_bit, - u32 macrotile_mode) +static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss) { - u32 value = (ubwc_swizzle & 0x1) | - (highest_bank_bit & 0x3) << 4 | - (macrotile_mode & 0x1) << 12; + const struct msm_mdss_data *data = msm_mdss->mdss_data; + u32 value = (data->ubwc_swizzle & 0x1) | + (data->highest_bank_bit & 0x3) << 4 | + (data->macrotile_mode & 0x1) << 12; - if (ubwc_version == UBWC_3_0) + if (data->ubwc_version == UBWC_3_0) value |= BIT(10); - if (ubwc_version == UBWC_1_0) + if (data->ubwc_version == UBWC_1_0) value |= BIT(8); writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC); } -static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss, - unsigned int ubwc_version, - u32 ubwc_swizzle, - u32 ubwc_static, - u32 highest_bank_bit, - u32 macrotile_mode) +static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) { - u32 value = (ubwc_swizzle & 0x7) | - (ubwc_static & 0x1) << 3 | - (highest_bank_bit & 0x7) << 4 | - (macrotile_mode & 0x1) << 12; + const struct msm_mdss_data *data = msm_mdss->mdss_data; + u32 value = (data->ubwc_swizzle & 0x7) | + (data->ubwc_static & 0x1) << 3 | + (data->highest_bank_bit & 0x7) << 4 | + (data->macrotile_mode & 0x1) << 12; writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC); - if (ubwc_version == UBWC_3_0) { + if (data->ubwc_version == UBWC_3_0) { writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2); writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE); } else { @@ -233,7 +235,6 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss, static int msm_mdss_enable(struct msm_mdss *msm_mdss) { int ret; - u32 hw_rev; /* * Several components have AXI clocks that can only be turned on if @@ -249,57 +250,36 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss) } /* - * HW_REV requires MDSS_MDP_CLK, which is not enabled by the mdss on - * mdp5 hardware. Skip reading it for now. + * Register access requires MDSS_MDP_CLK, which is not enabled by the + * mdss on mdp5 hardware. Skip it for now. */ - if (msm_mdss->is_mdp5) + if (msm_mdss->is_mdp5 || !msm_mdss->mdss_data) return 0; - hw_rev = readl_relaxed(msm_mdss->mmio + HW_REV); - dev_dbg(msm_mdss->dev, "HW_REV: 0x%x\n", hw_rev); - dev_dbg(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n", - readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION)); - /* * ubwc config is part of the "mdss" region which is not accessible * from the rest of the driver. hardcode known configurations here * * Decoder version can be read from the UBWC_DEC_HW_VERSION reg, - * UBWC_n and the rest of params comes from hw_catalog. - * Unforunately this driver can not access hw catalog, so we have to - * hardcode them here. + * UBWC_n and the rest of params comes from hw data. */ - switch (hw_rev) { - case DPU_HW_VER_500: - case DPU_HW_VER_501: - msm_mdss_setup_ubwc_dec_30(msm_mdss, UBWC_3_0, 0, 2, 0); - break; - case DPU_HW_VER_600: - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1); - break; - case DPU_HW_VER_620: - /* UBWC_2_0 */ - msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x1e); + switch (msm_mdss->mdss_data->ubwc_dec_version) { + case UBWC_2_0: + msm_mdss_setup_ubwc_dec_20(msm_mdss); break; - case DPU_HW_VER_630: - /* UBWC_2_0 */ - msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x11f); + case UBWC_3_0: + msm_mdss_setup_ubwc_dec_30(msm_mdss); break; - case DPU_HW_VER_700: - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1); + case UBWC_4_0: + msm_mdss_setup_ubwc_dec_40(msm_mdss); break; - case DPU_HW_VER_720: - msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_3_0, 6, 1, 1, 1); - break; - case DPU_HW_VER_800: - msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 2, 1); - break; - case DPU_HW_VER_810: - case DPU_HW_VER_900: - /* TODO: highest_bank_bit = 2 for LP_DDR4 */ - msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1); + default: + dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n", + msm_mdss->mdss_data->ubwc_dec_version); + dev_err(msm_mdss->dev, "HW_REV: 0x%x\n", + readl_relaxed(msm_mdss->mmio + HW_REV)); + dev_err(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n", + readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION)); break; } @@ -490,6 +470,8 @@ static int mdss_probe(struct platform_device *pdev) if (IS_ERR(mdss)) return PTR_ERR(mdss); + mdss->mdss_data = of_device_get_match_data(&pdev->dev); + platform_set_drvdata(pdev, mdss); /* @@ -519,21 +501,81 @@ static int mdss_remove(struct platform_device *pdev) return 0; } +static const struct msm_mdss_data sc7180_data = { + .ubwc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_static = 0x1e, +}; + +static const struct msm_mdss_data sc7280_data = { + .ubwc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = 6, + .ubwc_static = 1, + .highest_bank_bit = 1, + .macrotile_mode = 1, +}; + +static const struct msm_mdss_data sc8180x_data = { + .ubwc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_3_0, + .highest_bank_bit = 3, + .macrotile_mode = 1, +}; + +static const struct msm_mdss_data sc8280xp_data = { + .ubwc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = 6, + .ubwc_static = 1, + .highest_bank_bit = 2, + .macrotile_mode = 1, +}; + +static const struct msm_mdss_data sdm845_data = { + .ubwc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .highest_bank_bit = 2, +}; + +static const struct msm_mdss_data sm8150_data = { + .ubwc_version = UBWC_3_0, + .ubwc_dec_version = UBWC_3_0, + .highest_bank_bit = 2, +}; + +static const struct msm_mdss_data sm6115_data = { + .ubwc_version = UBWC_1_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_swizzle = 7, + .ubwc_static = 0x11f, +}; + +static const struct msm_mdss_data sm8250_data = { + .ubwc_version = UBWC_4_0, + .ubwc_dec_version = UBWC_4_0, + .ubwc_swizzle = 6, + .ubwc_static = 1, + /* TODO: highest_bank_bit = 2 for LP_DDR4 */ + .highest_bank_bit = 3, + .macrotile_mode = 1, +}; + static const struct of_device_id mdss_dt_match[] = { { .compatible = "qcom,mdss" }, { .compatible = "qcom,msm8998-mdss" }, { .compatible = "qcom,qcm2290-mdss" }, - { .compatible = "qcom,sdm845-mdss" }, - { .compatible = "qcom,sc7180-mdss" }, - { .compatible = "qcom,sc7280-mdss" }, - { .compatible = "qcom,sc8180x-mdss" }, - { .compatible = "qcom,sc8280xp-mdss" }, - { .compatible = "qcom,sm6115-mdss" }, - { .compatible = "qcom,sm8150-mdss" }, - { .compatible = "qcom,sm8250-mdss" }, - { .compatible = "qcom,sm8350-mdss" }, - { .compatible = "qcom,sm8450-mdss" }, - { .compatible = "qcom,sm8550-mdss" }, + { .compatible = "qcom,sdm845-mdss", .data = &sdm845_data }, + { .compatible = "qcom,sc7180-mdss", .data = &sc7180_data }, + { .compatible = "qcom,sc7280-mdss", .data = &sc7280_data }, + { .compatible = "qcom,sc8180x-mdss", .data = &sc8180x_data }, + { .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data }, + { .compatible = "qcom,sm6115-mdss", .data = &sm6115_data }, + { .compatible = "qcom,sm8150-mdss", .data = &sm8150_data }, + { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data }, + { .compatible = "qcom,sm8350-mdss", .data = &sm8250_data }, + { .compatible = "qcom,sm8450-mdss", .data = &sm8250_data }, + { .compatible = "qcom,sm8550-mdss", .data = &sm8250_data }, {} }; MODULE_DEVICE_TABLE(of, mdss_dt_match); diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h index dbf0d6f43fa9..6c34272a13fd 100644 --- a/include/uapi/drm/msm_drm.h +++ b/include/uapi/drm/msm_drm.h @@ -186,7 +186,11 @@ struct drm_msm_gem_cpu_fini { */ struct drm_msm_gem_submit_reloc { __u32 submit_offset; /* in, offset from submit_bo */ +#ifdef __cplusplus + __u32 _or; /* in, value OR'd with result */ +#else __u32 or; /* in, value OR'd with result */ +#endif __s32 shift; /* in, amount of left shift (can be negative) */ __u32 reloc_idx; /* in, index of reloc_bo buffer */ __u64 reloc_offset; /* in, offset from start of reloc_bo */ |