diff options
author | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2020-12-01 16:21:40 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 2020-12-01 16:21:40 +0100 |
commit | 67e061f044e46c9823e59ca7981786f858bfa292 (patch) | |
tree | 6a7a4e19aa0742ba825dc6a455687d967f77c055 /drivers/media/platform | |
parent | a3f132df0e5f25399c9592c2d14997975ddbf290 (diff) | |
parent | b65054597872ce3aefbc6a666385eabdf9e288da (diff) | |
download | linux-67e061f044e46c9823e59ca7981786f858bfa292.tar.bz2 |
Merge tag 'v5.10-rc6' into patchwork
Linux 5.10-rc6
* tag 'v5.10-rc6': (1815 commits)
Linux 5.10-rc6
sock: set sk_err to ee_errno on dequeue from errq
mptcp: fix NULL ptr dereference on bad MPJ
net: openvswitch: fix TTL decrement action netlink message format
perf probe: Change function definition check due to broken DWARF
perf probe: Fix to die_entrypc() returns error correctly
perf stat: Use proper cpu for shadow stats
perf record: Synthesize cgroup events only if needed
perf diff: Fix error return value in __cmd_diff()
perf tools: Update copy of libbpf's hashmap.c
x86/mce: Do not overwrite no_way_out if mce_end() fails
kvm: x86/mmu: Fix get_mmio_spte() on CPUs supporting 5-level PT
KVM: x86: Fix split-irqchip vs interrupt injection window request
KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
usb: typec: stusb160x: fix power-opmode property with typec-power-opmode
printk: finalize records with trailing newlines
can: af_can: can_rx_unregister(): remove WARN() statement from list operation sanity check
can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from request_threaded_irq()'s flags
...
Diffstat (limited to 'drivers/media/platform')
-rw-r--r-- | drivers/media/platform/Kconfig | 28 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/Makefile | 10 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c | 174 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h | 7 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h | 52 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c | 73 | ||||
-rw-r--r-- | drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c | 110 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/core.h | 15 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/pm_helpers.c | 4 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/venc.c | 31 | ||||
-rw-r--r-- | drivers/media/platform/qcom/venus/venc_ctrls.c | 14 |
13 files changed, 335 insertions, 187 deletions
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index b161f2ba238f..ffffef2267f4 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -271,17 +271,31 @@ config VIDEO_MEDIATEK_VCODEC depends on MTK_IOMMU || COMPILE_TEST depends on VIDEO_DEV && VIDEO_V4L2 depends on ARCH_MEDIATEK || COMPILE_TEST + depends on VIDEO_MEDIATEK_VPU || MTK_SCP + # The two following lines ensure we have the same state ("m" or "y") as + # our dependencies, to avoid missing symbols during link. + depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU + depends on MTK_SCP || !MTK_SCP select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV - select VIDEO_MEDIATEK_VPU - select MTK_SCP + select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU + select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP help - Mediatek video codec driver provides HW capability to - encode and decode in a range of video formats - This driver rely on VPU driver to communicate with VPU. + Mediatek video codec driver provides HW capability to + encode and decode in a range of video formats on MT8173 + and MT8183. + + Note that support for MT8173 requires VIDEO_MEDIATEK_VPU to + also be selected. Support for MT8183 depends on MTK_SCP. + + To compile this driver as modules, choose M here: the + modules will be called mtk-vcodec-dec and mtk-vcodec-enc. + +config VIDEO_MEDIATEK_VCODEC_VPU + bool - To compile this driver as modules, choose M here: the - modules will be called mtk-vcodec-dec and mtk-vcodec-enc. +config VIDEO_MEDIATEK_VCODEC_SCP + bool config VIDEO_MEM2MEM_DEINTERLACE tristate "Deinterlace support" diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile index f679c6e1a3e9..4618d43dbbc8 100644 --- a/drivers/media/platform/mtk-vcodec/Makefile +++ b/drivers/media/platform/mtk-vcodec/Makefile @@ -24,4 +24,12 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \ mtk-vcodec-common-y := mtk_vcodec_intr.o \ mtk_vcodec_util.o \ - mtk_vcodec_fw.o + mtk_vcodec_fw.o \ + +ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU),) +mtk-vcodec-common-y += mtk_vcodec_fw_vpu.o +endif + +ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),) +mtk-vcodec-common-y += mtk_vcodec_fw_scp.o +endif diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index c7ed09fbafb6..147dfef1638d 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -234,7 +234,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) } dma_set_max_seg_size(&pdev->dev, UINT_MAX); - dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_DEC); + dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, DECODER); if (IS_ERR(dev->fw_handler)) return PTR_ERR(dev->fw_handler); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c index a2aa96b03f66..dfb42e19bf81 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c @@ -286,7 +286,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) } dma_set_max_seg_size(&pdev->dev, UINT_MAX); - dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_ENC); + dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, ENCODER); if (IS_ERR(dev->fw_handler)) return PTR_ERR(dev->fw_handler); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c index 6c2a2568d844..94b39ae5c2e1 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.c @@ -1,193 +1,29 @@ // SPDX-License-Identifier: GPL-2.0 #include "mtk_vcodec_fw.h" +#include "mtk_vcodec_fw_priv.h" #include "mtk_vcodec_util.h" #include "mtk_vcodec_drv.h" -struct mtk_vcodec_fw_ops { - int (*load_firmware)(struct mtk_vcodec_fw *fw); - unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw); - unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw); - void * (*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr); - int (*ipi_register)(struct mtk_vcodec_fw *fw, int id, - mtk_vcodec_ipi_handler handler, const char *name, void *priv); - int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf, - unsigned int len, unsigned int wait); -}; - -struct mtk_vcodec_fw { - enum mtk_vcodec_fw_type type; - const struct mtk_vcodec_fw_ops *ops; - struct platform_device *pdev; - struct mtk_scp *scp; -}; - -static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw) -{ - return vpu_load_firmware(fw->pdev); -} - -static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw) -{ - return vpu_get_vdec_hw_capa(fw->pdev); -} - -static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw) -{ - return vpu_get_venc_hw_capa(fw->pdev); -} - -static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw, - u32 dtcm_dmem_addr) -{ - return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr); -} - -static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id, - mtk_vcodec_ipi_handler handler, - const char *name, void *priv) -{ - /* - * The handler we receive takes a void * as its first argument. We - * cannot change this because it needs to be passed down to the rproc - * subsystem when SCP is used. VPU takes a const argument, which is - * more constrained, so the conversion below is safe. - */ - ipi_handler_t handler_const = (ipi_handler_t)handler; - - return vpu_ipi_register(fw->pdev, id, handler_const, name, priv); -} - -static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, - unsigned int len, unsigned int wait) -{ - return vpu_ipi_send(fw->pdev, id, buf, len); -} - -static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = { - .load_firmware = mtk_vcodec_vpu_load_firmware, - .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa, - .get_venc_capa = mtk_vcodec_vpu_get_venc_capa, - .map_dm_addr = mtk_vcodec_vpu_map_dm_addr, - .ipi_register = mtk_vcodec_vpu_set_ipi_register, - .ipi_send = mtk_vcodec_vpu_ipi_send, -}; - -static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw) -{ - return rproc_boot(scp_get_rproc(fw->scp)); -} - -static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw) -{ - return scp_get_vdec_hw_capa(fw->scp); -} - -static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw) -{ - return scp_get_venc_hw_capa(fw->scp); -} - -static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw, - u32 dtcm_dmem_addr) -{ - return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr); -} - -static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id, - mtk_vcodec_ipi_handler handler, - const char *name, void *priv) -{ - return scp_ipi_register(fw->scp, id, handler, priv); -} - -static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, - unsigned int len, unsigned int wait) -{ - return scp_ipi_send(fw->scp, id, buf, len, wait); -} - -static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = { - .load_firmware = mtk_vcodec_scp_load_firmware, - .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa, - .get_venc_capa = mtk_vcodec_scp_get_venc_capa, - .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr, - .ipi_register = mtk_vcodec_scp_set_ipi_register, - .ipi_send = mtk_vcodec_scp_ipi_send, -}; - -static void mtk_vcodec_reset_handler(void *priv) -{ - struct mtk_vcodec_dev *dev = priv; - struct mtk_vcodec_ctx *ctx; - - mtk_v4l2_err("Watchdog timeout!!"); - - mutex_lock(&dev->dev_mutex); - list_for_each_entry(ctx, &dev->ctx_list, list) { - ctx->state = MTK_STATE_ABORT; - mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT", - ctx->id); - } - mutex_unlock(&dev->dev_mutex); -} - struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev, enum mtk_vcodec_fw_type type, - enum rst_id rst_id) + enum mtk_vcodec_fw_use fw_use) { - const struct mtk_vcodec_fw_ops *ops; - struct mtk_vcodec_fw *fw; - struct platform_device *fw_pdev = NULL; - struct mtk_scp *scp = NULL; - switch (type) { case VPU: - ops = &mtk_vcodec_vpu_msg; - fw_pdev = vpu_get_plat_device(dev->plat_dev); - if (!fw_pdev) { - mtk_v4l2_err("firmware device is not ready"); - return ERR_PTR(-EINVAL); - } - vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_reset_handler, - dev, rst_id); - break; + return mtk_vcodec_fw_vpu_init(dev, fw_use); case SCP: - ops = &mtk_vcodec_rproc_msg; - scp = scp_get(dev->plat_dev); - if (!scp) { - mtk_v4l2_err("could not get vdec scp handle"); - return ERR_PTR(-EPROBE_DEFER); - } - break; + return mtk_vcodec_fw_scp_init(dev); default: mtk_v4l2_err("invalid vcodec fw type"); return ERR_PTR(-EINVAL); } - - fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); - if (!fw) - return ERR_PTR(-EINVAL); - - fw->type = type; - fw->ops = ops; - fw->pdev = fw_pdev; - fw->scp = scp; - - return fw; } EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select); void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw) { - switch (fw->type) { - case VPU: - put_device(&fw->pdev->dev); - break; - case SCP: - scp_put(fw->scp); - break; - } + fw->ops->release(fw); } EXPORT_SYMBOL_GPL(mtk_vcodec_fw_release); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h index fadbbe6ba6cd..539bb626772c 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw.h @@ -15,6 +15,11 @@ enum mtk_vcodec_fw_type { SCP, }; +enum mtk_vcodec_fw_use { + DECODER, + ENCODER, +}; + struct mtk_vcodec_fw; typedef void (*mtk_vcodec_ipi_handler) (void *data, @@ -22,7 +27,7 @@ typedef void (*mtk_vcodec_ipi_handler) (void *data, struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev, enum mtk_vcodec_fw_type type, - enum rst_id rst_id); + enum mtk_vcodec_fw_use fw_use); void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw); int mtk_vcodec_fw_load_firmware(struct mtk_vcodec_fw *fw); diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h new file mode 100644 index 000000000000..b41e66185cec --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _MTK_VCODEC_FW_PRIV_H_ +#define _MTK_VCODEC_FW_PRIV_H_ + +#include "mtk_vcodec_fw.h" + +struct mtk_vcodec_dev; + +struct mtk_vcodec_fw { + enum mtk_vcodec_fw_type type; + const struct mtk_vcodec_fw_ops *ops; + struct platform_device *pdev; + struct mtk_scp *scp; +}; + +struct mtk_vcodec_fw_ops { + int (*load_firmware)(struct mtk_vcodec_fw *fw); + unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw); + unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw); + void *(*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr); + int (*ipi_register)(struct mtk_vcodec_fw *fw, int id, + mtk_vcodec_ipi_handler handler, const char *name, + void *priv); + int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf, + unsigned int len, unsigned int wait); + void (*release)(struct mtk_vcodec_fw *fw); +}; + +#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU) +struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, + enum mtk_vcodec_fw_use fw_use); +#else +static inline struct mtk_vcodec_fw * +mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, + enum mtk_vcodec_fw_use fw_use) +{ + return ERR_PTR(-ENODEV); +} +#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_VPU */ + +#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP) +struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev); +#else +static inline struct mtk_vcodec_fw * +mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev) +{ + return ERR_PTR(-ENODEV); +} +#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_SCP */ + +#endif /* _MTK_VCODEC_FW_PRIV_H_ */ diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c new file mode 100644 index 000000000000..d8e66b645bd8 --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "mtk_vcodec_fw_priv.h" +#include "mtk_vcodec_util.h" +#include "mtk_vcodec_drv.h" + +static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw) +{ + return rproc_boot(scp_get_rproc(fw->scp)); +} + +static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw) +{ + return scp_get_vdec_hw_capa(fw->scp); +} + +static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw) +{ + return scp_get_venc_hw_capa(fw->scp); +} + +static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw, + u32 dtcm_dmem_addr) +{ + return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr); +} + +static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id, + mtk_vcodec_ipi_handler handler, + const char *name, void *priv) +{ + return scp_ipi_register(fw->scp, id, handler, priv); +} + +static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, + unsigned int len, unsigned int wait) +{ + return scp_ipi_send(fw->scp, id, buf, len, wait); +} + +static void mtk_vcodec_scp_release(struct mtk_vcodec_fw *fw) +{ + scp_put(fw->scp); +} + +static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = { + .load_firmware = mtk_vcodec_scp_load_firmware, + .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa, + .get_venc_capa = mtk_vcodec_scp_get_venc_capa, + .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr, + .ipi_register = mtk_vcodec_scp_set_ipi_register, + .ipi_send = mtk_vcodec_scp_ipi_send, + .release = mtk_vcodec_scp_release, +}; + +struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev) +{ + struct mtk_vcodec_fw *fw; + struct mtk_scp *scp; + + scp = scp_get(dev->plat_dev); + if (!scp) { + mtk_v4l2_err("could not get vdec scp handle"); + return ERR_PTR(-EPROBE_DEFER); + } + + fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); + fw->type = SCP; + fw->ops = &mtk_vcodec_rproc_msg; + fw->scp = scp; + + return fw; +} diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c new file mode 100644 index 000000000000..cd27f637dbe7 --- /dev/null +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "mtk_vcodec_fw_priv.h" +#include "mtk_vcodec_util.h" +#include "mtk_vcodec_drv.h" + +static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw) +{ + return vpu_load_firmware(fw->pdev); +} + +static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw) +{ + return vpu_get_vdec_hw_capa(fw->pdev); +} + +static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw) +{ + return vpu_get_venc_hw_capa(fw->pdev); +} + +static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw, + u32 dtcm_dmem_addr) +{ + return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr); +} + +static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id, + mtk_vcodec_ipi_handler handler, + const char *name, void *priv) +{ + /* + * The handler we receive takes a void * as its first argument. We + * cannot change this because it needs to be passed down to the rproc + * subsystem when SCP is used. VPU takes a const argument, which is + * more constrained, so the conversion below is safe. + */ + ipi_handler_t handler_const = (ipi_handler_t)handler; + + return vpu_ipi_register(fw->pdev, id, handler_const, name, priv); +} + +static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, + unsigned int len, unsigned int wait) +{ + return vpu_ipi_send(fw->pdev, id, buf, len); +} + +static void mtk_vcodec_vpu_release(struct mtk_vcodec_fw *fw) +{ + put_device(&fw->pdev->dev); +} + +static void mtk_vcodec_vpu_reset_handler(void *priv) +{ + struct mtk_vcodec_dev *dev = priv; + struct mtk_vcodec_ctx *ctx; + + mtk_v4l2_err("Watchdog timeout!!"); + + mutex_lock(&dev->dev_mutex); + list_for_each_entry(ctx, &dev->ctx_list, list) { + ctx->state = MTK_STATE_ABORT; + mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT", + ctx->id); + } + mutex_unlock(&dev->dev_mutex); +} + +static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = { + .load_firmware = mtk_vcodec_vpu_load_firmware, + .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa, + .get_venc_capa = mtk_vcodec_vpu_get_venc_capa, + .map_dm_addr = mtk_vcodec_vpu_map_dm_addr, + .ipi_register = mtk_vcodec_vpu_set_ipi_register, + .ipi_send = mtk_vcodec_vpu_ipi_send, + .release = mtk_vcodec_vpu_release, +}; + +struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, + enum mtk_vcodec_fw_use fw_use) +{ + struct platform_device *fw_pdev; + struct mtk_vcodec_fw *fw; + enum rst_id rst_id; + + switch (fw_use) { + case ENCODER: + rst_id = VPU_RST_ENC; + break; + case DECODER: + default: + rst_id = VPU_RST_DEC; + break; + } + + fw_pdev = vpu_get_plat_device(dev->plat_dev); + if (!fw_pdev) { + mtk_v4l2_err("firmware device is not ready"); + return ERR_PTR(-EINVAL); + } + vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id); + + fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); + fw->type = VPU; + fw->ops = &mtk_vcodec_vpu_msg; + fw->pdev = fw_pdev; + + return fw; +} diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 3bc129a4f817..f03ed427accd 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -243,8 +243,19 @@ struct venc_controls { u32 header_mode; - u32 profile; - u32 level; + struct { + u32 h264; + u32 mpeg4; + u32 hevc; + u32 vp8; + u32 vp9; + } profile; + struct { + u32 h264; + u32 mpeg4; + u32 hevc; + u32 vp9; + } level; }; struct venus_buffer { diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index 12784e9b1d66..ca99908ca3d3 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -804,7 +804,7 @@ skip_pmdomains: return 0; opp_dl_add_err: - dev_pm_domain_detach(core->opp_pmdomain, true); + dev_pm_opp_detach_genpd(core->opp_table); opp_attach_err: if (core->pd_dl_venus) { device_link_del(core->pd_dl_venus); @@ -842,7 +842,7 @@ skip_pmdomains: if (core->opp_dl_venus) device_link_del(core->opp_dl_venus); - dev_pm_domain_detach(core->opp_pmdomain, true); + dev_pm_opp_detach_genpd(core->opp_table); } static int core_get_v4(struct device *dev) diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 0bf92cc21f3a..1c61602c5de1 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -537,6 +537,7 @@ static int venc_set_properties(struct venus_inst *inst) struct hfi_quantization quant; struct hfi_quantization_range quant_range; u32 ptype, rate_control, bitrate; + u32 profile, level; int ret; ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); @@ -684,7 +685,35 @@ static int venc_set_properties(struct venus_inst *inst) if (ret) return ret; - ret = venus_helper_set_profile_level(inst, ctr->profile, ctr->level); + switch (inst->hfi_codec) { + case HFI_VIDEO_CODEC_H264: + profile = ctr->profile.h264; + level = ctr->level.h264; + break; + case HFI_VIDEO_CODEC_MPEG4: + profile = ctr->profile.mpeg4; + level = ctr->level.mpeg4; + break; + case HFI_VIDEO_CODEC_VP8: + profile = ctr->profile.vp8; + level = 0; + break; + case HFI_VIDEO_CODEC_VP9: + profile = ctr->profile.vp9; + level = ctr->level.vp9; + break; + case HFI_VIDEO_CODEC_HEVC: + profile = ctr->profile.hevc; + level = ctr->level.hevc; + break; + case HFI_VIDEO_CODEC_MPEG2: + default: + profile = 0; + level = 0; + break; + } + + ret = venus_helper_set_profile_level(inst, profile, level); if (ret) return ret; diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index 0708b3b89d0c..cf860e6446c0 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -103,15 +103,25 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) ctr->h264_entropy_mode = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: + ctr->profile.mpeg4 = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_H264_PROFILE: + ctr->profile.h264 = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: + ctr->profile.hevc = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: - ctr->profile = ctrl->val; + ctr->profile.vp8 = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: + ctr->level.mpeg4 = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: + ctr->level.h264 = ctrl->val; + break; case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: - ctr->level = ctrl->val; + ctr->level.hevc = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: ctr->h264_i_qp = ctrl->val; |