| From 58aa15a26b4104a7783808d4f815185ff57017c4 Mon Sep 17 00:00:00 2001 |
| From: Yong Wu <yong.wu@mediatek.com> |
| Date: Fri, 11 Feb 2022 15:08:27 +0800 |
| Subject: [PATCH] Revert "FROMLIST: memory: mtk-smi: Get rid of |
| mtk_smi_larb_get/put" |
| |
| Revert "FROMLIST: dt-binding: mediatek: Get rid of mediatek, larb for multimedia HW" |
| This reverts commit 81c356de527cd4073ff140ca39efd0ea55427ba9. |
| Revert "FROMLIST: memory: mtk-smi: Get rid of mtk_smi_larb_get/put" |
| This reverts commit e0b2c5727626a39aa86c9f68b1d52262d6309300. |
| Revert "BACKPORT: FROMLIST: drm/mediatek: Get rid of mtk_smi_larb_get/put" |
| This reverts commit 45d9a4a3451963722f9f63d1247a2b74cd267939. |
| Revert "FROMLIST: drm/mediatek: Add pm runtime support for ovl and rdma" |
| This reverts commit b2528a7abf57d773a410c7cfdf9c36d206b1d042. |
| Revert "FROMLIST: media: mtk-vcodec: Get rid of mtk_smi_larb_get/put" |
| This reverts commit d27e2aeca797d1dd2790d0e15a2ef5ea4309bba4. |
| Revert "FROMLIST: media: mtk-mdp: Get rid of mtk_smi_larb_get/put" |
| This reverts commit eb4da80f6522f2d5b8cf2be5466363e990b31417. |
| Revert "FROMLIST: media: mtk-jpeg: Get rid of mtk_smi_larb_get/put" |
| This reverts commit 52e67eea10852cfc46997271704b946cd4774b00. |
| Revert "FROMLIST: iommu/mediatek: Add device_link between the consumer and the larb devices" |
| This reverts commit 7df81352b02e3aa935823dd3068b562d38a059a4. |
| Revert "FROMLIST: iommu/mediatek: Add probe_defer for smi-larb" |
| This reverts commit bcffc3608bf534e4ff1f1d07cb95c8857d33f86f. |
| |
| BUG=b:126008328 |
| TEST=emerge-corsola sys-kernel/chromeos-kernel-5_15 |
| |
| Signed-off-by: Yong Wu <yong.wu@mediatek.com> |
| Change-Id: Icfa63e5d20cd04bf67f8c6e47769479fde6e3f82 |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3454898 |
| Reviewed-by: Hsin-Yi Wang <hsinyi@chromium.org> |
| Commit-Queue: Hsin-Yi Wang <hsinyi@chromium.org> |
| Tested-by: Hsin-Yi Wang <hsinyi@chromium.org> |
| --- |
| .../bindings/media/mediatek-mdp.txt | 8 ++++ |
| drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 8 +--- |
| drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 9 +--- |
| drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 15 +++---- |
| drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 34 ++++++++++++++ |
| drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 + |
| drivers/gpu/drm/mediatek/mtk_drm_drv.c | 5 ++- |
| drivers/iommu/mtk_iommu.c | 30 ------------- |
| drivers/iommu/mtk_iommu_v1.c | 29 +----------- |
| .../platform/mediatek/jpeg/mtk_jpeg_core.c | 45 ++++++++++++++++++- |
| .../platform/mediatek/jpeg/mtk_jpeg_core.h | 2 + |
| .../platform/mediatek/mdp/mtk_mdp_comp.c | 40 +++++++++++++++++ |
| .../platform/mediatek/mdp/mtk_mdp_comp.h | 2 + |
| .../platform/mediatek/mdp/mtk_mdp_core.c | 1 + |
| .../platform/mediatek/vcodec/mtk_vcodec_drv.h | 3 ++ |
| .../platform/mediatek/vcodec/mtk_vcodec_enc.c | 1 + |
| .../mediatek/vcodec/mtk_vcodec_enc_pm.c | 43 +++++++++++++++--- |
| drivers/memory/mtk-smi.c | 14 ++++++ |
| include/soc/mediatek/smi.h | 20 +++++++++ |
| 19 files changed, 221 insertions(+), 89 deletions(-) |
| |
| diff --git a/Documentation/devicetree/bindings/media/mediatek-mdp.txt b/Documentation/devicetree/bindings/media/mediatek-mdp.txt |
| index 53ef26e2c857..caa24943da33 100644 |
| --- a/Documentation/devicetree/bindings/media/mediatek-mdp.txt |
| +++ b/Documentation/devicetree/bindings/media/mediatek-mdp.txt |
| @@ -27,6 +27,9 @@ Required properties (DMA function blocks, child node): |
| - iommus: should point to the respective IOMMU block with master port as |
| argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml |
| for details. |
| +- mediatek,larb: must contain the local arbiters in the current Socs, see |
| + Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml |
| + for details. |
| |
| Example: |
| mdp_rdma0: rdma@14001000 { |
| @@ -37,6 +40,7 @@ Example: |
| <&mmsys CLK_MM_MUTEX_32K>; |
| power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; |
| iommus = <&iommu M4U_PORT_MDP_RDMA0>; |
| + mediatek,larb = <&larb0>; |
| mediatek,vpu = <&vpu>; |
| }; |
| |
| @@ -47,6 +51,7 @@ Example: |
| <&mmsys CLK_MM_MUTEX_32K>; |
| power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; |
| iommus = <&iommu M4U_PORT_MDP_RDMA1>; |
| + mediatek,larb = <&larb4>; |
| }; |
| |
| mdp_rsz0: rsz@14003000 { |
| @@ -76,6 +81,7 @@ Example: |
| clocks = <&mmsys CLK_MM_MDP_WDMA>; |
| power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; |
| iommus = <&iommu M4U_PORT_MDP_WDMA>; |
| + mediatek,larb = <&larb0>; |
| }; |
| |
| mdp_wrot0: wrot@14007000 { |
| @@ -84,6 +90,7 @@ Example: |
| clocks = <&mmsys CLK_MM_MDP_WROT0>; |
| power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; |
| iommus = <&iommu M4U_PORT_MDP_WROT0>; |
| + mediatek,larb = <&larb0>; |
| }; |
| |
| mdp_wrot1: wrot@14008000 { |
| @@ -92,4 +99,5 @@ Example: |
| clocks = <&mmsys CLK_MM_MDP_WROT1>; |
| power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; |
| iommus = <&iommu M4U_PORT_MDP_WROT1>; |
| + mediatek,larb = <&larb4>; |
| }; |
| diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c |
| index 17cd9b932298..2146299e5f52 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c |
| @@ -11,7 +11,6 @@ |
| #include <linux/of_device.h> |
| #include <linux/of_irq.h> |
| #include <linux/platform_device.h> |
| -#include <linux/pm_runtime.h> |
| #include <linux/soc/mediatek/mtk-cmdq.h> |
| |
| #include "mtk_disp_drv.h" |
| @@ -415,13 +414,9 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) |
| return ret; |
| } |
| |
| - pm_runtime_enable(dev); |
| - |
| ret = component_add(dev, &mtk_disp_ovl_component_ops); |
| - if (ret) { |
| - pm_runtime_disable(dev); |
| + if (ret) |
| dev_err(dev, "Failed to add component: %d\n", ret); |
| - } |
| |
| return ret; |
| } |
| @@ -429,7 +424,6 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev) |
| static int mtk_disp_ovl_remove(struct platform_device *pdev) |
| { |
| component_del(&pdev->dev, &mtk_disp_ovl_component_ops); |
| - pm_runtime_disable(&pdev->dev); |
| |
| return 0; |
| } |
| diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c |
| index 662e91d9d45f..d41a3970b944 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c |
| @@ -9,7 +9,6 @@ |
| #include <linux/of_device.h> |
| #include <linux/of_irq.h> |
| #include <linux/platform_device.h> |
| -#include <linux/pm_runtime.h> |
| #include <linux/soc/mediatek/mtk-cmdq.h> |
| |
| #include "mtk_disp_drv.h" |
| @@ -328,13 +327,9 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev) |
| |
| platform_set_drvdata(pdev, priv); |
| |
| - pm_runtime_enable(dev); |
| - |
| ret = component_add(dev, &mtk_disp_rdma_component_ops); |
| - if (ret) { |
| - pm_runtime_disable(dev); |
| + if (ret) |
| dev_err(dev, "Failed to add component: %d\n", ret); |
| - } |
| |
| return ret; |
| } |
| @@ -343,8 +338,6 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) |
| { |
| component_del(&pdev->dev, &mtk_disp_rdma_component_ops); |
| |
| - pm_runtime_disable(&pdev->dev); |
| - |
| return 0; |
| } |
| |
| diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c |
| index ede435d2c1ef..8cc0a1283d7c 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c |
| @@ -12,6 +12,7 @@ |
| #include <linux/soc/mediatek/mtk-mutex.h> |
| |
| #include <asm/barrier.h> |
| +#include <soc/mediatek/smi.h> |
| |
| #include <drm/drm_atomic.h> |
| #include <drm/drm_atomic_helper.h> |
| @@ -662,15 +663,15 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, |
| |
| DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); |
| |
| - ret = pm_runtime_resume_and_get(comp->dev); |
| - if (ret < 0) { |
| - DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret); |
| + ret = mtk_smi_larb_get(comp->larb_dev); |
| + if (ret) { |
| + DRM_ERROR("Failed to get larb: %d\n", ret); |
| return; |
| } |
| |
| ret = mtk_crtc_ddp_hw_init(mtk_crtc); |
| if (ret) { |
| - pm_runtime_put(comp->dev); |
| + mtk_smi_larb_put(comp->larb_dev); |
| return; |
| } |
| |
| @@ -683,7 +684,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, |
| { |
| struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); |
| struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; |
| - int i, ret; |
| + int i; |
| |
| DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); |
| if (!mtk_crtc->enabled) |
| @@ -713,9 +714,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, |
| |
| drm_crtc_vblank_off(crtc); |
| mtk_crtc_ddp_hw_fini(mtk_crtc); |
| - ret = pm_runtime_put(comp->dev); |
| - if (ret < 0) |
| - DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret); |
| + mtk_smi_larb_put(comp->larb_dev); |
| |
| mtk_crtc->enabled = false; |
| } |
| diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |
| index 2e99aee13dfe..3667f9e61ad7 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |
| @@ -447,6 +447,30 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, |
| return ret; |
| } |
| |
| +static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp, |
| + struct device *dev) |
| +{ |
| + struct device_node *larb_node; |
| + struct platform_device *larb_pdev; |
| + |
| + larb_node = of_parse_phandle(node, "mediatek,larb", 0); |
| + if (!larb_node) { |
| + dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node); |
| + return -EINVAL; |
| + } |
| + |
| + larb_pdev = of_find_device_by_node(larb_node); |
| + if (!larb_pdev) { |
| + dev_warn(dev, "Waiting for larb device %pOF\n", larb_node); |
| + of_node_put(larb_node); |
| + return -EPROBE_DEFER; |
| + } |
| + of_node_put(larb_node); |
| + comp->larb_dev = &larb_pdev->dev; |
| + |
| + return 0; |
| +} |
| + |
| int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, |
| enum mtk_ddp_comp_id comp_id) |
| { |
| @@ -471,6 +495,16 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, |
| } |
| comp->dev = &comp_pdev->dev; |
| |
| + /* Only DMA capable components need the LARB property */ |
| + if (type == MTK_DISP_OVL || |
| + type == MTK_DISP_OVL_2L || |
| + type == MTK_DISP_RDMA || |
| + type == MTK_DISP_WDMA) { |
| + ret = mtk_ddp_get_larb_dev(node, comp, comp->dev); |
| + if (ret) |
| + return ret; |
| + } |
| + |
| if (type == MTK_DISP_AAL || |
| type == MTK_DISP_BLS || |
| type == MTK_DISP_CCORR || |
| diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |
| index ad267bb8fc9b..4c6a98662305 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |
| +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |
| @@ -71,6 +71,7 @@ struct mtk_ddp_comp_funcs { |
| struct mtk_ddp_comp { |
| struct device *dev; |
| int irq; |
| + struct device *larb_dev; |
| enum mtk_ddp_comp_id id; |
| const struct mtk_ddp_comp_funcs *funcs; |
| }; |
| diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| index 247c6ff277ef..632bf7ed888b 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| @@ -643,8 +643,11 @@ static int mtk_drm_probe(struct platform_device *pdev) |
| pm_runtime_disable(dev); |
| err_node: |
| of_node_put(private->mutex_node); |
| - for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) |
| + for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) { |
| of_node_put(private->comp_node[i]); |
| + if (private->ddp_comp[i].larb_dev) |
| + put_device(private->ddp_comp[i].larb_dev); |
| + } |
| return ret; |
| } |
| |
| diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c |
| index 6fd75a60abd6..c70a84f7c172 100644 |
| --- a/drivers/iommu/mtk_iommu.c |
| +++ b/drivers/iommu/mtk_iommu.c |
| @@ -557,52 +557,22 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) |
| { |
| struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| struct mtk_iommu_data *data; |
| - struct device_link *link; |
| - struct device *larbdev; |
| - unsigned int larbid, larbidx, i; |
| |
| if (!fwspec || fwspec->ops != &mtk_iommu_ops) |
| return ERR_PTR(-ENODEV); /* Not a iommu client device */ |
| |
| data = dev_iommu_priv_get(dev); |
| |
| - /* |
| - * Link the consumer device with the smi-larb device(supplier). |
| - * The device that connects with each a larb is a independent HW. |
| - * All the ports in each a device should be in the same larbs. |
| - */ |
| - larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); |
| - for (i = 1; i < fwspec->num_ids; i++) { |
| - larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]); |
| - if (larbid != larbidx) { |
| - dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n", |
| - larbid, larbidx); |
| - return ERR_PTR(-EINVAL); |
| - } |
| - } |
| - larbdev = data->larb_imu[larbid].dev; |
| - link = device_link_add(dev, larbdev, |
| - DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); |
| - if (!link) |
| - dev_err(dev, "Unable to link %s\n", dev_name(larbdev)); |
| return &data->iommu; |
| } |
| |
| static void mtk_iommu_release_device(struct device *dev) |
| { |
| struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| - struct mtk_iommu_data *data; |
| - struct device *larbdev; |
| - unsigned int larbid; |
| |
| if (!fwspec || fwspec->ops != &mtk_iommu_ops) |
| return; |
| |
| - data = dev_iommu_priv_get(dev); |
| - larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); |
| - larbdev = data->larb_imu[larbid].dev; |
| - device_link_remove(dev, larbdev); |
| - |
| iommu_fwspec_free(dev); |
| } |
| |
| diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c |
| index ecff800656e6..136e7215b25a 100644 |
| --- a/drivers/iommu/mtk_iommu_v1.c |
| +++ b/drivers/iommu/mtk_iommu_v1.c |
| @@ -423,9 +423,7 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) |
| struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| struct of_phandle_args iommu_spec; |
| struct mtk_iommu_data *data; |
| - int err, idx = 0, larbid, larbidx; |
| - struct device_link *link; |
| - struct device *larbdev; |
| + int err, idx = 0; |
| |
| /* |
| * In the deferred case, free the existed fwspec. |
| @@ -455,23 +453,6 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) |
| |
| data = dev_iommu_priv_get(dev); |
| |
| - /* Link the consumer device with the smi-larb device(supplier) */ |
| - larbid = mt2701_m4u_to_larb(fwspec->ids[0]); |
| - for (idx = 1; idx < fwspec->num_ids; idx++) { |
| - larbidx = mt2701_m4u_to_larb(fwspec->ids[idx]); |
| - if (larbid != larbidx) { |
| - dev_err(dev, "Can only use one larb. Fail@larb%d-%d.\n", |
| - larbid, larbidx); |
| - return ERR_PTR(-EINVAL); |
| - } |
| - } |
| - |
| - larbdev = data->larb_imu[larbid].dev; |
| - link = device_link_add(dev, larbdev, |
| - DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); |
| - if (!link) |
| - dev_err(dev, "Unable to link %s\n", dev_name(larbdev)); |
| - |
| return &data->iommu; |
| } |
| |
| @@ -492,18 +473,10 @@ static void mtk_iommu_probe_finalize(struct device *dev) |
| static void mtk_iommu_release_device(struct device *dev) |
| { |
| struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); |
| - struct mtk_iommu_data *data; |
| - struct device *larbdev; |
| - unsigned int larbid; |
| |
| if (!fwspec || fwspec->ops != &mtk_iommu_ops) |
| return; |
| |
| - data = dev_iommu_priv_get(dev); |
| - larbid = mt2701_m4u_to_larb(fwspec->ids[0]); |
| - larbdev = data->larb_imu[larbid].dev; |
| - device_link_remove(dev, larbdev); |
| - |
| iommu_fwspec_free(dev); |
| } |
| |
| diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |
| index ab5485dfc20c..b334bbb2e682 100644 |
| --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |
| +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |
| @@ -22,6 +22,7 @@ |
| #include <media/v4l2-ioctl.h> |
| #include <media/videobuf2-core.h> |
| #include <media/videobuf2-dma-contig.h> |
| +#include <soc/mediatek/smi.h> |
| |
| #include "mtk_jpeg_enc_hw.h" |
| #include "mtk_jpeg_dec_hw.h" |
| @@ -1054,6 +1055,10 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg) |
| { |
| int ret; |
| |
| + ret = mtk_smi_larb_get(jpeg->larb); |
| + if (ret) |
| + dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret); |
| + |
| ret = clk_bulk_prepare_enable(jpeg->variant->num_clks, |
| jpeg->variant->clks); |
| if (ret) |
| @@ -1064,6 +1069,7 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg) |
| { |
| clk_bulk_disable_unprepare(jpeg->variant->num_clks, |
| jpeg->variant->clks); |
| + mtk_smi_larb_put(jpeg->larb); |
| } |
| |
| static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) |
| @@ -1278,6 +1284,35 @@ static struct clk_bulk_data mtk_jpeg_clocks[] = { |
| { .id = "jpgenc" }, |
| }; |
| |
| +static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg) |
| +{ |
| + struct device_node *node; |
| + struct platform_device *pdev; |
| + int ret; |
| + |
| + node = of_parse_phandle(jpeg->dev->of_node, "mediatek,larb", 0); |
| + if (!node) |
| + return -EINVAL; |
| + pdev = of_find_device_by_node(node); |
| + if (WARN_ON(!pdev)) { |
| + of_node_put(node); |
| + return -EINVAL; |
| + } |
| + of_node_put(node); |
| + |
| + jpeg->larb = &pdev->dev; |
| + |
| + ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks, |
| + jpeg->variant->clks); |
| + if (ret) { |
| + dev_err(&pdev->dev, "failed to get jpeg clock:%d\n", ret); |
| + put_device(&pdev->dev); |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| static void mtk_jpeg_job_timeout_work(struct work_struct *work) |
| { |
| struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev, |
| @@ -1298,6 +1333,11 @@ static void mtk_jpeg_job_timeout_work(struct work_struct *work) |
| v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); |
| } |
| |
| +static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg) |
| +{ |
| + put_device(jpeg->larb); |
| +} |
| + |
| static int mtk_jpeg_probe(struct platform_device *pdev) |
| { |
| struct mtk_jpeg_dev *jpeg; |
| @@ -1332,8 +1372,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev) |
| goto err_req_irq; |
| } |
| |
| - ret = devm_clk_bulk_get(jpeg->dev, jpeg->variant->num_clks, |
| - jpeg->variant->clks); |
| + ret = mtk_jpeg_clk_init(jpeg); |
| if (ret) { |
| dev_err(&pdev->dev, "Failed to init clk, err %d\n", ret); |
| goto err_clk_init; |
| @@ -1399,6 +1438,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev) |
| v4l2_device_unregister(&jpeg->v4l2_dev); |
| |
| err_dev_register: |
| + mtk_jpeg_clk_release(jpeg); |
| |
| err_clk_init: |
| |
| @@ -1416,6 +1456,7 @@ static int mtk_jpeg_remove(struct platform_device *pdev) |
| video_device_release(jpeg->vdev); |
| v4l2_m2m_release(jpeg->m2m_dev); |
| v4l2_device_unregister(&jpeg->v4l2_dev); |
| + mtk_jpeg_clk_release(jpeg); |
| |
| return 0; |
| } |
| diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h |
| index 3e4811a41ba2..595f7f10c9fd 100644 |
| --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h |
| +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h |
| @@ -85,6 +85,7 @@ struct mtk_jpeg_variant { |
| * @alloc_ctx: videobuf2 memory allocator's context |
| * @vdev: video device node for jpeg mem2mem mode |
| * @reg_base: JPEG registers mapping |
| + * @larb: SMI device |
| * @job_timeout_work: IRQ timeout structure |
| * @variant: driver variant to be used |
| */ |
| @@ -98,6 +99,7 @@ struct mtk_jpeg_dev { |
| void *alloc_ctx; |
| struct video_device *vdev; |
| void __iomem *reg_base; |
| + struct device *larb; |
| struct delayed_work job_timeout_work; |
| const struct mtk_jpeg_variant *variant; |
| }; |
| diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c |
| index 1e3833f1c9ae..b3426a551bea 100644 |
| --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c |
| +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c |
| @@ -9,6 +9,7 @@ |
| #include <linux/of.h> |
| #include <linux/of_address.h> |
| #include <linux/of_platform.h> |
| +#include <soc/mediatek/smi.h> |
| |
| #include "mtk_mdp_comp.h" |
| |
| @@ -17,6 +18,14 @@ void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp) |
| { |
| int i, err; |
| |
| + if (comp->larb_dev) { |
| + err = mtk_smi_larb_get(comp->larb_dev); |
| + if (err) |
| + dev_err(dev, |
| + "failed to get larb, err %d. type:%d\n", |
| + err, comp->type); |
| + } |
| + |
| for (i = 0; i < ARRAY_SIZE(comp->clk); i++) { |
| if (IS_ERR(comp->clk[i])) |
| continue; |
| @@ -37,12 +46,17 @@ void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp) |
| continue; |
| clk_disable_unprepare(comp->clk[i]); |
| } |
| + |
| + if (comp->larb_dev) |
| + mtk_smi_larb_put(comp->larb_dev); |
| } |
| |
| int mtk_mdp_comp_init(struct device *dev, struct device_node *node, |
| struct mtk_mdp_comp *comp, |
| enum mtk_mdp_comp_type comp_type) |
| { |
| + struct device_node *larb_node; |
| + struct platform_device *larb_pdev; |
| int ret; |
| int i; |
| |
| @@ -63,6 +77,32 @@ int mtk_mdp_comp_init(struct device *dev, struct device_node *node, |
| break; |
| } |
| |
| + /* Only DMA capable components need the LARB property */ |
| + comp->larb_dev = NULL; |
| + if (comp->type != MTK_MDP_RDMA && |
| + comp->type != MTK_MDP_WDMA && |
| + comp->type != MTK_MDP_WROT) |
| + return 0; |
| + |
| + larb_node = of_parse_phandle(node, "mediatek,larb", 0); |
| + if (!larb_node) { |
| + dev_err(dev, |
| + "Missing mediadek,larb phandle in %pOF node\n", node); |
| + ret = -EINVAL; |
| + goto put_dev; |
| + } |
| + |
| + larb_pdev = of_find_device_by_node(larb_node); |
| + if (!larb_pdev) { |
| + dev_warn(dev, "Waiting for larb device %pOF\n", larb_node); |
| + of_node_put(larb_node); |
| + ret = -EPROBE_DEFER; |
| + goto put_dev; |
| + } |
| + of_node_put(larb_node); |
| + |
| + comp->larb_dev = &larb_pdev->dev; |
| + |
| return 0; |
| |
| put_dev: |
| diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.h b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.h |
| index ae41dd3cd72a..7897766c96bb 100644 |
| --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.h |
| +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_comp.h |
| @@ -26,12 +26,14 @@ enum mtk_mdp_comp_type { |
| * @node: list node to track sibing MDP components |
| * @dev_node: component device node |
| * @clk: clocks required for component |
| + * @larb_dev: SMI device required for component |
| * @type: component type |
| */ |
| struct mtk_mdp_comp { |
| struct list_head node; |
| struct device_node *dev_node; |
| struct clk *clk[2]; |
| + struct device *larb_dev; |
| enum mtk_mdp_comp_type type; |
| }; |
| |
| diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c |
| index d83c4964eaf9..fbd6e06a0567 100644 |
| --- a/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c |
| +++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_core.c |
| @@ -17,6 +17,7 @@ |
| #include <linux/platform_device.h> |
| #include <linux/pm_runtime.h> |
| #include <linux/workqueue.h> |
| +#include <soc/mediatek/smi.h> |
| |
| #include "mtk_mdp_core.h" |
| #include "mtk_mdp_m2m.h" |
| diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h |
| index 813901c4be5e..94b47b7c912b 100644 |
| --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h |
| +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h |
| @@ -214,7 +214,10 @@ struct mtk_vcodec_clk { |
| */ |
| struct mtk_vcodec_pm { |
| struct mtk_vcodec_clk vdec_clk; |
| + struct device *larbvdec; |
| + |
| struct mtk_vcodec_clk venc_clk; |
| + struct device *larbvenc; |
| struct device *dev; |
| }; |
| |
| diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c |
| index a8de28b90d4c..434b8c4b7cb7 100644 |
| --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c |
| +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c |
| @@ -8,6 +8,7 @@ |
| #include <media/v4l2-event.h> |
| #include <media/v4l2-mem2mem.h> |
| #include <media/videobuf2-dma-contig.h> |
| +#include <soc/mediatek/smi.h> |
| #include <linux/pm_runtime.h> |
| |
| #include "mtk_vcodec_drv.h" |
| diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_pm.c |
| index 7055954eb2af..309843cce17e 100644 |
| --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_pm.c |
| +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_pm.c |
| @@ -8,35 +8,57 @@ |
| #include <linux/of_address.h> |
| #include <linux/of_platform.h> |
| #include <linux/pm_runtime.h> |
| +#include <soc/mediatek/smi.h> |
| |
| #include "mtk_vcodec_enc_pm.h" |
| #include "mtk_vcodec_util.h" |
| |
| int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev) |
| { |
| + struct device_node *node; |
| struct platform_device *pdev; |
| struct mtk_vcodec_pm *pm; |
| struct mtk_vcodec_clk *enc_clk; |
| struct mtk_vcodec_clk_info *clk_info; |
| int ret, i; |
| + struct device *dev; |
| |
| pdev = mtkdev->plat_dev; |
| pm = &mtkdev->pm; |
| memset(pm, 0, sizeof(struct mtk_vcodec_pm)); |
| pm->dev = &pdev->dev; |
| + dev = &pdev->dev; |
| enc_clk = &pm->venc_clk; |
| |
| + node = of_parse_phandle(dev->of_node, "mediatek,larb", 0); |
| + if (!node) { |
| + mtk_v4l2_err("no mediatek,larb found"); |
| + return -ENODEV; |
| + } |
| + pdev = of_find_device_by_node(node); |
| + of_node_put(node); |
| + if (!pdev) { |
| + mtk_v4l2_err("no mediatek,larb device found"); |
| + return -ENODEV; |
| + } |
| + pm->larbvenc = &pdev->dev; |
| + pdev = mtkdev->plat_dev; |
| + pm->dev = &pdev->dev; |
| + |
| enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node, |
| "clock-names"); |
| if (enc_clk->clk_num > 0) { |
| enc_clk->clk_info = devm_kcalloc(&pdev->dev, |
| enc_clk->clk_num, sizeof(*clk_info), |
| GFP_KERNEL); |
| - if (!enc_clk->clk_info) |
| - return -ENOMEM; |
| + if (!enc_clk->clk_info) { |
| + ret = -ENOMEM; |
| + goto put_larbvenc; |
| + } |
| } else { |
| mtk_v4l2_err("Failed to get venc clock count"); |
| - return -EINVAL; |
| + ret = -EINVAL; |
| + goto put_larbvenc; |
| } |
| |
| for (i = 0; i < enc_clk->clk_num; i++) { |
| @@ -45,18 +67,23 @@ int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev) |
| "clock-names", i, &clk_info->clk_name); |
| if (ret) { |
| mtk_v4l2_err("venc failed to get clk name %d", i); |
| - return ret; |
| + goto put_larbvenc; |
| } |
| clk_info->vcodec_clk = devm_clk_get(&pdev->dev, |
| clk_info->clk_name); |
| if (IS_ERR(clk_info->vcodec_clk)) { |
| mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i, |
| clk_info->clk_name); |
| - return PTR_ERR(clk_info->vcodec_clk); |
| + ret = PTR_ERR(clk_info->vcodec_clk); |
| + goto put_larbvenc; |
| } |
| } |
| |
| return 0; |
| + |
| +put_larbvenc: |
| + put_device(pm->larbvenc); |
| + return ret; |
| } |
| |
| void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm) |
| @@ -73,6 +100,11 @@ void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm) |
| } |
| } |
| |
| + ret = mtk_smi_larb_get(pm->larbvenc); |
| + if (ret) { |
| + mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret); |
| + goto clkerr; |
| + } |
| return; |
| |
| clkerr: |
| @@ -85,6 +117,7 @@ void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm) |
| struct mtk_vcodec_clk *enc_clk = &pm->venc_clk; |
| int i = 0; |
| |
| + mtk_smi_larb_put(pm->larbvenc); |
| for (i = enc_clk->clk_num - 1; i >= 0; i--) |
| clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); |
| } |
| diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c |
| index 86a3d34f418e..7d8a083df44a 100644 |
| --- a/drivers/memory/mtk-smi.c |
| +++ b/drivers/memory/mtk-smi.c |
| @@ -154,6 +154,20 @@ struct mtk_smi_larb { /* larb: local arbiter */ |
| unsigned char *bank; |
| }; |
| |
| +int mtk_smi_larb_get(struct device *larbdev) |
| +{ |
| + int ret = pm_runtime_resume_and_get(larbdev); |
| + |
| + return (ret < 0) ? ret : 0; |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_smi_larb_get); |
| + |
| +void mtk_smi_larb_put(struct device *larbdev) |
| +{ |
| + pm_runtime_put_sync(larbdev); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_smi_larb_put); |
| + |
| static int |
| mtk_smi_larb_bind(struct device *dev, struct device *master, void *data) |
| { |
| diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h |
| index 11f7d6b59642..15e3397cec58 100644 |
| --- a/include/soc/mediatek/smi.h |
| +++ b/include/soc/mediatek/smi.h |
| @@ -19,6 +19,26 @@ struct mtk_smi_larb_iommu { |
| unsigned char bank[32]; |
| }; |
| |
| +/* |
| + * mtk_smi_larb_get: Enable the power domain and clocks for this local arbiter. |
| + * It also initialize some basic setting(like iommu). |
| + * mtk_smi_larb_put: Disable the power domain and clocks for this local arbiter. |
| + * Both should be called in non-atomic context. |
| + * |
| + * Returns 0 if successful, negative on failure. |
| + */ |
| +int mtk_smi_larb_get(struct device *larbdev); |
| +void mtk_smi_larb_put(struct device *larbdev); |
| + |
| +#else |
| + |
| +static inline int mtk_smi_larb_get(struct device *larbdev) |
| +{ |
| + return 0; |
| +} |
| + |
| +static inline void mtk_smi_larb_put(struct device *larbdev) { } |
| + |
| #endif |
| |
| #endif |
| -- |
| 2.35.1.1178.g4f1659d476-goog |
| |