diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 11e2dfcdfba82..4e533c572ab8d 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -5496,8 +5497,8 @@ resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x1940 0>, - <&apps_smmu 0x1947 0>; + iommu-map = , + ; dma-coherent; /* diff --git a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi index 8db958d60fd1d..07fa9cb148ae6 100644 --- a/arch/arm64/boot/dts/qcom/lemans-auto.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-auto.dtsi @@ -102,3 +102,7 @@ }; }; }; + +&iris { + firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi index 3fa8c1f35524c..d66b33a1812ca 100644 --- a/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans-ride-common.dtsi @@ -580,8 +580,6 @@ }; &iris { - firmware-name = "qcom/vpu/vpu30_p4_s6.mbn"; - status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index 0bc19fd728cdd..ae546fc2ad2ee 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -4562,11 +4563,13 @@ memory-region = <&pil_video_mem>; + firmware-name = "qcom/vpu/vpu30_p4_s6_16mb.mbn"; + resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>; reset-names = "bus"; - iommus = <&apps_smmu 0x0880 0x0400>, - <&apps_smmu 0x0887 0x0400>; + iommu-map = , + ; dma-coherent; status = "disabled"; diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index f1f003a787bf2..0db94a5e38789 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -336,7 +336,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, enum iris_buffer_type buffer_type, u32 index) { struct iris_buffers *buffers = &inst->buffers[buffer_type]; - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer_type); struct iris_buffer *buffer; if (!buffers->size) @@ -352,7 +352,7 @@ static int iris_create_internal_buffer(struct iris_inst *inst, buffer->buffer_size = buffers->size; buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE | DMA_ATTR_NO_KERNEL_MAPPING; - buffer->kvaddr = dma_alloc_attrs(core->dev, buffer->buffer_size, + buffer->kvaddr = dma_alloc_attrs(dev, buffer->buffer_size, &buffer->device_addr, GFP_KERNEL, buffer->dma_attrs); if (!buffer->kvaddr) { kfree(buffer); @@ -489,10 +489,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane) int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer) { - struct iris_core *core = inst->core; + struct device *dev = iris_get_cb_dev(inst, buffer->type); list_del(&buffer->list); - dma_free_attrs(core->dev, buffer->buffer_size, buffer->kvaddr, + dma_free_attrs(dev, buffer->buffer_size, buffer->kvaddr, buffer->device_addr, buffer->dma_attrs); kfree(buffer); diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index ef081ccc3429d..c85fd7f292467 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -34,6 +34,9 @@ enum domain_type { * struct iris_core - holds core parameters valid for all instances * * @dev: reference to device structure + * @dev_np: reference to non-pixel context bank device structure + * @dev_p: reference to pixel context bank device structure + * @dev_bs: reference to bitstream context bank device structure * @reg_base: IO memory base address * @irq: iris irq * @v4l2_dev: a holder for v4l2 device structure @@ -77,6 +80,9 @@ enum domain_type { struct iris_core { struct device *dev; + struct device *dev_np; + struct device *dev_p; + struct device *dev_bs; void __iomem *reg_base; int irq; struct v4l2_device v4l2_dev; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index b3ed06297953b..f465ff00a9ba3 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -245,25 +245,26 @@ static void iris_hfi_queue_deinit(struct iris_iface_q_info *iface_q) int iris_hfi_queues_init(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; struct iris_hfi_queue_table_header *q_tbl_hdr; u32 queue_size; /* Iris hardware requires 4K queue alignment */ queue_size = ALIGN((sizeof(*q_tbl_hdr) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ)), SZ_4K); - core->iface_q_table_vaddr = dma_alloc_attrs(core->dev, queue_size, + core->iface_q_table_vaddr = dma_alloc_attrs(dev, queue_size, &core->iface_q_table_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->iface_q_table_vaddr) { - dev_err(core->dev, "queues alloc and map failed\n"); + dev_err(dev, "queues alloc and map failed\n"); return -ENOMEM; } - core->sfr_vaddr = dma_alloc_attrs(core->dev, SFR_SIZE, + core->sfr_vaddr = dma_alloc_attrs(dev, SFR_SIZE, &core->sfr_daddr, GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->sfr_vaddr) { - dev_err(core->dev, "sfr alloc and map failed\n"); - dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, + dev_err(dev, "sfr alloc and map failed\n"); + dma_free_attrs(dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); return -ENOMEM; } @@ -291,6 +292,7 @@ int iris_hfi_queues_init(struct iris_core *core) void iris_hfi_queues_deinit(struct iris_core *core) { + struct device *dev = core->dev_np ? core->dev_np : core->dev; u32 queue_size; if (!core->iface_q_table_vaddr) @@ -300,7 +302,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) iris_hfi_queue_deinit(&core->message_queue); iris_hfi_queue_deinit(&core->command_queue); - dma_free_attrs(core->dev, SFR_SIZE, core->sfr_vaddr, + dma_free_attrs(dev, SFR_SIZE, core->sfr_vaddr, core->sfr_daddr, DMA_ATTR_WRITE_COMBINE); core->sfr_vaddr = NULL; @@ -309,7 +311,7 @@ void iris_hfi_queues_deinit(struct iris_core *core) queue_size = ALIGN(sizeof(struct iris_hfi_queue_table_header) + (IFACEQ_QUEUE_SIZE * IFACEQ_NUMQ), SZ_4K); - dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, + dma_free_attrs(dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); core->iface_q_table_vaddr = NULL; diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index 5a489917580eb..55ff6137d9a95 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -219,6 +219,8 @@ struct iris_platform_data { u32 (*get_vpu_buffer_size)(struct iris_inst *inst, enum iris_buffer_type buffer_type); const struct vpu_ops *vpu_ops; void (*set_preset_registers)(struct iris_core *core); + int (*init_cb_devs)(struct iris_core *core); + void (*deinit_cb_devs)(struct iris_core *core); const struct icc_info *icc_tbl; unsigned int icc_tbl_size; const struct bw_info *bw_tbl_dec; diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c index 5da90d47f9c6e..0d642d79eb994 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c @@ -761,6 +761,47 @@ static void iris_set_sm8550_preset_registers(struct iris_core *core) writel(0x0, core->reg_base + 0xB0088); } +static int sm8550_init_cb_devs(struct iris_core *core) +{ + const u32 f_id_np = 0; /* IRIS_NON_PIXEL_VCODEC */ + const u32 f_id_p = 1; /* IRIS_PIXEL */ + struct device *dev; + + dev = iris_create_cb_dev(core, "iris_non_pixel", &f_id_np); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + core->dev_np = dev; + core->dev_bs = core->dev_np; + + dev = iris_create_cb_dev(core, "iris_pixel", &f_id_p); + if (IS_ERR(dev)) + goto err_unreg_dev_np; + + core->dev_p = dev; + + return 0; + +err_unreg_dev_np: + platform_device_unregister(to_platform_device(core->dev_np)); + core->dev_np = NULL; + core->dev_bs = NULL; + + return PTR_ERR(dev); +} + +static void sm8550_deinit_cb_devs(struct iris_core *core) +{ + if (core->dev_np) + platform_device_unregister(to_platform_device(core->dev_np)); + if (core->dev_p) + platform_device_unregister(to_platform_device(core->dev_p)); + + core->dev_np = NULL; + core->dev_bs = NULL; + core->dev_p = NULL; +} + static const struct icc_info sm8550_icc_table[] = { { "cpu-cfg", 1000, 1000 }, { "video-mem", 1000, 15000000 }, @@ -928,6 +969,8 @@ const struct iris_platform_data sm8550_data = { .get_vpu_buffer_size = iris_vpu_buf_size, .vpu_ops = &iris_vpu3_ops, .set_preset_registers = iris_set_sm8550_preset_registers, + .init_cb_devs = sm8550_init_cb_devs, + .deinit_cb_devs = sm8550_deinit_cb_devs, .icc_tbl = sm8550_icc_table, .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table), .clk_rst_tbl = sm8550_clk_reset_table, diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 7b612ad37e4fd..269c14dd965eb 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -123,6 +123,20 @@ static int iris_init_resets(struct iris_core *core) core->iris_platform_data->controller_rst_tbl_size); } +static int iris_init_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->init_cb_devs) + return core->iris_platform_data->init_cb_devs(core); + + return 0; +} + +static void iris_deinit_cb_devs(struct iris_core *core) +{ + if (core->iris_platform_data->deinit_cb_devs) + core->iris_platform_data->deinit_cb_devs(core); +} + static int iris_init_resources(struct iris_core *core) { int ret; @@ -193,6 +207,7 @@ static void iris_remove(struct platform_device *pdev) return; iris_core_deinit(core); + iris_deinit_cb_devs(core); video_unregister_device(core->vdev_dec); video_unregister_device(core->vdev_enc); @@ -259,11 +274,15 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; + ret = iris_init_cb_devs(core); + if (ret) + return ret; + iris_session_init_caps(core); ret = v4l2_device_register(dev, &core->v4l2_dev); if (ret) - return ret; + goto err_deinit_cb; ret = iris_register_video_device(core, DECODER); if (ret) @@ -277,9 +296,11 @@ static int iris_probe(struct platform_device *pdev) dma_mask = core->iris_platform_data->dma_mask; - ret = dma_set_mask_and_coherent(dev, dma_mask); - if (ret) - goto err_vdev_unreg_enc; + if (device_iommu_mapped(core->dev)) { + ret = dma_set_mask_and_coherent(core->dev, dma_mask); + if (ret) + goto err_vdev_unreg_enc; + } dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(&pdev->dev, DMA_BIT_MASK(32)); @@ -298,6 +319,8 @@ static int iris_probe(struct platform_device *pdev) video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); +err_deinit_cb: + iris_deinit_cb_devs(core); return ret; } diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c index 773f6548370a2..b10884eb3ac64 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.c +++ b/drivers/media/platform/qcom/iris/iris_resources.c @@ -6,12 +6,14 @@ #include #include #include +#include #include #include #include #include #include "iris_core.h" +#include "iris_instance.h" #include "iris_resources.h" #define BW_THRESHOLD 50000 @@ -141,3 +143,77 @@ int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type return 0; } + +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id) +{ + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, 0); + if (!pdev) + return ERR_PTR(-ENOMEM); + + pdev->dev.parent = core->dev; + + ret = platform_device_add(pdev); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + ret = of_dma_configure_id(&pdev->dev, core->dev->of_node, true, f_id); + if (ret) + goto error_unregister; + + ret = dma_set_mask_and_coherent(&pdev->dev, core->iris_platform_data->dma_mask); + if (ret) + goto error_unregister; + + return &pdev->dev; + +error_unregister: + platform_device_unregister(to_platform_device(&pdev->dev)); + + return ERR_PTR(ret); +} + +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type) +{ + struct iris_core *core = inst->core; + struct device *dev = NULL; + + switch (buffer_type) { + case BUF_INPUT: + if (inst->domain == DECODER) + dev = core->dev_bs; + else + dev = core->dev_p; + break; + case BUF_OUTPUT: + if (inst->domain == DECODER) + dev = core->dev_p; + else + dev = core->dev_bs; + break; + case BUF_BIN: + dev = core->dev_bs; + break; + case BUF_DPB: + case BUF_PARTIAL: + case BUF_SCRATCH_2: + case BUF_VPSS: + dev = core->dev_p; + break; + case BUF_ARP: + case BUF_COMV: + case BUF_LINE: + case BUF_NON_COMV: + case BUF_PERSIST: + dev = core->dev_np; + break; + default: + dev_err(core->dev, "invalid buffer type: %d\n", buffer_type); + } + + return dev ? dev : core->dev; +} diff --git a/drivers/media/platform/qcom/iris/iris_resources.h b/drivers/media/platform/qcom/iris/iris_resources.h index 6bfbd2dc6db09..e6a6dc24a7f12 100644 --- a/drivers/media/platform/qcom/iris/iris_resources.h +++ b/drivers/media/platform/qcom/iris/iris_resources.h @@ -15,5 +15,7 @@ int iris_unset_icc_bw(struct iris_core *core); int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw); int iris_disable_unprepare_clock(struct iris_core *core, enum platform_clk_type clk_type); int iris_prepare_enable_clock(struct iris_core *core, enum platform_clk_type clk_type); +struct device *iris_create_cb_dev(struct iris_core *core, const char *name, const u32 *f_id); +struct device *iris_get_cb_dev(struct iris_inst *inst, enum iris_buffer_type buffer_type); #endif diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index bd38d84c9cc79..8ed6520f5ae3a 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -107,7 +107,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ src_vq->drv_priv = inst; src_vq->buf_struct_size = sizeof(struct iris_buffer); src_vq->min_reqbufs_allocation = MIN_BUFFERS; - src_vq->dev = inst->core->dev; + src_vq->dev = iris_get_cb_dev(inst, BUF_INPUT); src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) @@ -121,7 +121,7 @@ iris_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_ dst_vq->drv_priv = inst; dst_vq->buf_struct_size = sizeof(struct iris_buffer); dst_vq->min_reqbufs_allocation = MIN_BUFFERS; - dst_vq->dev = inst->core->dev; + dst_vq->dev = iris_get_cb_dev(inst, BUF_OUTPUT); dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); diff --git a/include/dt-bindings/media/qcom,sm8550-iris.h b/include/dt-bindings/media/qcom,sm8550-iris.h new file mode 100644 index 0000000000000..5165ef817f8bb --- /dev/null +++ b/include/dt-bindings/media/qcom,sm8550-iris.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ +#define _DT_BINDINGS_MEDIA_QCOM_SM8550_IRIS_H_ + +/* Function identifiers for iommu-map to attach for the context bank devices */ +#define IRIS_NON_PIXEL_VCODEC 0 +#define IRIS_PIXEL 1 + +#endif