From 4ac8d4b38281daeedb255bd8671db406247bcb9c Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:10:03 +0100 Subject: [PATCH 01/35] Revert "During my research I found that some of the requirements for the memory buffers for MFC v6+ devices were blindly copied from the previous (v5) version and simply turned out to be excessive. The relaxed requirements are applied by the recent patches to the MFC driver and the driver is now fully functional even without the reserved memory blocks for all v6+ variants. This patch removes those reserved memory nodes from all boards having MFC v6+ hardware block." This reverts commit 7f3f878710c40e46bb42bcea552273bd54452b65. --- arch/arm/boot/dts/exynos5250-arndale.dts | 1 + arch/arm/boot/dts/exynos5250-smdk5250.dts | 1 + arch/arm/boot/dts/exynos5250-spring.dts | 1 + arch/arm/boot/dts/exynos5420-arndale-octa.dts | 1 + arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 + arch/arm/boot/dts/exynos5420-smdk5420.dts | 1 + arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 1 + arch/arm/boot/dts/exynos5800-peach-pi.dts | 1 + 8 files changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 6a432460eb77..6098dacd09f1 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -14,6 +14,7 @@ #include #include #include "exynos5250.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Insignal Arndale evaluation board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 6632f657394e..a97a785ccc6b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -13,6 +13,7 @@ #include #include #include "exynos5250.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index 95c3bcace9dc..4d7bdb735ed3 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -14,6 +14,7 @@ #include #include #include "exynos5250.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Spring"; diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index ee1bb9b8b366..9cc83c51c925 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -16,6 +16,7 @@ #include #include #include +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Insignal Arndale Octa evaluation board based on EXYNOS5420"; diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 672f49ee27e2..ec4a00f1ce01 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -16,6 +16,7 @@ #include #include "exynos5420.dtsi" #include "exynos5420-cpus.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Peach Pit Rev 6+"; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 08c8ab173e87..aaccd0da41e5 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -13,6 +13,7 @@ #include "exynos5420.dtsi" #include "exynos5420-cpus.dtsi" #include +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Samsung SMDK5420 board based on EXYNOS5420"; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 6412070b6344..3cd7cb3626e1 100755 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -19,6 +19,7 @@ #include #include "exynos5800.dtsi" #include "exynos5422-cpus.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { revision = <0x0100>; diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 6f2364e12607..01f466816fea 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -16,6 +16,7 @@ #include #include "exynos5800.dtsi" #include "exynos5420-cpus.dtsi" +#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Peach Pi Rev 10+"; From 0e95bb5ef686452830cc2b2ce239ab40074af888 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:10:43 +0100 Subject: [PATCH 02/35] Revert "It turned out that all versions of MFC v6+ hardware doesn't have a strict requirement for ALL buffers to be allocated on higher addresses than the firmware base like it was documented for MFC v5. This requirement is true only for the device and per-context buffers. All video data buffers can be allocated anywhere for all MFC v6+ versions. Basing on this fact, the special DMA configuration based on two reserved memory regions is not really needed for MFC v6+ devices, because the memory requirements for the firmware, device and per-context buffers can be fulfilled by the simple probe-time pre-allocated block allocator instroduced in previous patch." This reverts commit 67d8fdd38deec1734be23d223d9279169006c812. --- Documentation/devicetree/bindings/media/s5p-mfc.txt | 2 +- drivers/media/platform/s5p-mfc/s5p_mfc.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt index d3404b5d4d17..2c901286d818 100644 --- a/Documentation/devicetree/bindings/media/s5p-mfc.txt +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt @@ -28,7 +28,7 @@ Optional properties: - memory-region : from reserved memory binding: phandles to two reserved memory regions, first is for "left" mfc memory bus interfaces, second if for the "right" mfc memory bus, used when no SYSMMU - support is available; used only by MFC v5 present in Exynos4 SoCs + support is available Obsolete properties: - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 5fa080649e2a..45b8cdef94b0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1182,12 +1182,9 @@ static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - unsigned long mem_size = SZ_4M; + unsigned long mem_size = SZ_8M; unsigned int bitmap_size; - if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev)) - mem_size = SZ_8M; - if (mfc_mem_size) mem_size = memparse(mfc_mem_size, NULL); @@ -1247,7 +1244,7 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev)) + if (exynos_is_iommu_available(dev)) return s5p_mfc_configure_common_memory(mfc_dev); else return s5p_mfc_configure_2port_memory(mfc_dev); @@ -1258,7 +1255,7 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; s5p_mfc_release_firmware(mfc_dev); - if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev)) + if (exynos_is_iommu_available(dev)) s5p_mfc_unconfigure_common_memory(mfc_dev); else s5p_mfc_unconfigure_2port_memory(mfc_dev); From 9329826759ded613c3a4b69bb8eaf4304b04ab71 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:11:03 +0100 Subject: [PATCH 03/35] Revert "The main reason for using special configuration of IOMMU domain was the problem with MFC firmware, which failed to operate properly when placed at 0 DMA address. Instead of adding custom code for configuring each variant of IOMMU domain and architecture specific glue code, simply use what arch code provides and if the DMA base address equals zero, skip first 128 KiB to keep required alignment. This patch also make the driver operational on ARM64 architecture, because it no longer depends on ARM specific DMA-mapping and IOMMU glue code functions." This reverts commit 9a09c76039f99da7945f9a74d1f833aad705229a. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 30 ++++++----- .../media/platform/s5p-mfc/s5p_mfc_iommu.h | 51 ++++++++++++++++++- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 45b8cdef94b0..1a87af65c06a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1184,6 +1184,18 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; unsigned long mem_size = SZ_8M; unsigned int bitmap_size; + /* + * When IOMMU is available, we cannot use the default configuration, + * because of MFC firmware requirements: address space limited to + * 256M and non-zero default start address. + * This is still simplified, not optimal configuration, but for now + * IOMMU core doesn't allow to configure device's IOMMUs channel + * separately. + */ + int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, + S5P_MFC_IOMMU_DMA_SIZE); + if (ret) + return ret; if (mfc_mem_size) mem_size = memparse(mfc_mem_size, NULL); @@ -1191,8 +1203,10 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!mfc_dev->mem_bitmap) + if (!mfc_dev->mem_bitmap) { + exynos_unconfigure_iommu(dev); return -ENOMEM; + } mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, &mfc_dev->mem_base, GFP_KERNEL); @@ -1200,24 +1214,13 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) kfree(mfc_dev->mem_bitmap); dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", (mem_size / SZ_1M)); + exynos_unconfigure_iommu(dev); return -ENOMEM; } mfc_dev->mem_size = mem_size; mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; - /* - * MFC hardware cannot handle 0 as a base address, so mark first 128K - * as used (to keep required base alignment) and adjust base address - */ - if (mfc_dev->mem_base == (dma_addr_t)0) { - unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER; - - bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT); - mfc_dev->dma_base[BANK1_CTX] += offset; - mfc_dev->dma_base[BANK2_CTX] += offset; - } - /* Firmware allocation cannot fail in this case */ s5p_mfc_alloc_firmware(mfc_dev); @@ -1234,6 +1237,7 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; + exynos_unconfigure_iommu(dev); dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, mfc_dev->mem_base); kfree(mfc_dev->mem_bitmap); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h index 76667924ee2a..6962132ae8fa 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h @@ -11,13 +11,54 @@ #ifndef S5P_MFC_IOMMU_H_ #define S5P_MFC_IOMMU_H_ -#if defined(CONFIG_EXYNOS_IOMMU) +#define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu +#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M + +#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) + +#include static inline bool exynos_is_iommu_available(struct device *dev) { return dev->archdata.iommu != NULL; } +static inline void exynos_unconfigure_iommu(struct device *dev) +{ + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); + + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); +} + +static inline int exynos_configure_iommu(struct device *dev, + unsigned int base, unsigned int size) +{ + struct dma_iommu_mapping *mapping = NULL; + int ret; + + /* Disable the default mapping created by device core */ + if (to_dma_iommu_mapping(dev)) + exynos_unconfigure_iommu(dev); + + mapping = arm_iommu_create_mapping(dev->bus, base, size); + if (IS_ERR(mapping)) { + pr_warn("Failed to create IOMMU mapping for device %s\n", + dev_name(dev)); + return PTR_ERR(mapping); + } + + ret = arm_iommu_attach_device(dev, mapping); + if (ret) { + pr_warn("Failed to attached device %s to IOMMU_mapping\n", + dev_name(dev)); + arm_iommu_release_mapping(mapping); + return ret; + } + + return 0; +} + #else static inline bool exynos_is_iommu_available(struct device *dev) @@ -25,6 +66,14 @@ static inline bool exynos_is_iommu_available(struct device *dev) return false; } +static inline int exynos_configure_iommu(struct device *dev, + unsigned int base, unsigned int size) +{ + return -ENOSYS; +} + +static inline void exynos_unconfigure_iommu(struct device *dev) { } + #endif #endif /* S5P_MFC_IOMMU_H_ */ From d7134bc783a84ebb1c219ca0e104e9aa53ba8424 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:11:42 +0100 Subject: [PATCH 04/35] Revert "Current MFC driver depends on the fact that when IOMMU is available, the DMA-mapping framework and its IOMMU glue will use first-fit allocator. This was true for ARM architecture, but its not for ARM64 arch. However, in case of MFC v6+ hardware and latest firmware, it turned out that there is no strict requirement for ALL buffers to be allocated on higher addresses than the firmware base. This requirement is true only for the device and per-context buffers. All video data buffers can be allocated anywhere for all MFC v6+ versions." This reverts commit 2bf9e9f04adf02ee1e4972827295a3d662eb59f5. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 47 +++------------ .../media/platform/s5p-mfc/s5p_mfc_common.h | 4 -- drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 57 +++++++------------ 3 files changed, 27 insertions(+), 81 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 1a87af65c06a..3618e2272f5e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -43,10 +43,6 @@ int mfc_debug_level; module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages"); -static char *mfc_mem_size = NULL; -module_param_named(mem, mfc_mem_size, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers"); - /* Helper functions for interrupt processing */ /* Remove from hw execution round robin */ @@ -1182,8 +1178,6 @@ static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - unsigned long mem_size = SZ_8M; - unsigned int bitmap_size; /* * When IOMMU is available, we cannot use the default configuration, * because of MFC firmware requirements: address space limited to @@ -1197,38 +1191,16 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) if (ret) return ret; - if (mfc_mem_size) - mem_size = memparse(mfc_mem_size, NULL); - - bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); - - mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!mfc_dev->mem_bitmap) { - exynos_unconfigure_iommu(dev); - return -ENOMEM; - } - - mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, - &mfc_dev->mem_base, GFP_KERNEL); - if (!mfc_dev->mem_virt) { - kfree(mfc_dev->mem_bitmap); - dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", - (mem_size / SZ_1M)); - exynos_unconfigure_iommu(dev); - return -ENOMEM; - } - mfc_dev->mem_size = mem_size; - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; - mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; - - /* Firmware allocation cannot fail in this case */ - s5p_mfc_alloc_firmware(mfc_dev); - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + ret = s5p_mfc_alloc_firmware(mfc_dev); + if (ret) { + exynos_unconfigure_iommu(dev); + return ret; + } - dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n", - (mem_size / SZ_1M)); + mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->dma_base[BANK2_CTX] = mfc_dev->fw_buf.dma; + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); return 0; } @@ -1238,9 +1210,6 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; exynos_unconfigure_iommu(dev); - dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, - mfc_dev->mem_base); - kfree(mfc_dev->mem_bitmap); vb2_dma_contig_clear_max_seg_size(dev); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index a209a7a52907..e38a8eec15f9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -315,10 +315,6 @@ struct s5p_mfc_dev { unsigned int int_err; wait_queue_head_t queue; struct s5p_mfc_priv_buf fw_buf; - size_t mem_size; - dma_addr_t mem_base; - unsigned long *mem_bitmap; - void *mem_virt; dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 34a66189d980..9294ee124661 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -40,60 +40,41 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, struct s5p_mfc_priv_buf *b) { - unsigned int bits = dev->mem_size >> PAGE_SHIFT; - unsigned int count = b->size >> PAGE_SHIFT; - unsigned int align = (SZ_64K >> PAGE_SHIFT) - 1; - unsigned int start, offset; + struct device *mem_dev = dev->mem_dev[mem_ctx]; + dma_addr_t base = dev->dma_base[mem_ctx]; mfc_debug(3, "Allocating priv: %zu\n", b->size); - if (dev->mem_virt) { - start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align); - if (start > bits) - goto no_mem; + b->ctx = mem_ctx; + b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); - bitmap_set(dev->mem_bitmap, start, count); - offset = start << PAGE_SHIFT; - b->virt = dev->mem_virt + offset; - b->dma = dev->mem_base + offset; - } else { - struct device *mem_dev = dev->mem_dev[mem_ctx]; - dma_addr_t base = dev->dma_base[mem_ctx]; + if (!b->virt) { + mfc_err("Allocating private buffer of size %zu failed\n", + b->size); + return -ENOMEM; + } - b->ctx = mem_ctx; - b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); - if (!b->virt) - goto no_mem; - if (b->dma < base) { - mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", - &b->dma, &base); - dma_free_coherent(mem_dev, b->size, b->virt, b->dma); - return -ENOMEM; - } + if (b->dma < base) { + mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", + &b->dma, &base); + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + return -ENOMEM; } mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma); return 0; -no_mem: - mfc_err("Allocating private buffer of size %zu failed\n", b->size); - return -ENOMEM; } void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_priv_buf *b) { - if (dev->mem_virt) { - unsigned int start = (b->dma - dev->mem_base) >> PAGE_SHIFT; - unsigned int count = b->size >> PAGE_SHIFT; - - bitmap_clear(dev->mem_bitmap, start, count); - } else { - struct device *mem_dev = dev->mem_dev[b->ctx]; + struct device *mem_dev = dev->mem_dev[b->ctx]; + if (b->virt) { dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + b->virt = NULL; + b->dma = 0; + b->size = 0; } - b->virt = NULL; - b->dma = 0; - b->size = 0; } From 2fceb391ff122527960ab65f2e90838b0aa4f092 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:17:29 +0100 Subject: [PATCH 05/35] Revert "Move code for DMA memory configuration with IOMMU into separate function to make it easier to compare what is being done in each case." This reverts commit 5bd6e8b795ab9e95ab7d087d90c6e8f9e25e6f83. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 104 +++++++++-------------- 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 3618e2272f5e..c56ceb812de0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1107,14 +1107,43 @@ static struct device *s5p_mfc_alloc_memdev(struct device *dev, return NULL; } -static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) +static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; void *bank2_virt; dma_addr_t bank2_dma_addr; unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER; + struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf; int ret; + /* + * When IOMMU is available, we cannot use the default configuration, + * because of MFC firmware requirements: address space limited to + * 256M and non-zero default start address. + * This is still simplified, not optimal configuration, but for now + * IOMMU core doesn't allow to configure device's IOMMUs channel + * separately. + */ + if (exynos_is_iommu_available(dev)) { + int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, + S5P_MFC_IOMMU_DMA_SIZE); + if (ret) + return ret; + + mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; + ret = s5p_mfc_alloc_firmware(mfc_dev); + if (ret) { + exynos_unconfigure_iommu(dev); + return ret; + } + + mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; + mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma; + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + return 0; + } + /* * Create and initialize virtual devices for accessing * reserved memory regions. @@ -1138,7 +1167,7 @@ static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) return ret; } - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, &bank2_dma_addr, GFP_KERNEL); @@ -1167,71 +1196,22 @@ static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) return 0; } -static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) -{ - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); -} - -static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) -{ - struct device *dev = &mfc_dev->plat_dev->dev; - /* - * When IOMMU is available, we cannot use the default configuration, - * because of MFC firmware requirements: address space limited to - * 256M and non-zero default start address. - * This is still simplified, not optimal configuration, but for now - * IOMMU core doesn't allow to configure device's IOMMUs channel - * separately. - */ - int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, - S5P_MFC_IOMMU_DMA_SIZE); - if (ret) - return ret; - - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { - exynos_unconfigure_iommu(dev); - return ret; - } - - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; - mfc_dev->dma_base[BANK2_CTX] = mfc_dev->fw_buf.dma; - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - return 0; -} - -static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) -{ - struct device *dev = &mfc_dev->plat_dev->dev; - - exynos_unconfigure_iommu(dev); - vb2_dma_contig_clear_max_seg_size(dev); -} - -static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) -{ - struct device *dev = &mfc_dev->plat_dev->dev; - - if (exynos_is_iommu_available(dev)) - return s5p_mfc_configure_common_memory(mfc_dev); - else - return s5p_mfc_configure_2port_memory(mfc_dev); -} - static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; s5p_mfc_release_firmware(mfc_dev); - if (exynos_is_iommu_available(dev)) - s5p_mfc_unconfigure_common_memory(mfc_dev); - else - s5p_mfc_unconfigure_2port_memory(mfc_dev); + + if (exynos_is_iommu_available(dev)) { + exynos_unconfigure_iommu(dev); + vb2_dma_contig_clear_max_seg_size(dev); + return; + } + + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); } /* MFC probe function */ From 252fe43727fc4b9ea2d812cbce8884a7f9630ae2 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:17:50 +0100 Subject: [PATCH 06/35] Revert "Firmware for MFC v6+ variants is not larger than 400 KiB, so there is no need to allocate a full 1 MiB buffer for it. Reduce it to 512 KiB to keep proper alignment of allocated buffer." This reverts commit 3b9a20dc3ca76d19ca383b6419c33b68ec1f53dd. --- drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 2 +- drivers/media/platform/s5p-mfc/regs-mfc-v7.h | 2 +- drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h index c0166ee9a455..d2cd35916dc5 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h @@ -403,7 +403,7 @@ #define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */ /* MFCv6 variant defines */ -#define MAX_FW_SIZE_V6 (SZ_512K) /* 512KB */ +#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */ #define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V6 0x61 #define MFC_NUM_PORTS_V6 1 diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h index 9f220769d970..1a5c6fdf7846 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h @@ -34,7 +34,7 @@ #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4 /* MFCv7 variant defines */ -#define MAX_FW_SIZE_V7 (SZ_512K) /* 512KB */ +#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */ #define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V7 0x72 #define MFC_NUM_PORTS_V7 1 diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h index 75f5f7511d72..4d1c3750eb5e 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h @@ -116,7 +116,7 @@ #define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64 /* MFCv8 variant defines */ -#define MAX_FW_SIZE_V8 (SZ_512K) /* 512KB */ +#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */ #define MAX_CPB_SIZE_V8 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V8 0x80 #define MFC_NUM_PORTS_V8 1 From f4a1a0de1aa5e3baab238b37ecd9e7a89d9ca213 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:18:18 +0100 Subject: [PATCH 07/35] Revert "Once firmware buffer has been converted to use s5p_mfc_priv_buf structure, it is possible to allocate it with existing s5p_mfc_alloc_priv_buf() function. This change will help to reduce code variants in the next patches." This reverts commit 7866d659552947c98f688df0d6080b141b96f8c7. --- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index a1811ee538bd..b0cf3970117a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -27,7 +27,6 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; - int err; fw_buf->size = dev->variant->buf_size->fw; @@ -36,10 +35,11 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) return -ENOMEM; } - err = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->fw_buf); - if (err) { + fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, + &fw_buf->dma, GFP_KERNEL); + if (!fw_buf->virt) { mfc_err("Allocating bitprocessor buffer failed\n"); - return err; + return -ENOMEM; } return 0; @@ -92,7 +92,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) { /* Before calling this function one has to make sure * that MFC is no longer processing */ - s5p_mfc_release_priv_buf(dev, &dev->fw_buf); + if (!dev->fw_buf.virt) + return -EINVAL; + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_buf.size, + dev->fw_buf.virt, dev->fw_buf.dma); + dev->fw_buf.virt = NULL; return 0; } From fe223228b1bb9f4b789acaab603201fdfc644781 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:18:44 +0100 Subject: [PATCH 08/35] Revert "o complete DMA memory configuration for MFC device, allocation of the firmware buffer is needed, because some parameters are dependant on its base address. Till now, this has been handled in the s5p_mfc_alloc_firmware() function. This patch moves that logic to s5p_mfc_configure_dma_memory() to keep DMA memory related operations in a single place. This way s5p_mfc_alloc_firmware() is simplified and does what it name says. The other consequence of this change is moving s5p_mfc_alloc_firmware() call from the s5p_mfc_probe() function to the s5p_mfc_configure_dma_memory()." This reverts commit bd8e44da9d22c38bcabcba55da25400ba5c0b9b3. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 62 ++++--------------- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 31 ++++++++++ 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index c56ceb812de0..c24c380222a7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1110,11 +1110,6 @@ static struct device *s5p_mfc_alloc_memdev(struct device *dev, static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - void *bank2_virt; - dma_addr_t bank2_dma_addr; - unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER; - struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf; - int ret; /* * When IOMMU is available, we cannot use the default configuration, @@ -1127,21 +1122,14 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); - if (ret) - return ret; - - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { - exynos_unconfigure_iommu(dev); - return ret; + if (ret == 0) { + mfc_dev->mem_dev[BANK1_CTX] = + mfc_dev->mem_dev[BANK2_CTX] = dev; + vb2_dma_contig_set_max_seg_size(dev, + DMA_BIT_MASK(32)); } - mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; - mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma; - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - return 0; + return ret; } /* @@ -1159,35 +1147,6 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return -ENODEV; } - /* Allocate memory for firmware and initialize both banks addresses */ - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - return ret; - } - - mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; - - bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, - &bank2_dma_addr, GFP_KERNEL); - if (!bank2_virt) { - mfc_err("Allocating bank2 base failed\n"); - s5p_mfc_release_firmware(mfc_dev); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - return -ENOMEM; - } - - /* Valid buffers passed to MFC encoder with LAST_FRAME command - * should not have address of bank2 - MFC will treat it as a null frame. - * To avoid such situation we set bank2 address below the pool address. - */ - mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; - - dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt, - bank2_dma_addr); - vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX], DMA_BIT_MASK(32)); vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX], @@ -1200,8 +1159,6 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - s5p_mfc_release_firmware(mfc_dev); - if (exynos_is_iommu_available(dev)) { exynos_unconfigure_iommu(dev); vb2_dma_contig_clear_max_seg_size(dev); @@ -1278,6 +1235,10 @@ static int s5p_mfc_probe(struct platform_device *pdev) dev->watchdog_timer.data = (unsigned long)dev; dev->watchdog_timer.function = s5p_mfc_watchdog; + ret = s5p_mfc_alloc_firmware(dev); + if (ret) + goto err_res; + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_v4l2_dev_reg; @@ -1352,6 +1313,8 @@ err_enc_alloc: err_dec_alloc: v4l2_device_unregister(&dev->v4l2_dev); err_v4l2_dev_reg: + s5p_mfc_release_firmware(dev); +err_res: s5p_mfc_final_pm(dev); err_dma: s5p_mfc_unconfigure_dma_memory(dev); @@ -1393,6 +1356,7 @@ static int s5p_mfc_remove(struct platform_device *pdev) video_device_release(dev->vfd_enc); video_device_release(dev->vfd_dec); v4l2_device_unregister(&dev->v4l2_dev); + s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); s5p_mfc_final_pm(dev); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index b0cf3970117a..50d698968049 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -26,6 +26,9 @@ /* Allocate memory for firmware */ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { + void *bank2_virt; + dma_addr_t bank2_dma_addr; + unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; fw_buf->size = dev->variant->buf_size->fw; @@ -41,7 +44,35 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; } + dev->dma_base[BANK1_CTX] = fw_buf->dma; + if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { + bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], + align_size, &bank2_dma_addr, GFP_KERNEL); + + if (!bank2_virt) { + mfc_err("Allocating bank2 base failed\n"); + dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, + fw_buf->virt, fw_buf->dma); + fw_buf->virt = NULL; + return -ENOMEM; + } + + /* Valid buffers passed to MFC encoder with LAST_FRAME command + * should not have address of bank2 - MFC will treat it as a null frame. + * To avoid such situation we set bank2 address below the pool address. + */ + dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; + + dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, + bank2_virt, bank2_dma_addr); + + } else { + /* In this case bank2 can point to the same address as bank1. + * Firmware will always occupy the beginning of this area so it is + * impossible having a video frame buffer with zero address. */ + dev->dma_base[BANK2_CTX] = dev->dma_base[BANK1_CTX]; + } return 0; } From fa608b5883730ee69332f2b1678e730d5deb2844 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:19:23 +0100 Subject: [PATCH 09/35] Revert "Use s5p_mfc_priv_buf structure for keeping the firmware image. This will help handling of firmware buffer allocation in the next patches." This reverts commit 2d54a695b8aabd0dfc495c6cfd12183095959bb5. --- .../media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 2 +- .../media/platform/s5p-mfc/s5p_mfc_common.h | 3 +- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 36 +++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c index 4c80bb4243be..8c4739ca16d6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c @@ -47,7 +47,7 @@ static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) struct s5p_mfc_cmd_args h2r_args; memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - h2r_args.arg[0] = dev->fw_buf.size; + h2r_args.arg[0] = dev->fw_size; return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index e38a8eec15f9..be011700cb12 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -314,7 +314,8 @@ struct s5p_mfc_dev { int int_type; unsigned int int_err; wait_queue_head_t queue; - struct s5p_mfc_priv_buf fw_buf; + size_t fw_size; + void *fw_virt_addr; dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 50d698968049..c9bff3d0655f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -29,22 +29,21 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) void *bank2_virt; dma_addr_t bank2_dma_addr; unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; - struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; - fw_buf->size = dev->variant->buf_size->fw; + dev->fw_size = dev->variant->buf_size->fw; - if (fw_buf->virt) { + if (dev->fw_virt_addr) { mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); return -ENOMEM; } - fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, - &fw_buf->dma, GFP_KERNEL); - if (!fw_buf->virt) { + dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], + dev->fw_size, &dev->dma_base[BANK1_CTX], + GFP_KERNEL); + if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; } - dev->dma_base[BANK1_CTX] = fw_buf->dma; if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], @@ -52,9 +51,10 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); - dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, - fw_buf->virt, fw_buf->dma); - fw_buf->virt = NULL; + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, + dev->fw_virt_addr, + dev->dma_base[BANK1_CTX]); + dev->fw_virt_addr = NULL; return -ENOMEM; } @@ -101,17 +101,17 @@ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); return -EINVAL; } - if (fw_blob->size > dev->fw_buf.size) { + if (fw_blob->size > dev->fw_size) { mfc_err("MFC firmware is too big to be loaded\n"); release_firmware(fw_blob); return -ENOMEM; } - if (!dev->fw_buf.virt) { + if (!dev->fw_virt_addr) { mfc_err("MFC firmware is not allocated\n"); release_firmware(fw_blob); return -EINVAL; } - memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size); + memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); mfc_debug_leave(); @@ -123,11 +123,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) { /* Before calling this function one has to make sure * that MFC is no longer processing */ - if (!dev->fw_buf.virt) + if (!dev->fw_virt_addr) return -EINVAL; - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_buf.size, - dev->fw_buf.virt, dev->fw_buf.dma); - dev->fw_buf.virt = NULL; + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, + dev->fw_virt_addr, dev->dma_base[BANK1_CTX]); + dev->fw_virt_addr = NULL; return 0; } @@ -246,7 +246,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) int ret; mfc_debug_enter(); - if (!dev->fw_buf.virt) { + if (!dev->fw_virt_addr) { mfc_err("Firmware memory is not allocated.\n"); return -EINVAL; } From 4c2235b34686bd2eb36a01f09be0999716b92bd5 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:19:45 +0100 Subject: [PATCH 10/35] Revert "Setting DMA max segment size to 32 bit mask is a part of DMA memory configuration, so move those calls to s5p_mfc_configure_dma_memory() function." This reverts commit fe59dc08f8dc811e272e101a08666fade3cd1f82. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index c24c380222a7..67a0450b0bb5 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1122,13 +1122,9 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); - if (ret == 0) { + if (ret == 0) mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - vb2_dma_contig_set_max_seg_size(dev, - DMA_BIT_MASK(32)); - } - return ret; } @@ -1147,11 +1143,6 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return -ENODEV; } - vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX], - DMA_BIT_MASK(32)); - vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX], - DMA_BIT_MASK(32)); - return 0; } @@ -1161,14 +1152,11 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { exynos_unconfigure_iommu(dev); - vb2_dma_contig_clear_max_seg_size(dev); return; } device_unregister(mfc_dev->mem_dev[BANK1_CTX]); device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); } /* MFC probe function */ @@ -1226,6 +1214,11 @@ static int s5p_mfc_probe(struct platform_device *pdev) goto err_dma; } + vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX], + DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX], + DMA_BIT_MASK(32)); + mutex_init(&dev->mfc_mutex); init_waitqueue_head(&dev->queue); dev->hw_lock = 0; @@ -1358,6 +1351,8 @@ static int s5p_mfc_remove(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]); s5p_mfc_final_pm(dev); return 0; From 8d6048e4562d338ff359b0ce58340835d24cb5e0 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:20:02 +0100 Subject: [PATCH 11/35] Revert "Change parameters for s5p_mfc_alloc_priv_buf() and s5p_mfc_release_priv_buf() functions. Instead of DMA device pointer and a base, provide common MFC device structure and memory bank context identifier." This reverts commit 3dafb955c3a344bc64af8d0e5470e04c4a6de589. --- .../media/platform/s5p-mfc/s5p_mfc_common.h | 2 -- drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 20 +++++-------- drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 8 ++--- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 30 +++++++++++-------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 ++++++---- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index be011700cb12..d8b1e2bcfc6a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -240,14 +240,12 @@ struct s5p_mfc_variant { * buffer accessed by driver * @dma: DMA address, only valid when kernel DMA API used * @size: size of the buffer - * @ctx: memory context (bank) used for this allocation */ struct s5p_mfc_priv_buf { unsigned long ofs; void *virt; dma_addr_t dma; size_t size; - unsigned int ctx; }; /** diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 9294ee124661..99f65a92a6be 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -37,16 +37,12 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); } -int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, - struct s5p_mfc_priv_buf *b) +int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, + struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[mem_ctx]; - dma_addr_t base = dev->dma_base[mem_ctx]; - mfc_debug(3, "Allocating priv: %zu\n", b->size); - b->ctx = mem_ctx; - b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); if (!b->virt) { mfc_err("Allocating private buffer of size %zu failed\n", @@ -57,7 +53,7 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, if (b->dma < base) { mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", &b->dma, &base); - dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + dma_free_coherent(dev, b->size, b->virt, b->dma); return -ENOMEM; } @@ -65,13 +61,11 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, return 0; } -void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, - struct s5p_mfc_priv_buf *b) +void s5p_mfc_release_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[b->ctx]; - if (b->virt) { - dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + dma_free_coherent(dev, b->size, b->virt, b->dma); b->virt = NULL; b->dma = 0; b->size = 0; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 108e59382e0c..b6ac417ab63e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -315,10 +315,10 @@ struct s5p_mfc_hw_ops { void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); -int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, - struct s5p_mfc_priv_buf *b); -void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, - struct s5p_mfc_priv_buf *b); +int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, + struct s5p_mfc_priv_buf *b); +void s5p_mfc_release_priv_buf(struct device *dev, + struct s5p_mfc_priv_buf *b); #endif /* S5P_MFC_OPR_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 20e8a1bdc984..32ce9ade2edb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -41,7 +41,8 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -57,7 +58,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release temporary buffers for decoding */ static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->dsc); } /* Allocate codec buffers */ @@ -172,7 +173,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -181,10 +183,12 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) } /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK2_CTX, &ctx->bank2); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], + dev->dma_base[BANK2_CTX], &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); - s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], + &ctx->bank1); return ret; } BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); @@ -195,8 +199,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); - s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK2_CTX], &ctx->bank2); } /* Allocate memory for instance data buffer */ @@ -212,7 +216,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -225,10 +230,11 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); - s5p_mfc_release_priv_buf(dev, &ctx->ctx); + s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); return ret; } @@ -244,8 +250,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx); - s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->shm); } static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 4e5ead236455..51053ed68741 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,7 +239,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -252,7 +253,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); } /* Allocate memory for instance data buffer */ @@ -291,7 +292,8 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -308,7 +310,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); } /* Allocate context buffers for SYS_INIT */ @@ -320,7 +322,8 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->ctx_buf); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); return ret; @@ -337,7 +340,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) /* Release context buffers for SYS_INIT */ static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) { - s5p_mfc_release_priv_buf(dev, &dev->ctx_buf); + s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &dev->ctx_buf); } static int calc_plane(int width, int height) From 0608fed2ef44a128540eba853405713e09b8c0a2 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:20:34 +0100 Subject: [PATCH 12/35] Revert "Internal MFC driver device structure contains two entries for keeping addresses of the DMA memory banks. Replace them with the dma_base[] array and use defines for accessing particular banks. This will help to simplify code in the next patches." This reverts commit fbd8561d4962c97c288e4965df1ddec99dae8aeb. --- .../media/platform/s5p-mfc/s5p_mfc_common.h | 6 ++- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 27 ++++++------- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 38 +++++++++---------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 10 ++--- 4 files changed, 38 insertions(+), 43 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index d8b1e2bcfc6a..c0a77c105714 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -273,7 +273,8 @@ struct s5p_mfc_priv_buf { * @queue: waitqueue for waiting for completion of device commands * @fw_size: size of firmware * @fw_virt_addr: virtual firmware address - * @dma_base[]: address of the beginning of memory banks + * @bank1: address of the beginning of bank 1 memory + * @bank2: address of the beginning of bank 2 memory * @hw_lock: used for hardware locking * @ctx: array of driver contexts * @curr_ctx: number of the currently running context @@ -314,7 +315,8 @@ struct s5p_mfc_dev { wait_queue_head_t queue; size_t fw_size; void *fw_virt_addr; - dma_addr_t dma_base[BANK_CTX_NUM]; + dma_addr_t bank1; + dma_addr_t bank2; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; int curr_ctx; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index c9bff3d0655f..cd1406c75d9a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -38,8 +38,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], - dev->fw_size, &dev->dma_base[BANK1_CTX], - GFP_KERNEL); + dev->fw_size, &dev->bank1, GFP_KERNEL); + if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; @@ -52,8 +52,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, - dev->dma_base[BANK1_CTX]); + dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return -ENOMEM; } @@ -62,7 +61,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ - dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; + dev->bank2 = bank2_dma_addr - align_size; dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, bank2_virt, bank2_dma_addr); @@ -71,7 +70,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) /* In this case bank2 can point to the same address as bank1. * Firmware will always occupy the beginning of this area so it is * impossible having a video frame buffer with zero address. */ - dev->dma_base[BANK2_CTX] = dev->dma_base[BANK1_CTX]; + dev->bank2 = dev->bank1; } return 0; } @@ -126,7 +125,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) if (!dev->fw_virt_addr) return -EINVAL; dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->dma_base[BANK1_CTX]); + dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return 0; } @@ -212,17 +211,13 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) { if (IS_MFCV6_PLUS(dev)) { - mfc_write(dev, dev->dma_base[BANK1_CTX], - S5P_FIMV_RISC_BASE_ADDRESS_V6); - mfc_debug(2, "Base Address : %pad\n", - &dev->dma_base[BANK1_CTX]); + mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); + mfc_debug(2, "Base Address : %pad\n", &dev->bank1); } else { - mfc_write(dev, dev->dma_base[BANK1_CTX], - S5P_FIMV_MC_DRAMBASE_ADR_A); - mfc_write(dev, dev->dma_base[BANK2_CTX], - S5P_FIMV_MC_DRAMBASE_ADR_B); + mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A); + mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B); mfc_debug(2, "Bank1: %pad, Bank2: %pad\n", - &dev->dma_base[BANK1_CTX], &dev->dma_base[BANK2_CTX]); + &dev->bank1, &dev->bank2); } } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 32ce9ade2edb..65dd3e64b4db 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -30,8 +30,8 @@ #include #include -#define OFFSETA(x) (((x) - dev->dma_base[BANK1_CTX]) >> MFC_OFFSET_SHIFT) -#define OFFSETB(x) (((x) - dev->dma_base[BANK2_CTX]) >> MFC_OFFSET_SHIFT) +#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT) +#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT) /* Allocate temporary buffers for decoding */ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) @@ -41,8 +41,8 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -174,7 +174,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) if (ctx->bank1.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->bank1); + dev->bank1, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -184,7 +184,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], - dev->dma_base[BANK2_CTX], &ctx->bank2); + dev->bank2, &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], @@ -216,8 +216,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -230,8 +230,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); @@ -239,7 +239,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) } /* shared memory offset only keeps the offset from base (port a) */ - ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK1_CTX]; + ctx->shm.ofs = ctx->shm.dma - dev->bank1; BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); memset(ctx->shm.virt, 0, buf_size->shm); @@ -538,10 +538,10 @@ static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev = ctx->dev; - *y_addr = dev->dma_base[BANK2_CTX] + - (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT); - *c_addr = dev->dma_base[BANK2_CTX] + - (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT); + *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) + << MFC_OFFSET_SHIFT); + *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) + << MFC_OFFSET_SHIFT); } /* Set encoding ref & codec buffer */ @@ -1218,8 +1218,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) } if (list_empty(&ctx->src_queue)) { /* send null frame */ - s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK2_CTX], - dev->dma_base[BANK2_CTX]); + s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2); src_mb = NULL; } else { src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, @@ -1227,9 +1226,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) src_mb->flags |= MFC_BUF_FLAG_USED; if (src_mb->b->vb2_buf.planes[0].bytesused == 0) { /* send null frame */ - s5p_mfc_set_enc_frame_buffer_v5(ctx, - dev->dma_base[BANK2_CTX], - dev->dma_base[BANK2_CTX]); + s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, + dev->bank2); ctx->state = MFCINST_FINISHING; } else { src_y_addr = vb2_dma_contig_plane_dma_addr( diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 51053ed68741..d2bc938253bc 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -240,7 +240,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->bank1); + dev->bank1, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -292,8 +292,8 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -322,8 +322,8 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &dev->ctx_buf); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); return ret; From 5cc88afcb878a472119d1387ac0ab90867cc19c7 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:20:58 +0100 Subject: [PATCH 13/35] Revert "Internal MFC driver device structure contains two pointers to devices used for DMA memory allocation: mem_dev_l and mem_dev_r. Replace them with the mem_dev[] array and use defines for accessing particular banks. This will help to simplify code in the next patches." This reverts commit 29faddbeb34603d6e31895ae095c3589b430e532. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 31 ++++++++---------- .../media/platform/s5p-mfc/s5p_mfc_common.h | 11 ++++--- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 23 +++++++------ drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 8 ++--- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 10 +++--- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 32 ++++++++----------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 ++++----- 7 files changed, 61 insertions(+), 69 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 67a0450b0bb5..f59a2ca6c0fb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1123,8 +1123,7 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); if (ret == 0) - mfc_dev->mem_dev[BANK1_CTX] = - mfc_dev->mem_dev[BANK2_CTX] = dev; + mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev; return ret; } @@ -1132,14 +1131,14 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) * Create and initialize virtual devices for accessing * reserved memory regions. */ - mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left", - BANK1_CTX); - if (!mfc_dev->mem_dev[BANK1_CTX]) + mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left", + MFC_BANK1_ALLOC_CTX); + if (!mfc_dev->mem_dev_l) return -ENODEV; - mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right", - BANK2_CTX); - if (!mfc_dev->mem_dev[BANK2_CTX]) { - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right", + MFC_BANK2_ALLOC_CTX); + if (!mfc_dev->mem_dev_r) { + device_unregister(mfc_dev->mem_dev_l); return -ENODEV; } @@ -1155,8 +1154,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) return; } - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + device_unregister(mfc_dev->mem_dev_l); + device_unregister(mfc_dev->mem_dev_r); } /* MFC probe function */ @@ -1214,10 +1213,8 @@ static int s5p_mfc_probe(struct platform_device *pdev) goto err_dma; } - vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX], - DMA_BIT_MASK(32)); - vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX], - DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); mutex_init(&dev->mfc_mutex); init_waitqueue_head(&dev->queue); @@ -1351,8 +1348,8 @@ static int s5p_mfc_remove(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r); s5p_mfc_final_pm(dev); return 0; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index c0a77c105714..388d23dd4098 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -33,9 +33,8 @@ * while mmaping */ #define DST_QUEUE_OFF_BASE (1 << 30) -#define BANK1_CTX 0 -#define BANK2_CTX 1 -#define BANK_CTX_NUM 2 +#define MFC_BANK1_ALLOC_CTX 0 +#define MFC_BANK2_ALLOC_CTX 1 #define MFC_BANK1_ALIGN_ORDER 13 #define MFC_BANK2_ALIGN_ORDER 13 @@ -255,7 +254,8 @@ struct s5p_mfc_priv_buf { * @vfd_dec: video device for decoding * @vfd_enc: video device for encoding * @plat_dev: platform device - * @mem_dev[]: child devices of the memory banks + * @mem_dev_l: child device of the left memory bank (0) + * @mem_dev_r: child device of the right memory bank (1) * @regs_base: base address of the MFC hw registers * @irq: irq resource * @dec_ctrl_handler: control framework handler for decoding @@ -297,7 +297,8 @@ struct s5p_mfc_dev { struct video_device *vfd_dec; struct video_device *vfd_enc; struct platform_device *plat_dev; - struct device *mem_dev[BANK_CTX_NUM]; + struct device *mem_dev_l; + struct device *mem_dev_r; void __iomem *regs_base; int irq; struct v4l2_ctrl_handler dec_ctrl_handler; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index cd1406c75d9a..cc888713b3b6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -28,7 +28,6 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { void *bank2_virt; dma_addr_t bank2_dma_addr; - unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; dev->fw_size = dev->variant->buf_size->fw; @@ -37,8 +36,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) return -ENOMEM; } - dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], - dev->fw_size, &dev->bank1, GFP_KERNEL); + dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, + &dev->bank1, GFP_KERNEL); if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); @@ -46,13 +45,13 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { - bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], - align_size, &bank2_dma_addr, GFP_KERNEL); + bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, + &bank2_dma_addr, GFP_KERNEL); if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->bank1); + dma_free_coherent(dev->mem_dev_l, dev->fw_size, + dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return -ENOMEM; } @@ -61,10 +60,10 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ - dev->bank2 = bank2_dma_addr - align_size; + dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER); - dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, - bank2_virt, bank2_dma_addr); + dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, + bank2_virt, bank2_dma_addr); } else { /* In this case bank2 can point to the same address as bank1. @@ -124,8 +123,8 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) * that MFC is no longer processing */ if (!dev->fw_virt_addr) return -EINVAL; - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->bank1); + dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr, + dev->bank1); dev->fw_virt_addr = NULL; return 0; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index d470f0f7b1a0..6e5ca86fb331 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -935,14 +935,14 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_l; else - alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_r; + alloc_devs[1] = ctx->dev->mem_dev_l; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) { psize[0] = ctx->dec_src_buf_size; - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_l; } else { mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); return -EINVAL; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 5747dc453f10..7de9b6485e38 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1845,7 +1845,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, if (*buf_count > MFC_MAX_BUFFERS) *buf_count = MFC_MAX_BUFFERS; psize[0] = ctx->enc_dst_buf_size; - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_l; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->src_fmt) *plane_count = ctx->src_fmt->num_planes; @@ -1861,11 +1861,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) { - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_l; + alloc_devs[1] = ctx->dev->mem_dev_l; } else { - alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK2_CTX]; + alloc_devs[0] = ctx->dev->mem_dev_r; + alloc_devs[1] = ctx->dev->mem_dev_r; } } else { mfc_err("invalid queue type: %d\n", vq->type); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 65dd3e64b4db..f4301d5bbd32 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -41,8 +41,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -58,7 +57,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release temporary buffers for decoding */ static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->dsc); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->dsc); } /* Allocate codec buffers */ @@ -173,8 +172,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->bank1, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, + &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -183,12 +182,11 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) } /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], - dev->bank2, &ctx->bank2); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, dev->bank2, + &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], - &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); return ret; } BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); @@ -199,8 +197,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK2_CTX], &ctx->bank2); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_r, &ctx->bank2); } /* Allocate memory for instance data buffer */ @@ -216,8 +214,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -230,11 +227,10 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); - s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(dev->mem_dev_l, &ctx->ctx); return ret; } @@ -250,8 +246,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->shm); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->shm); } static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index d2bc938253bc..d6f207e859ab 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,8 +239,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->bank1, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, + &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -253,7 +253,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); } /* Allocate memory for instance data buffer */ @@ -292,8 +292,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -310,7 +309,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); } /* Allocate context buffers for SYS_INIT */ @@ -322,7 +321,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); @@ -340,7 +339,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) /* Release context buffers for SYS_INIT */ static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) { - s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &dev->ctx_buf); + s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf); } static int calc_plane(int width, int height) From c536dbe4d0d53f991ab163199dc1632f22afd422 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:21:21 +0100 Subject: [PATCH 14/35] Revert "Replace custom code with generic helper to retrieve driver data." This reverts commit 87541760bed4b9f80ce40196701adaab7593f3f3. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 17 +++++++++++++++-- drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index f59a2ca6c0fb..ce71d68fca9c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include "s5p_mfc_common.h" @@ -1158,6 +1157,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) device_unregister(mfc_dev->mem_dev_r); } +static void *mfc_get_drv_data(struct platform_device *pdev); + /* MFC probe function */ static int s5p_mfc_probe(struct platform_device *pdev) { @@ -1181,7 +1182,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) return -ENODEV; } - dev->variant = of_device_get_match_data(&pdev->dev); + dev->variant = mfc_get_drv_data(pdev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->regs_base = devm_ioremap_resource(&pdev->dev, res); @@ -1540,6 +1541,18 @@ static const struct of_device_id exynos_mfc_match[] = { }; MODULE_DEVICE_TABLE(of, exynos_mfc_match); +static void *mfc_get_drv_data(struct platform_device *pdev) +{ + struct s5p_mfc_variant *driver_data = NULL; + const struct of_device_id *match; + + match = of_match_node(exynos_mfc_match, pdev->dev.of_node); + if (match) + driver_data = (struct s5p_mfc_variant *)match->data; + + return driver_data; +} + static struct platform_driver s5p_mfc_driver = { .probe = s5p_mfc_probe, .remove = s5p_mfc_remove, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 388d23dd4098..0048eaf14445 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -192,7 +192,7 @@ struct s5p_mfc_buf { */ struct s5p_mfc_pm { struct clk *clock_gate; - const char * const *clk_names; + const char **clk_names; struct clk *clocks[MFC_MAX_CLOCKS]; int num_clocks; bool use_clock_gating; @@ -304,7 +304,7 @@ struct s5p_mfc_dev { struct v4l2_ctrl_handler dec_ctrl_handler; struct v4l2_ctrl_handler enc_ctrl_handler; struct s5p_mfc_pm pm; - const struct s5p_mfc_variant *variant; + struct s5p_mfc_variant *variant; int num_inst; spinlock_t irqlock; /* lock when operating on context */ spinlock_t condlock; /* lock when changing/checking if a context is From 7c96259b0bee0063371949f2638d41a91a0ee5c5 Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:21:39 +0100 Subject: [PATCH 15/35] Revert "Remove unused structures, definitions and functions that are no longer called from the driver code." This reverts commit f23daeb501a139710ada7b336063409a1d1e3847. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 21 +++++++++++++++++++ .../media/platform/s5p-mfc/s5p_mfc_common.h | 13 ++++++++++++ drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 + 3 files changed, 35 insertions(+) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index ce71d68fca9c..66462554eb2f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1422,11 +1422,16 @@ static struct s5p_mfc_buf_size buf_size_v5 = { .priv = &mfc_buf_size_v5, }; +static struct s5p_mfc_buf_align mfc_buf_align_v5 = { + .base = MFC_BASE_ALIGN_ORDER, +}; + static struct s5p_mfc_variant mfc_drvdata_v5 = { .version = MFC_VERSION, .version_bit = MFC_V5_BIT, .port_num = MFC_NUM_PORTS, .buf_size = &buf_size_v5, + .buf_align = &mfc_buf_align_v5, .fw_name[0] = "s5p-mfc.fw", .clk_names = {"mfc", "sclk_mfc"}, .num_clocks = 2, @@ -1447,11 +1452,16 @@ static struct s5p_mfc_buf_size buf_size_v6 = { .priv = &mfc_buf_size_v6, }; +static struct s5p_mfc_buf_align mfc_buf_align_v6 = { + .base = 0, +}; + static struct s5p_mfc_variant mfc_drvdata_v6 = { .version = MFC_VERSION_V6, .version_bit = MFC_V6_BIT, .port_num = MFC_NUM_PORTS_V6, .buf_size = &buf_size_v6, + .buf_align = &mfc_buf_align_v6, .fw_name[0] = "s5p-mfc-v6.fw", /* * v6-v2 firmware contains bug fixes and interface change @@ -1476,11 +1486,16 @@ static struct s5p_mfc_buf_size buf_size_v7 = { .priv = &mfc_buf_size_v7, }; +static struct s5p_mfc_buf_align mfc_buf_align_v7 = { + .base = 0, +}; + static struct s5p_mfc_variant mfc_drvdata_v7 = { .version = MFC_VERSION_V7, .version_bit = MFC_V7_BIT, .port_num = MFC_NUM_PORTS_V7, .buf_size = &buf_size_v7, + .buf_align = &mfc_buf_align_v7, .fw_name[0] = "s5p-mfc-v7.fw", .clk_names = {"mfc", "sclk_mfc"}, .num_clocks = 2, @@ -1500,11 +1515,16 @@ static struct s5p_mfc_buf_size buf_size_v8 = { .priv = &mfc_buf_size_v8, }; +static struct s5p_mfc_buf_align mfc_buf_align_v8 = { + .base = 0, +}; + static struct s5p_mfc_variant mfc_drvdata_v8 = { .version = MFC_VERSION_V8, .version_bit = MFC_V8_BIT, .port_num = MFC_NUM_PORTS_V8, .buf_size = &buf_size_v8, + .buf_align = &mfc_buf_align_v8, .fw_name[0] = "s5p-mfc-v8.fw", .clk_names = {"mfc"}, .num_clocks = 1, @@ -1515,6 +1535,7 @@ static struct s5p_mfc_variant mfc_drvdata_v8_5433 = { .version_bit = MFC_V8_BIT, .port_num = MFC_NUM_PORTS_V8, .buf_size = &buf_size_v8, + .buf_align = &mfc_buf_align_v8, .fw_name[0] = "s5p-mfc-v8.fw", .clk_names = {"pclk", "aclk", "aclk_xiu"}, .num_clocks = 3, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 0048eaf14445..3816a37de4bc 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -44,6 +44,14 @@ #include +static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) +{ + /* Same functionality as the vb2_dma_contig_plane_paddr */ + dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b); + + return *paddr; +} + /* MFC definitions */ #define MFC_MAX_EXTRA_DPB 5 #define MFC_MAX_BUFFERS 32 @@ -221,11 +229,16 @@ struct s5p_mfc_buf_size { void *priv; }; +struct s5p_mfc_buf_align { + unsigned int base; +}; + struct s5p_mfc_variant { unsigned int version; unsigned int port_num; u32 version_bit; struct s5p_mfc_buf_size *buf_size; + struct s5p_mfc_buf_align *buf_align; char *fw_name[MFC_FW_MAX_VERSIONS]; const char *clk_names[MFC_MAX_CLOCKS]; int num_clocks; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index 45c807bf19cc..8e5df041edf7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h @@ -18,6 +18,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev); +int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev); From 477e0bd905406ed969ea3b81e5c171f7a6a617fd Mon Sep 17 00:00:00 2001 From: Ard van Breemen Date: Wed, 22 Mar 2017 16:22:13 +0100 Subject: [PATCH 16/35] Revert "media: s5p-mfc: Fix initialization of internal structures" This reverts commit 03d3abd16379f54bb800233b18fbd6787a528874. --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 66462554eb2f..44546286a04b 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -764,7 +764,6 @@ static int s5p_mfc_open(struct file *file) ret = -ENOMEM; goto err_alloc; } - init_waitqueue_head(&ctx->queue); v4l2_fh_init(&ctx->fh, vdev); file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); @@ -900,6 +899,7 @@ static int s5p_mfc_open(struct file *file) mfc_err("Failed to initialize videobuf2 queue(output)\n"); goto err_queue_init; } + init_waitqueue_head(&ctx->queue); mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; @@ -1218,13 +1218,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); mutex_init(&dev->mfc_mutex); - init_waitqueue_head(&dev->queue); - dev->hw_lock = 0; - INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker); - atomic_set(&dev->watchdog_cnt, 0); - init_timer(&dev->watchdog_timer); - dev->watchdog_timer.data = (unsigned long)dev; - dev->watchdog_timer.function = s5p_mfc_watchdog; ret = s5p_mfc_alloc_firmware(dev); if (ret) @@ -1233,6 +1226,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_v4l2_dev_reg; + init_waitqueue_head(&dev->queue); /* decoder */ vfd = video_device_alloc(); @@ -1269,6 +1263,13 @@ static int s5p_mfc_probe(struct platform_device *pdev) video_set_drvdata(vfd, dev); platform_set_drvdata(pdev, dev); + dev->hw_lock = 0; + INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker); + atomic_set(&dev->watchdog_cnt, 0); + init_timer(&dev->watchdog_timer); + dev->watchdog_timer.data = (unsigned long)dev; + dev->watchdog_timer.function = s5p_mfc_watchdog; + /* Initialize HW ops and commands based on MFC version */ s5p_mfc_init_hw_ops(dev); s5p_mfc_init_hw_cmds(dev); From 10b8acb88f7c9ac158a918ea268ba5860fedc813 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 3 Feb 2017 15:05:18 +0100 Subject: [PATCH 17/35] media: s5p-mfc: Fix initialization of internal structures Initialize members of the internal device and context structures as early as possible to avoid access to uninitialized objects on initialization failures. If loading firmware or creating of the hardware instance fails, driver will access device or context queue in error handling path, which might not be initialized yet, what causes kernel panic. Fix this by moving initialization of all static members as early as possible. Signed-off-by: Marek Szyprowski Acked-by: Andrzej Hajda Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 44546286a04b..66462554eb2f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -764,6 +764,7 @@ static int s5p_mfc_open(struct file *file) ret = -ENOMEM; goto err_alloc; } + init_waitqueue_head(&ctx->queue); v4l2_fh_init(&ctx->fh, vdev); file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); @@ -899,7 +900,6 @@ static int s5p_mfc_open(struct file *file) mfc_err("Failed to initialize videobuf2 queue(output)\n"); goto err_queue_init; } - init_waitqueue_head(&ctx->queue); mutex_unlock(&dev->mfc_mutex); mfc_debug_leave(); return ret; @@ -1218,6 +1218,13 @@ static int s5p_mfc_probe(struct platform_device *pdev) vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); mutex_init(&dev->mfc_mutex); + init_waitqueue_head(&dev->queue); + dev->hw_lock = 0; + INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker); + atomic_set(&dev->watchdog_cnt, 0); + init_timer(&dev->watchdog_timer); + dev->watchdog_timer.data = (unsigned long)dev; + dev->watchdog_timer.function = s5p_mfc_watchdog; ret = s5p_mfc_alloc_firmware(dev); if (ret) @@ -1226,7 +1233,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_v4l2_dev_reg; - init_waitqueue_head(&dev->queue); /* decoder */ vfd = video_device_alloc(); @@ -1263,13 +1269,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) video_set_drvdata(vfd, dev); platform_set_drvdata(pdev, dev); - dev->hw_lock = 0; - INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker); - atomic_set(&dev->watchdog_cnt, 0); - init_timer(&dev->watchdog_timer); - dev->watchdog_timer.data = (unsigned long)dev; - dev->watchdog_timer.function = s5p_mfc_watchdog; - /* Initialize HW ops and commands based on MFC version */ s5p_mfc_init_hw_ops(dev); s5p_mfc_init_hw_cmds(dev); From 7326933ab3b3f49cbb6f0244753ff05a564c2f11 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:27 +0100 Subject: [PATCH 18/35] media: s5p-mfc: Remove unused structures and dead code Remove unused structures, definitions and functions that are no longer called from the driver code. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Reviewed-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 21 ------------------- .../media/platform/s5p-mfc/s5p_mfc_common.h | 13 ------------ drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h | 1 - 3 files changed, 35 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 66462554eb2f..ce71d68fca9c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1422,16 +1422,11 @@ static struct s5p_mfc_buf_size buf_size_v5 = { .priv = &mfc_buf_size_v5, }; -static struct s5p_mfc_buf_align mfc_buf_align_v5 = { - .base = MFC_BASE_ALIGN_ORDER, -}; - static struct s5p_mfc_variant mfc_drvdata_v5 = { .version = MFC_VERSION, .version_bit = MFC_V5_BIT, .port_num = MFC_NUM_PORTS, .buf_size = &buf_size_v5, - .buf_align = &mfc_buf_align_v5, .fw_name[0] = "s5p-mfc.fw", .clk_names = {"mfc", "sclk_mfc"}, .num_clocks = 2, @@ -1452,16 +1447,11 @@ static struct s5p_mfc_buf_size buf_size_v6 = { .priv = &mfc_buf_size_v6, }; -static struct s5p_mfc_buf_align mfc_buf_align_v6 = { - .base = 0, -}; - static struct s5p_mfc_variant mfc_drvdata_v6 = { .version = MFC_VERSION_V6, .version_bit = MFC_V6_BIT, .port_num = MFC_NUM_PORTS_V6, .buf_size = &buf_size_v6, - .buf_align = &mfc_buf_align_v6, .fw_name[0] = "s5p-mfc-v6.fw", /* * v6-v2 firmware contains bug fixes and interface change @@ -1486,16 +1476,11 @@ static struct s5p_mfc_buf_size buf_size_v7 = { .priv = &mfc_buf_size_v7, }; -static struct s5p_mfc_buf_align mfc_buf_align_v7 = { - .base = 0, -}; - static struct s5p_mfc_variant mfc_drvdata_v7 = { .version = MFC_VERSION_V7, .version_bit = MFC_V7_BIT, .port_num = MFC_NUM_PORTS_V7, .buf_size = &buf_size_v7, - .buf_align = &mfc_buf_align_v7, .fw_name[0] = "s5p-mfc-v7.fw", .clk_names = {"mfc", "sclk_mfc"}, .num_clocks = 2, @@ -1515,16 +1500,11 @@ static struct s5p_mfc_buf_size buf_size_v8 = { .priv = &mfc_buf_size_v8, }; -static struct s5p_mfc_buf_align mfc_buf_align_v8 = { - .base = 0, -}; - static struct s5p_mfc_variant mfc_drvdata_v8 = { .version = MFC_VERSION_V8, .version_bit = MFC_V8_BIT, .port_num = MFC_NUM_PORTS_V8, .buf_size = &buf_size_v8, - .buf_align = &mfc_buf_align_v8, .fw_name[0] = "s5p-mfc-v8.fw", .clk_names = {"mfc"}, .num_clocks = 1, @@ -1535,7 +1515,6 @@ static struct s5p_mfc_variant mfc_drvdata_v8_5433 = { .version_bit = MFC_V8_BIT, .port_num = MFC_NUM_PORTS_V8, .buf_size = &buf_size_v8, - .buf_align = &mfc_buf_align_v8, .fw_name[0] = "s5p-mfc-v8.fw", .clk_names = {"pclk", "aclk", "aclk_xiu"}, .num_clocks = 3, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 3816a37de4bc..0048eaf14445 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -44,14 +44,6 @@ #include -static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b) -{ - /* Same functionality as the vb2_dma_contig_plane_paddr */ - dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b); - - return *paddr; -} - /* MFC definitions */ #define MFC_MAX_EXTRA_DPB 5 #define MFC_MAX_BUFFERS 32 @@ -229,16 +221,11 @@ struct s5p_mfc_buf_size { void *priv; }; -struct s5p_mfc_buf_align { - unsigned int base; -}; - struct s5p_mfc_variant { unsigned int version; unsigned int port_num; u32 version_bit; struct s5p_mfc_buf_size *buf_size; - struct s5p_mfc_buf_align *buf_align; char *fw_name[MFC_FW_MAX_VERSIONS]; const char *clk_names[MFC_MAX_CLOCKS]; int num_clocks; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h index 8e5df041edf7..45c807bf19cc 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h @@ -18,7 +18,6 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev); -int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev); int s5p_mfc_init_hw(struct s5p_mfc_dev *dev); void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev); From d02ff86d28b0637a3753951f2f3a45334173dba6 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:28 +0100 Subject: [PATCH 19/35] media: s5p-mfc: Use generic of_device_get_match_data helper Replace custom code with generic helper to retrieve driver data. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Reviewed-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 17 ++--------------- drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 4 ++-- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index ce71d68fca9c..f59a2ca6c0fb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "s5p_mfc_common.h" @@ -1157,8 +1158,6 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) device_unregister(mfc_dev->mem_dev_r); } -static void *mfc_get_drv_data(struct platform_device *pdev); - /* MFC probe function */ static int s5p_mfc_probe(struct platform_device *pdev) { @@ -1182,7 +1181,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) return -ENODEV; } - dev->variant = mfc_get_drv_data(pdev); + dev->variant = of_device_get_match_data(&pdev->dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->regs_base = devm_ioremap_resource(&pdev->dev, res); @@ -1541,18 +1540,6 @@ static const struct of_device_id exynos_mfc_match[] = { }; MODULE_DEVICE_TABLE(of, exynos_mfc_match); -static void *mfc_get_drv_data(struct platform_device *pdev) -{ - struct s5p_mfc_variant *driver_data = NULL; - const struct of_device_id *match; - - match = of_match_node(exynos_mfc_match, pdev->dev.of_node); - if (match) - driver_data = (struct s5p_mfc_variant *)match->data; - - return driver_data; -} - static struct platform_driver s5p_mfc_driver = { .probe = s5p_mfc_probe, .remove = s5p_mfc_remove, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 0048eaf14445..388d23dd4098 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -192,7 +192,7 @@ struct s5p_mfc_buf { */ struct s5p_mfc_pm { struct clk *clock_gate; - const char **clk_names; + const char * const *clk_names; struct clk *clocks[MFC_MAX_CLOCKS]; int num_clocks; bool use_clock_gating; @@ -304,7 +304,7 @@ struct s5p_mfc_dev { struct v4l2_ctrl_handler dec_ctrl_handler; struct v4l2_ctrl_handler enc_ctrl_handler; struct s5p_mfc_pm pm; - struct s5p_mfc_variant *variant; + const struct s5p_mfc_variant *variant; int num_inst; spinlock_t irqlock; /* lock when operating on context */ spinlock_t condlock; /* lock when changing/checking if a context is From f8e4274e475ae1f385239d20955c9bd287a79cd9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:29 +0100 Subject: [PATCH 20/35] media: s5p-mfc: Replace mem_dev_* entries with an array Internal MFC driver device structure contains two pointers to devices used for DMA memory allocation: mem_dev_l and mem_dev_r. Replace them with the mem_dev[] array and use defines for accessing particular banks. This will help to simplify code in the next patches. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 31 ++++++++++-------- .../media/platform/s5p-mfc/s5p_mfc_common.h | 11 +++---- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 23 ++++++------- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 8 ++--- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 10 +++--- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 32 +++++++++++-------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 +++++---- 7 files changed, 69 insertions(+), 61 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index f59a2ca6c0fb..67a0450b0bb5 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1123,7 +1123,8 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); if (ret == 0) - mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev; + mfc_dev->mem_dev[BANK1_CTX] = + mfc_dev->mem_dev[BANK2_CTX] = dev; return ret; } @@ -1131,14 +1132,14 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) * Create and initialize virtual devices for accessing * reserved memory regions. */ - mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left", - MFC_BANK1_ALLOC_CTX); - if (!mfc_dev->mem_dev_l) + mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left", + BANK1_CTX); + if (!mfc_dev->mem_dev[BANK1_CTX]) return -ENODEV; - mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right", - MFC_BANK2_ALLOC_CTX); - if (!mfc_dev->mem_dev_r) { - device_unregister(mfc_dev->mem_dev_l); + mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right", + BANK2_CTX); + if (!mfc_dev->mem_dev[BANK2_CTX]) { + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); return -ENODEV; } @@ -1154,8 +1155,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) return; } - device_unregister(mfc_dev->mem_dev_l); - device_unregister(mfc_dev->mem_dev_r); + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + device_unregister(mfc_dev->mem_dev[BANK2_CTX]); } /* MFC probe function */ @@ -1213,8 +1214,10 @@ static int s5p_mfc_probe(struct platform_device *pdev) goto err_dma; } - vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32)); - vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX], + DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX], + DMA_BIT_MASK(32)); mutex_init(&dev->mfc_mutex); init_waitqueue_head(&dev->queue); @@ -1348,8 +1351,8 @@ static int s5p_mfc_remove(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]); + vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]); s5p_mfc_final_pm(dev); return 0; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 388d23dd4098..c0a77c105714 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -33,8 +33,9 @@ * while mmaping */ #define DST_QUEUE_OFF_BASE (1 << 30) -#define MFC_BANK1_ALLOC_CTX 0 -#define MFC_BANK2_ALLOC_CTX 1 +#define BANK1_CTX 0 +#define BANK2_CTX 1 +#define BANK_CTX_NUM 2 #define MFC_BANK1_ALIGN_ORDER 13 #define MFC_BANK2_ALIGN_ORDER 13 @@ -254,8 +255,7 @@ struct s5p_mfc_priv_buf { * @vfd_dec: video device for decoding * @vfd_enc: video device for encoding * @plat_dev: platform device - * @mem_dev_l: child device of the left memory bank (0) - * @mem_dev_r: child device of the right memory bank (1) + * @mem_dev[]: child devices of the memory banks * @regs_base: base address of the MFC hw registers * @irq: irq resource * @dec_ctrl_handler: control framework handler for decoding @@ -297,8 +297,7 @@ struct s5p_mfc_dev { struct video_device *vfd_dec; struct video_device *vfd_enc; struct platform_device *plat_dev; - struct device *mem_dev_l; - struct device *mem_dev_r; + struct device *mem_dev[BANK_CTX_NUM]; void __iomem *regs_base; int irq; struct v4l2_ctrl_handler dec_ctrl_handler; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index cc888713b3b6..cd1406c75d9a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -28,6 +28,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { void *bank2_virt; dma_addr_t bank2_dma_addr; + unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; dev->fw_size = dev->variant->buf_size->fw; @@ -36,8 +37,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) return -ENOMEM; } - dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, - &dev->bank1, GFP_KERNEL); + dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], + dev->fw_size, &dev->bank1, GFP_KERNEL); if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); @@ -45,13 +46,13 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { - bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, - &bank2_dma_addr, GFP_KERNEL); + bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], + align_size, &bank2_dma_addr, GFP_KERNEL); if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); - dma_free_coherent(dev->mem_dev_l, dev->fw_size, - dev->fw_virt_addr, dev->bank1); + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, + dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return -ENOMEM; } @@ -60,10 +61,10 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ - dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER); + dev->bank2 = bank2_dma_addr - align_size; - dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, - bank2_virt, bank2_dma_addr); + dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, + bank2_virt, bank2_dma_addr); } else { /* In this case bank2 can point to the same address as bank1. @@ -123,8 +124,8 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) * that MFC is no longer processing */ if (!dev->fw_virt_addr) return -EINVAL; - dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr, - dev->bank1); + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, + dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return 0; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6e5ca86fb331..d470f0f7b1a0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -935,14 +935,14 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) - alloc_devs[0] = ctx->dev->mem_dev_l; + alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; else - alloc_devs[0] = ctx->dev->mem_dev_r; - alloc_devs[1] = ctx->dev->mem_dev_l; + alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) { psize[0] = ctx->dec_src_buf_size; - alloc_devs[0] = ctx->dev->mem_dev_l; + alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; } else { mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); return -EINVAL; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 7de9b6485e38..5747dc453f10 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1845,7 +1845,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, if (*buf_count > MFC_MAX_BUFFERS) *buf_count = MFC_MAX_BUFFERS; psize[0] = ctx->enc_dst_buf_size; - alloc_devs[0] = ctx->dev->mem_dev_l; + alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->src_fmt) *plane_count = ctx->src_fmt->num_planes; @@ -1861,11 +1861,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) { - alloc_devs[0] = ctx->dev->mem_dev_l; - alloc_devs[1] = ctx->dev->mem_dev_l; + alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; } else { - alloc_devs[0] = ctx->dev->mem_dev_r; - alloc_devs[1] = ctx->dev->mem_dev_r; + alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK2_CTX]; } } else { mfc_err("invalid queue type: %d\n", vq->type); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index f4301d5bbd32..65dd3e64b4db 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -41,7 +41,8 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -57,7 +58,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release temporary buffers for decoding */ static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->dsc); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->dsc); } /* Allocate codec buffers */ @@ -172,8 +173,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, - &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->bank1, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -182,11 +183,12 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) } /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, dev->bank2, - &ctx->bank2); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], + dev->bank2, &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], + &ctx->bank1); return ret; } BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); @@ -197,8 +199,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_r, &ctx->bank2); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK2_CTX], &ctx->bank2); } /* Allocate memory for instance data buffer */ @@ -214,7 +216,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -227,10 +230,11 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); - s5p_mfc_release_priv_buf(dev->mem_dev_l, &ctx->ctx); + s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); return ret; } @@ -246,8 +250,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->shm); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->shm); } static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index d6f207e859ab..d2bc938253bc 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,8 +239,8 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, - &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->bank1, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -253,7 +253,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); } /* Allocate memory for instance data buffer */ @@ -292,7 +292,8 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, + &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -309,7 +310,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); } /* Allocate context buffers for SYS_INIT */ @@ -321,7 +322,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_l, dev->bank1, + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); @@ -339,7 +340,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) /* Release context buffers for SYS_INIT */ static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) { - s5p_mfc_release_priv_buf(dev->mem_dev_l, &dev->ctx_buf); + s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &dev->ctx_buf); } static int calc_plane(int width, int height) From 62d3e1dd336e5cbfafa703a1c38e8bb70ec47bf2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:30 +0100 Subject: [PATCH 21/35] media: s5p-mfc: Replace bank1/bank2 entries with an array Internal MFC driver device structure contains two entries for keeping addresses of the DMA memory banks. Replace them with the dma_base[] array and use defines for accessing particular banks. This will help to simplify code in the next patches. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- .../media/platform/s5p-mfc/s5p_mfc_common.h | 6 +-- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 27 +++++++------ .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 38 ++++++++++--------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 10 ++--- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index c0a77c105714..d8b1e2bcfc6a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -273,8 +273,7 @@ struct s5p_mfc_priv_buf { * @queue: waitqueue for waiting for completion of device commands * @fw_size: size of firmware * @fw_virt_addr: virtual firmware address - * @bank1: address of the beginning of bank 1 memory - * @bank2: address of the beginning of bank 2 memory + * @dma_base[]: address of the beginning of memory banks * @hw_lock: used for hardware locking * @ctx: array of driver contexts * @curr_ctx: number of the currently running context @@ -315,8 +314,7 @@ struct s5p_mfc_dev { wait_queue_head_t queue; size_t fw_size; void *fw_virt_addr; - dma_addr_t bank1; - dma_addr_t bank2; + dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; int curr_ctx; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index cd1406c75d9a..c9bff3d0655f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -38,8 +38,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) } dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], - dev->fw_size, &dev->bank1, GFP_KERNEL); - + dev->fw_size, &dev->dma_base[BANK1_CTX], + GFP_KERNEL); if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; @@ -52,7 +52,8 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->bank1); + dev->fw_virt_addr, + dev->dma_base[BANK1_CTX]); dev->fw_virt_addr = NULL; return -ENOMEM; } @@ -61,7 +62,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ - dev->bank2 = bank2_dma_addr - align_size; + dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, bank2_virt, bank2_dma_addr); @@ -70,7 +71,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) /* In this case bank2 can point to the same address as bank1. * Firmware will always occupy the beginning of this area so it is * impossible having a video frame buffer with zero address. */ - dev->bank2 = dev->bank1; + dev->dma_base[BANK2_CTX] = dev->dma_base[BANK1_CTX]; } return 0; } @@ -125,7 +126,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) if (!dev->fw_virt_addr) return -EINVAL; dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->bank1); + dev->fw_virt_addr, dev->dma_base[BANK1_CTX]); dev->fw_virt_addr = NULL; return 0; } @@ -211,13 +212,17 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) { if (IS_MFCV6_PLUS(dev)) { - mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS_V6); - mfc_debug(2, "Base Address : %pad\n", &dev->bank1); + mfc_write(dev, dev->dma_base[BANK1_CTX], + S5P_FIMV_RISC_BASE_ADDRESS_V6); + mfc_debug(2, "Base Address : %pad\n", + &dev->dma_base[BANK1_CTX]); } else { - mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A); - mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B); + mfc_write(dev, dev->dma_base[BANK1_CTX], + S5P_FIMV_MC_DRAMBASE_ADR_A); + mfc_write(dev, dev->dma_base[BANK2_CTX], + S5P_FIMV_MC_DRAMBASE_ADR_B); mfc_debug(2, "Bank1: %pad, Bank2: %pad\n", - &dev->bank1, &dev->bank2); + &dev->dma_base[BANK1_CTX], &dev->dma_base[BANK2_CTX]); } } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 65dd3e64b4db..32ce9ade2edb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -30,8 +30,8 @@ #include #include -#define OFFSETA(x) (((x) - dev->bank1) >> MFC_OFFSET_SHIFT) -#define OFFSETB(x) (((x) - dev->bank2) >> MFC_OFFSET_SHIFT) +#define OFFSETA(x) (((x) - dev->dma_base[BANK1_CTX]) >> MFC_OFFSET_SHIFT) +#define OFFSETB(x) (((x) - dev->dma_base[BANK2_CTX]) >> MFC_OFFSET_SHIFT) /* Allocate temporary buffers for decoding */ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) @@ -41,8 +41,8 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -174,7 +174,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) if (ctx->bank1.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->bank1, &ctx->bank1); + dev->dma_base[BANK1_CTX], &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -184,7 +184,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], - dev->bank2, &ctx->bank2); + dev->dma_base[BANK2_CTX], &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], @@ -216,8 +216,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -230,8 +230,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); @@ -239,7 +239,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) } /* shared memory offset only keeps the offset from base (port a) */ - ctx->shm.ofs = ctx->shm.dma - dev->bank1; + ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK1_CTX]; BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); memset(ctx->shm.virt, 0, buf_size->shm); @@ -538,10 +538,10 @@ static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev = ctx->dev; - *y_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) - << MFC_OFFSET_SHIFT); - *c_addr = dev->bank2 + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) - << MFC_OFFSET_SHIFT); + *y_addr = dev->dma_base[BANK2_CTX] + + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT); + *c_addr = dev->dma_base[BANK2_CTX] + + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT); } /* Set encoding ref & codec buffer */ @@ -1218,7 +1218,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) } if (list_empty(&ctx->src_queue)) { /* send null frame */ - s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, dev->bank2); + s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK2_CTX], + dev->dma_base[BANK2_CTX]); src_mb = NULL; } else { src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, @@ -1226,8 +1227,9 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) src_mb->flags |= MFC_BUF_FLAG_USED; if (src_mb->b->vb2_buf.planes[0].bytesused == 0) { /* send null frame */ - s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->bank2, - dev->bank2); + s5p_mfc_set_enc_frame_buffer_v5(ctx, + dev->dma_base[BANK2_CTX], + dev->dma_base[BANK2_CTX]); ctx->state = MFCINST_FINISHING; } else { src_y_addr = vb2_dma_contig_plane_dma_addr( diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index d2bc938253bc..51053ed68741 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -240,7 +240,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->bank1, &ctx->bank1); + dev->dma_base[BANK1_CTX], &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -292,8 +292,8 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -322,8 +322,8 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], dev->bank1, - &dev->ctx_buf); + ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], + dev->dma_base[BANK1_CTX], &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); return ret; From 36bde237ff0a173ca455912f2eef7765b01221ce Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:31 +0100 Subject: [PATCH 22/35] media: s5p-mfc: Simplify alloc/release private buffer functions Change parameters for s5p_mfc_alloc_priv_buf() and s5p_mfc_release_priv_buf() functions. Instead of DMA device pointer and a base, provide common MFC device structure and memory bank context identifier. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- .../media/platform/s5p-mfc/s5p_mfc_common.h | 2 ++ drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 20 ++++++++----- drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 8 ++--- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 30 ++++++++----------- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 15 ++++------ 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index d8b1e2bcfc6a..be011700cb12 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -240,12 +240,14 @@ struct s5p_mfc_variant { * buffer accessed by driver * @dma: DMA address, only valid when kernel DMA API used * @size: size of the buffer + * @ctx: memory context (bank) used for this allocation */ struct s5p_mfc_priv_buf { unsigned long ofs; void *virt; dma_addr_t dma; size_t size; + unsigned int ctx; }; /** diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 99f65a92a6be..9294ee124661 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -37,12 +37,16 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev); } -int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, - struct s5p_mfc_priv_buf *b) +int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, + struct s5p_mfc_priv_buf *b) { + struct device *mem_dev = dev->mem_dev[mem_ctx]; + dma_addr_t base = dev->dma_base[mem_ctx]; + mfc_debug(3, "Allocating priv: %zu\n", b->size); - b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL); + b->ctx = mem_ctx; + b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); if (!b->virt) { mfc_err("Allocating private buffer of size %zu failed\n", @@ -53,7 +57,7 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, if (b->dma < base) { mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", &b->dma, &base); - dma_free_coherent(dev, b->size, b->virt, b->dma); + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); return -ENOMEM; } @@ -61,11 +65,13 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, return 0; } -void s5p_mfc_release_priv_buf(struct device *dev, - struct s5p_mfc_priv_buf *b) +void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, + struct s5p_mfc_priv_buf *b) { + struct device *mem_dev = dev->mem_dev[b->ctx]; + if (b->virt) { - dma_free_coherent(dev, b->size, b->virt, b->dma); + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); b->virt = NULL; b->dma = 0; b->size = 0; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index b6ac417ab63e..108e59382e0c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -315,10 +315,10 @@ struct s5p_mfc_hw_ops { void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev); void s5p_mfc_init_regs(struct s5p_mfc_dev *dev); -int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base, - struct s5p_mfc_priv_buf *b); -void s5p_mfc_release_priv_buf(struct device *dev, - struct s5p_mfc_priv_buf *b); +int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, + struct s5p_mfc_priv_buf *b); +void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, + struct s5p_mfc_priv_buf *b); #endif /* S5P_MFC_OPR_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 32ce9ade2edb..20e8a1bdc984 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -41,8 +41,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -58,7 +57,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release temporary buffers for decoding */ static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->dsc); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc); } /* Allocate codec buffers */ @@ -173,8 +172,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -183,12 +181,10 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) } /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK2_CTX], - dev->dma_base[BANK2_CTX], &ctx->bank2); + ret = s5p_mfc_alloc_priv_buf(dev, BANK2_CTX, &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], - &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); return ret; } BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1)); @@ -199,8 +195,8 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK2_CTX], &ctx->bank2); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2); } /* Allocate memory for instance data buffer */ @@ -216,8 +212,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -230,11 +225,10 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); - s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(dev, &ctx->ctx); return ret; } @@ -250,8 +244,8 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->shm); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm); } static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 51053ed68741..4e5ead236455 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,8 +239,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -253,7 +252,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->bank1); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); } /* Allocate memory for instance data buffer */ @@ -292,8 +291,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -310,7 +308,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) /* Release instance buffer */ static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev->mem_dev[BANK1_CTX], &ctx->ctx); + s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx); } /* Allocate context buffers for SYS_INIT */ @@ -322,8 +320,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev->mem_dev[BANK1_CTX], - dev->dma_base[BANK1_CTX], &dev->ctx_buf); + ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); return ret; @@ -340,7 +337,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) /* Release context buffers for SYS_INIT */ static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev) { - s5p_mfc_release_priv_buf(dev->mem_dev[BANK1_CTX], &dev->ctx_buf); + s5p_mfc_release_priv_buf(dev, &dev->ctx_buf); } static int calc_plane(int width, int height) From 17cbc9330d2fcb25818fcffb1a55f15b1ab8d210 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:32 +0100 Subject: [PATCH 23/35] media: s5p-mfc: Move setting DMA max segment size to DMA configure function Setting DMA max segment size to 32 bit mask is a part of DMA memory configuration, so move those calls to s5p_mfc_configure_dma_memory() function. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 67a0450b0bb5..c24c380222a7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1122,9 +1122,13 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); - if (ret == 0) + if (ret == 0) { mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; + vb2_dma_contig_set_max_seg_size(dev, + DMA_BIT_MASK(32)); + } + return ret; } @@ -1143,6 +1147,11 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return -ENODEV; } + vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX], + DMA_BIT_MASK(32)); + vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX], + DMA_BIT_MASK(32)); + return 0; } @@ -1152,11 +1161,14 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { exynos_unconfigure_iommu(dev); + vb2_dma_contig_clear_max_seg_size(dev); return; } device_unregister(mfc_dev->mem_dev[BANK1_CTX]); device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); } /* MFC probe function */ @@ -1214,11 +1226,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) goto err_dma; } - vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK1_CTX], - DMA_BIT_MASK(32)); - vb2_dma_contig_set_max_seg_size(dev->mem_dev[BANK2_CTX], - DMA_BIT_MASK(32)); - mutex_init(&dev->mfc_mutex); init_waitqueue_head(&dev->queue); dev->hw_lock = 0; @@ -1351,8 +1358,6 @@ static int s5p_mfc_remove(struct platform_device *pdev) v4l2_device_unregister(&dev->v4l2_dev); s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(dev->mem_dev[BANK2_CTX]); s5p_mfc_final_pm(dev); return 0; From 9e90e7ba71565fce1b53b997f47785189e5a3e98 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:33 +0100 Subject: [PATCH 24/35] media: s5p-mfc: Put firmware to private buffer structure Use s5p_mfc_priv_buf structure for keeping the firmware image. This will help handling of firmware buffer allocation in the next patches. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- .../media/platform/s5p-mfc/s5p_mfc_cmd_v5.c | 2 +- .../media/platform/s5p-mfc/s5p_mfc_common.h | 3 +- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 36 +++++++++---------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c index 8c4739ca16d6..4c80bb4243be 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c @@ -47,7 +47,7 @@ static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev) struct s5p_mfc_cmd_args h2r_args; memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args)); - h2r_args.arg[0] = dev->fw_size; + h2r_args.arg[0] = dev->fw_buf.size; return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index be011700cb12..e38a8eec15f9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -314,8 +314,7 @@ struct s5p_mfc_dev { int int_type; unsigned int int_err; wait_queue_head_t queue; - size_t fw_size; - void *fw_virt_addr; + struct s5p_mfc_priv_buf fw_buf; dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index c9bff3d0655f..50d698968049 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -29,21 +29,22 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) void *bank2_virt; dma_addr_t bank2_dma_addr; unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; + struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; - dev->fw_size = dev->variant->buf_size->fw; + fw_buf->size = dev->variant->buf_size->fw; - if (dev->fw_virt_addr) { + if (fw_buf->virt) { mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); return -ENOMEM; } - dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], - dev->fw_size, &dev->dma_base[BANK1_CTX], - GFP_KERNEL); - if (!dev->fw_virt_addr) { + fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, + &fw_buf->dma, GFP_KERNEL); + if (!fw_buf->virt) { mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; } + dev->dma_base[BANK1_CTX] = fw_buf->dma; if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], @@ -51,10 +52,9 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, - dev->dma_base[BANK1_CTX]); - dev->fw_virt_addr = NULL; + dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, + fw_buf->virt, fw_buf->dma); + fw_buf->virt = NULL; return -ENOMEM; } @@ -101,17 +101,17 @@ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); return -EINVAL; } - if (fw_blob->size > dev->fw_size) { + if (fw_blob->size > dev->fw_buf.size) { mfc_err("MFC firmware is too big to be loaded\n"); release_firmware(fw_blob); return -ENOMEM; } - if (!dev->fw_virt_addr) { + if (!dev->fw_buf.virt) { mfc_err("MFC firmware is not allocated\n"); release_firmware(fw_blob); return -EINVAL; } - memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size); + memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size); wmb(); release_firmware(fw_blob); mfc_debug_leave(); @@ -123,11 +123,11 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) { /* Before calling this function one has to make sure * that MFC is no longer processing */ - if (!dev->fw_virt_addr) + if (!dev->fw_buf.virt) return -EINVAL; - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_size, - dev->fw_virt_addr, dev->dma_base[BANK1_CTX]); - dev->fw_virt_addr = NULL; + dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_buf.size, + dev->fw_buf.virt, dev->fw_buf.dma); + dev->fw_buf.virt = NULL; return 0; } @@ -246,7 +246,7 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) int ret; mfc_debug_enter(); - if (!dev->fw_virt_addr) { + if (!dev->fw_buf.virt) { mfc_err("Firmware memory is not allocated.\n"); return -EINVAL; } From 9abf75a826291cbeff732f45b792fc21cdf2d4bf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:34 +0100 Subject: [PATCH 25/35] media: s5p-mfc: Move firmware allocation to DMA configure function To complete DMA memory configuration for MFC device, allocation of the firmware buffer is needed, because some parameters are dependant on its base address. Till now, this has been handled in the s5p_mfc_alloc_firmware() function. This patch moves that logic to s5p_mfc_configure_dma_memory() to keep DMA memory related operations in a single place. This way s5p_mfc_alloc_firmware() is simplified and does what it name says. The other consequence of this change is moving s5p_mfc_alloc_firmware() call from the s5p_mfc_probe() function to the s5p_mfc_configure_dma_memory(). Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 62 +++++++++++++++---- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 31 ---------- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index c24c380222a7..c56ceb812de0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1110,6 +1110,11 @@ static struct device *s5p_mfc_alloc_memdev(struct device *dev, static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; + void *bank2_virt; + dma_addr_t bank2_dma_addr; + unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER; + struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf; + int ret; /* * When IOMMU is available, we cannot use the default configuration, @@ -1122,14 +1127,21 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) if (exynos_is_iommu_available(dev)) { int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, S5P_MFC_IOMMU_DMA_SIZE); - if (ret == 0) { - mfc_dev->mem_dev[BANK1_CTX] = - mfc_dev->mem_dev[BANK2_CTX] = dev; - vb2_dma_contig_set_max_seg_size(dev, - DMA_BIT_MASK(32)); + if (ret) + return ret; + + mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; + ret = s5p_mfc_alloc_firmware(mfc_dev); + if (ret) { + exynos_unconfigure_iommu(dev); + return ret; } - return ret; + mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; + mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma; + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + return 0; } /* @@ -1147,6 +1159,35 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return -ENODEV; } + /* Allocate memory for firmware and initialize both banks addresses */ + ret = s5p_mfc_alloc_firmware(mfc_dev); + if (ret) { + device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + return ret; + } + + mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; + + bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, + &bank2_dma_addr, GFP_KERNEL); + if (!bank2_virt) { + mfc_err("Allocating bank2 base failed\n"); + s5p_mfc_release_firmware(mfc_dev); + device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + return -ENOMEM; + } + + /* Valid buffers passed to MFC encoder with LAST_FRAME command + * should not have address of bank2 - MFC will treat it as a null frame. + * To avoid such situation we set bank2 address below the pool address. + */ + mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; + + dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt, + bank2_dma_addr); + vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX], DMA_BIT_MASK(32)); vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX], @@ -1159,6 +1200,8 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; + s5p_mfc_release_firmware(mfc_dev); + if (exynos_is_iommu_available(dev)) { exynos_unconfigure_iommu(dev); vb2_dma_contig_clear_max_seg_size(dev); @@ -1235,10 +1278,6 @@ static int s5p_mfc_probe(struct platform_device *pdev) dev->watchdog_timer.data = (unsigned long)dev; dev->watchdog_timer.function = s5p_mfc_watchdog; - ret = s5p_mfc_alloc_firmware(dev); - if (ret) - goto err_res; - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) goto err_v4l2_dev_reg; @@ -1313,8 +1352,6 @@ err_enc_alloc: err_dec_alloc: v4l2_device_unregister(&dev->v4l2_dev); err_v4l2_dev_reg: - s5p_mfc_release_firmware(dev); -err_res: s5p_mfc_final_pm(dev); err_dma: s5p_mfc_unconfigure_dma_memory(dev); @@ -1356,7 +1393,6 @@ static int s5p_mfc_remove(struct platform_device *pdev) video_device_release(dev->vfd_enc); video_device_release(dev->vfd_dec); v4l2_device_unregister(&dev->v4l2_dev); - s5p_mfc_release_firmware(dev); s5p_mfc_unconfigure_dma_memory(dev); s5p_mfc_final_pm(dev); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index 50d698968049..b0cf3970117a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -26,9 +26,6 @@ /* Allocate memory for firmware */ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { - void *bank2_virt; - dma_addr_t bank2_dma_addr; - unsigned int align_size = 1 << MFC_BASE_ALIGN_ORDER; struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; fw_buf->size = dev->variant->buf_size->fw; @@ -44,35 +41,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; } - dev->dma_base[BANK1_CTX] = fw_buf->dma; - if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { - bank2_virt = dma_alloc_coherent(dev->mem_dev[BANK2_CTX], - align_size, &bank2_dma_addr, GFP_KERNEL); - - if (!bank2_virt) { - mfc_err("Allocating bank2 base failed\n"); - dma_free_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, - fw_buf->virt, fw_buf->dma); - fw_buf->virt = NULL; - return -ENOMEM; - } - - /* Valid buffers passed to MFC encoder with LAST_FRAME command - * should not have address of bank2 - MFC will treat it as a null frame. - * To avoid such situation we set bank2 address below the pool address. - */ - dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; - - dma_free_coherent(dev->mem_dev[BANK2_CTX], align_size, - bank2_virt, bank2_dma_addr); - - } else { - /* In this case bank2 can point to the same address as bank1. - * Firmware will always occupy the beginning of this area so it is - * impossible having a video frame buffer with zero address. */ - dev->dma_base[BANK2_CTX] = dev->dma_base[BANK1_CTX]; - } return 0; } From 3e2c77839d6926c6e2b26562923d91286a07a791 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:35 +0100 Subject: [PATCH 26/35] media: s5p-mfc: Allocate firmware with internal private buffer alloc function Once firmware buffer has been converted to use s5p_mfc_priv_buf structure, it is possible to allocate it with existing s5p_mfc_alloc_priv_buf() function. This change will help to reduce code variants in the next patches. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index b0cf3970117a..a1811ee538bd 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -27,6 +27,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf; + int err; fw_buf->size = dev->variant->buf_size->fw; @@ -35,11 +36,10 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) return -ENOMEM; } - fw_buf->virt = dma_alloc_coherent(dev->mem_dev[BANK1_CTX], fw_buf->size, - &fw_buf->dma, GFP_KERNEL); - if (!fw_buf->virt) { + err = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->fw_buf); + if (err) { mfc_err("Allocating bitprocessor buffer failed\n"); - return -ENOMEM; + return err; } return 0; @@ -92,11 +92,7 @@ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev) { /* Before calling this function one has to make sure * that MFC is no longer processing */ - if (!dev->fw_buf.virt) - return -EINVAL; - dma_free_coherent(dev->mem_dev[BANK1_CTX], dev->fw_buf.size, - dev->fw_buf.virt, dev->fw_buf.dma); - dev->fw_buf.virt = NULL; + s5p_mfc_release_priv_buf(dev, &dev->fw_buf); return 0; } From 28f10463647ab8445f54738bda7bd90bd90bcbcd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:36 +0100 Subject: [PATCH 27/35] media: s5p-mfc: Reduce firmware buffer size for MFC v6+ variants Firmware for MFC v6+ variants is not larger than 400 KiB, so there is no need to allocate a full 1 MiB buffer for it. Reduce it to 512 KiB to keep proper alignment of allocated buffer. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 2 +- drivers/media/platform/s5p-mfc/regs-mfc-v7.h | 2 +- drivers/media/platform/s5p-mfc/regs-mfc-v8.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h index d2cd35916dc5..c0166ee9a455 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h @@ -403,7 +403,7 @@ #define MFC_OTHER_ENC_CTX_BUF_SIZE_V6 (12 * SZ_1K) /* 12KB */ /* MFCv6 variant defines */ -#define MAX_FW_SIZE_V6 (SZ_1M) /* 1MB */ +#define MAX_FW_SIZE_V6 (SZ_512K) /* 512KB */ #define MAX_CPB_SIZE_V6 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V6 0x61 #define MFC_NUM_PORTS_V6 1 diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h index 1a5c6fdf7846..9f220769d970 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h @@ -34,7 +34,7 @@ #define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4 /* MFCv7 variant defines */ -#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */ +#define MAX_FW_SIZE_V7 (SZ_512K) /* 512KB */ #define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V7 0x72 #define MFC_NUM_PORTS_V7 1 diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h index 4d1c3750eb5e..75f5f7511d72 100644 --- a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h +++ b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h @@ -116,7 +116,7 @@ #define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64 /* MFCv8 variant defines */ -#define MAX_FW_SIZE_V8 (SZ_1M) /* 1MB */ +#define MAX_FW_SIZE_V8 (SZ_512K) /* 512KB */ #define MAX_CPB_SIZE_V8 (3 * SZ_1M) /* 3MB */ #define MFC_VERSION_V8 0x80 #define MFC_NUM_PORTS_V8 1 From 3274889e7f3074606ab49bd352a5c5da16480481 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:37 +0100 Subject: [PATCH 28/35] media: s5p-mfc: Split variant DMA memory configuration into separate functions Move code for DMA memory configuration with IOMMU into separate function to make it easier to compare what is being done in each case. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 104 ++++++++++++++--------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index c56ceb812de0..3618e2272f5e 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1107,43 +1107,14 @@ static struct device *s5p_mfc_alloc_memdev(struct device *dev, return NULL; } -static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) +static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; void *bank2_virt; dma_addr_t bank2_dma_addr; unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER; - struct s5p_mfc_priv_buf *fw_buf = &mfc_dev->fw_buf; int ret; - /* - * When IOMMU is available, we cannot use the default configuration, - * because of MFC firmware requirements: address space limited to - * 256M and non-zero default start address. - * This is still simplified, not optimal configuration, but for now - * IOMMU core doesn't allow to configure device's IOMMUs channel - * separately. - */ - if (exynos_is_iommu_available(dev)) { - int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, - S5P_MFC_IOMMU_DMA_SIZE); - if (ret) - return ret; - - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { - exynos_unconfigure_iommu(dev); - return ret; - } - - mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; - mfc_dev->dma_base[BANK2_CTX] = fw_buf->dma; - vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - return 0; - } - /* * Create and initialize virtual devices for accessing * reserved memory regions. @@ -1167,7 +1138,7 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return ret; } - mfc_dev->dma_base[BANK1_CTX] = fw_buf->dma; + mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, &bank2_dma_addr, GFP_KERNEL); @@ -1196,22 +1167,71 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) return 0; } +static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) +{ + device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + device_unregister(mfc_dev->mem_dev[BANK2_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); +} + +static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) +{ + struct device *dev = &mfc_dev->plat_dev->dev; + /* + * When IOMMU is available, we cannot use the default configuration, + * because of MFC firmware requirements: address space limited to + * 256M and non-zero default start address. + * This is still simplified, not optimal configuration, but for now + * IOMMU core doesn't allow to configure device's IOMMUs channel + * separately. + */ + int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, + S5P_MFC_IOMMU_DMA_SIZE); + if (ret) + return ret; + + mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; + ret = s5p_mfc_alloc_firmware(mfc_dev); + if (ret) { + exynos_unconfigure_iommu(dev); + return ret; + } + + mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->dma_base[BANK2_CTX] = mfc_dev->fw_buf.dma; + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + return 0; +} + +static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) +{ + struct device *dev = &mfc_dev->plat_dev->dev; + + exynos_unconfigure_iommu(dev); + vb2_dma_contig_clear_max_seg_size(dev); +} + +static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) +{ + struct device *dev = &mfc_dev->plat_dev->dev; + + if (exynos_is_iommu_available(dev)) + return s5p_mfc_configure_common_memory(mfc_dev); + else + return s5p_mfc_configure_2port_memory(mfc_dev); +} + static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; s5p_mfc_release_firmware(mfc_dev); - - if (exynos_is_iommu_available(dev)) { - exynos_unconfigure_iommu(dev); - vb2_dma_contig_clear_max_seg_size(dev); - return; - } - - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); + if (exynos_is_iommu_available(dev)) + s5p_mfc_unconfigure_common_memory(mfc_dev); + else + s5p_mfc_unconfigure_2port_memory(mfc_dev); } /* MFC probe function */ From 4994e6859c2534b450b5b9bc202a7295c932d41a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:38 +0100 Subject: [PATCH 29/35] media: s5p-mfc: Add support for probe-time preallocated block based allocator Current MFC driver depends on the fact that when IOMMU is available, the DMA-mapping framework and its IOMMU glue will use first-fit allocator. This was true for ARM architecture, but its not for ARM64 arch. However, in case of MFC v6+ hardware and latest firmware, it turned out that there is no strict requirement for ALL buffers to be allocated on higher addresses than the firmware base. This requirement is true only for the device and per-context buffers. All video data buffers can be allocated anywhere for all MFC v6+ versions. Such relaxed requirements for the memory buffers can be easily fulfilled by allocating firmware, device and per-context buffers from the probe-time preallocated larger buffer. This patch adds support for it. This way the driver finally works fine on ARM64 architecture. The size of the preallocated buffer is 8 MiB, what is enough for three instances H264 decoders or encoders (other codecs have smaller memory requirements). If one needs more for particular use case, one can use "mem" module parameter to force larger (or smaller) buffer (for example by adding "s5p_mfc.mem=16M" to kernel command line). Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 43 ++++++++++++-- .../media/platform/s5p-mfc/s5p_mfc_common.h | 4 ++ drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 57 ++++++++++++------- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 3618e2272f5e..1a87af65c06a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -43,6 +43,10 @@ int mfc_debug_level; module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages"); +static char *mfc_mem_size = NULL; +module_param_named(mem, mfc_mem_size, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers"); + /* Helper functions for interrupt processing */ /* Remove from hw execution round robin */ @@ -1178,6 +1182,8 @@ static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; + unsigned long mem_size = SZ_8M; + unsigned int bitmap_size; /* * When IOMMU is available, we cannot use the default configuration, * because of MFC firmware requirements: address space limited to @@ -1191,17 +1197,39 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) if (ret) return ret; - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; - ret = s5p_mfc_alloc_firmware(mfc_dev); - if (ret) { + if (mfc_mem_size) + mem_size = memparse(mfc_mem_size, NULL); + + bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); + + mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!mfc_dev->mem_bitmap) { exynos_unconfigure_iommu(dev); - return ret; + return -ENOMEM; } - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; - mfc_dev->dma_base[BANK2_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, + &mfc_dev->mem_base, GFP_KERNEL); + if (!mfc_dev->mem_virt) { + kfree(mfc_dev->mem_bitmap); + dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", + (mem_size / SZ_1M)); + exynos_unconfigure_iommu(dev); + return -ENOMEM; + } + mfc_dev->mem_size = mem_size; + mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; + mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; + + /* Firmware allocation cannot fail in this case */ + s5p_mfc_alloc_firmware(mfc_dev); + + mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n", + (mem_size / SZ_1M)); + return 0; } @@ -1210,6 +1238,9 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; exynos_unconfigure_iommu(dev); + dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, + mfc_dev->mem_base); + kfree(mfc_dev->mem_bitmap); vb2_dma_contig_clear_max_seg_size(dev); } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index e38a8eec15f9..a209a7a52907 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -315,6 +315,10 @@ struct s5p_mfc_dev { unsigned int int_err; wait_queue_head_t queue; struct s5p_mfc_priv_buf fw_buf; + size_t mem_size; + dma_addr_t mem_base; + unsigned long *mem_bitmap; + void *mem_virt; dma_addr_t dma_base[BANK_CTX_NUM]; unsigned long hw_lock; struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS]; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 9294ee124661..34a66189d980 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -40,41 +40,60 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev) int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[mem_ctx]; - dma_addr_t base = dev->dma_base[mem_ctx]; + unsigned int bits = dev->mem_size >> PAGE_SHIFT; + unsigned int count = b->size >> PAGE_SHIFT; + unsigned int align = (SZ_64K >> PAGE_SHIFT) - 1; + unsigned int start, offset; mfc_debug(3, "Allocating priv: %zu\n", b->size); - b->ctx = mem_ctx; - b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + if (dev->mem_virt) { + start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align); + if (start > bits) + goto no_mem; - if (!b->virt) { - mfc_err("Allocating private buffer of size %zu failed\n", - b->size); - return -ENOMEM; - } + bitmap_set(dev->mem_bitmap, start, count); + offset = start << PAGE_SHIFT; + b->virt = dev->mem_virt + offset; + b->dma = dev->mem_base + offset; + } else { + struct device *mem_dev = dev->mem_dev[mem_ctx]; + dma_addr_t base = dev->dma_base[mem_ctx]; - if (b->dma < base) { - mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", - &b->dma, &base); - dma_free_coherent(mem_dev, b->size, b->virt, b->dma); - return -ENOMEM; + b->ctx = mem_ctx; + b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + if (!b->virt) + goto no_mem; + if (b->dma < base) { + mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n", + &b->dma, &base); + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + return -ENOMEM; + } } mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma); return 0; +no_mem: + mfc_err("Allocating private buffer of size %zu failed\n", b->size); + return -ENOMEM; } void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_priv_buf *b) { - struct device *mem_dev = dev->mem_dev[b->ctx]; + if (dev->mem_virt) { + unsigned int start = (b->dma - dev->mem_base) >> PAGE_SHIFT; + unsigned int count = b->size >> PAGE_SHIFT; + + bitmap_clear(dev->mem_bitmap, start, count); + } else { + struct device *mem_dev = dev->mem_dev[b->ctx]; - if (b->virt) { dma_free_coherent(mem_dev, b->size, b->virt, b->dma); - b->virt = NULL; - b->dma = 0; - b->size = 0; } + b->virt = NULL; + b->dma = 0; + b->size = 0; } From 2a50d9e1aab55794412c8f08f4f5af4d9eef34b3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:39 +0100 Subject: [PATCH 30/35] media: s5p-mfc: Remove special configuration of IOMMU domain The main reason for using special configuration of IOMMU domain was the problem with MFC firmware, which failed to operate properly when placed at 0 DMA address. Instead of adding custom code for configuring each variant of IOMMU domain and architecture specific glue code, simply use what arch code provides and if the DMA base address equals zero, skip first 128 KiB to keep required alignment. This patch also make the driver operational on ARM64 architecture, because it no longer depends on ARM specific DMA-mapping and IOMMU glue code functions. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 30 +++++------ .../media/platform/s5p-mfc/s5p_mfc_iommu.h | 51 +------------------ 2 files changed, 14 insertions(+), 67 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 1a87af65c06a..45b8cdef94b0 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1184,18 +1184,6 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; unsigned long mem_size = SZ_8M; unsigned int bitmap_size; - /* - * When IOMMU is available, we cannot use the default configuration, - * because of MFC firmware requirements: address space limited to - * 256M and non-zero default start address. - * This is still simplified, not optimal configuration, but for now - * IOMMU core doesn't allow to configure device's IOMMUs channel - * separately. - */ - int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, - S5P_MFC_IOMMU_DMA_SIZE); - if (ret) - return ret; if (mfc_mem_size) mem_size = memparse(mfc_mem_size, NULL); @@ -1203,10 +1191,8 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) bitmap_size = BITS_TO_LONGS(mem_size >> PAGE_SHIFT) * sizeof(long); mfc_dev->mem_bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!mfc_dev->mem_bitmap) { - exynos_unconfigure_iommu(dev); + if (!mfc_dev->mem_bitmap) return -ENOMEM; - } mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size, &mfc_dev->mem_base, GFP_KERNEL); @@ -1214,13 +1200,24 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) kfree(mfc_dev->mem_bitmap); dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n", (mem_size / SZ_1M)); - exynos_unconfigure_iommu(dev); return -ENOMEM; } mfc_dev->mem_size = mem_size; mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; + /* + * MFC hardware cannot handle 0 as a base address, so mark first 128K + * as used (to keep required base alignment) and adjust base address + */ + if (mfc_dev->mem_base == (dma_addr_t)0) { + unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER; + + bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT); + mfc_dev->dma_base[BANK1_CTX] += offset; + mfc_dev->dma_base[BANK2_CTX] += offset; + } + /* Firmware allocation cannot fail in this case */ s5p_mfc_alloc_firmware(mfc_dev); @@ -1237,7 +1234,6 @@ static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - exynos_unconfigure_iommu(dev); dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt, mfc_dev->mem_base); kfree(mfc_dev->mem_bitmap); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h index 6962132ae8fa..76667924ee2a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h @@ -11,54 +11,13 @@ #ifndef S5P_MFC_IOMMU_H_ #define S5P_MFC_IOMMU_H_ -#define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu -#define S5P_MFC_IOMMU_DMA_SIZE SZ_256M - -#if defined(CONFIG_EXYNOS_IOMMU) && defined(CONFIG_ARM_DMA_USE_IOMMU) - -#include +#if defined(CONFIG_EXYNOS_IOMMU) static inline bool exynos_is_iommu_available(struct device *dev) { return dev->archdata.iommu != NULL; } -static inline void exynos_unconfigure_iommu(struct device *dev) -{ - struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); - - arm_iommu_detach_device(dev); - arm_iommu_release_mapping(mapping); -} - -static inline int exynos_configure_iommu(struct device *dev, - unsigned int base, unsigned int size) -{ - struct dma_iommu_mapping *mapping = NULL; - int ret; - - /* Disable the default mapping created by device core */ - if (to_dma_iommu_mapping(dev)) - exynos_unconfigure_iommu(dev); - - mapping = arm_iommu_create_mapping(dev->bus, base, size); - if (IS_ERR(mapping)) { - pr_warn("Failed to create IOMMU mapping for device %s\n", - dev_name(dev)); - return PTR_ERR(mapping); - } - - ret = arm_iommu_attach_device(dev, mapping); - if (ret) { - pr_warn("Failed to attached device %s to IOMMU_mapping\n", - dev_name(dev)); - arm_iommu_release_mapping(mapping); - return ret; - } - - return 0; -} - #else static inline bool exynos_is_iommu_available(struct device *dev) @@ -66,14 +25,6 @@ static inline bool exynos_is_iommu_available(struct device *dev) return false; } -static inline int exynos_configure_iommu(struct device *dev, - unsigned int base, unsigned int size) -{ - return -ENOSYS; -} - -static inline void exynos_unconfigure_iommu(struct device *dev) { } - #endif #endif /* S5P_MFC_IOMMU_H_ */ From f6c15d45194cc27d357f100c1283e048fb497c20 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:40 +0100 Subject: [PATCH 31/35] media: s5p-mfc: Use preallocated block allocator always for MFC v6+ It turned out that all versions of MFC v6+ hardware doesn't have a strict requirement for ALL buffers to be allocated on higher addresses than the firmware base like it was documented for MFC v5. This requirement is true only for the device and per-context buffers. All video data buffers can be allocated anywhere for all MFC v6+ versions. Basing on this fact, the special DMA configuration based on two reserved memory regions is not really needed for MFC v6+ devices, because the memory requirements for the firmware, device and per-context buffers can be fulfilled by the simple probe-time pre-allocated block allocator instroduced in previous patch. This patch enables support for such pre-allocated block based allocator always for MFC v6+ devices. Due to the limitations of the memory management subsystem the largest supported size of the pre-allocated buffer when no CMA (Contiguous Memory Allocator) is enabled is 4MiB. This patch also removes the requirement to provide two reserved memory regions for MFC v6+ devices in device tree. Now the driver is fully functional without them. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- Documentation/devicetree/bindings/media/s5p-mfc.txt | 2 +- drivers/media/platform/s5p-mfc/s5p_mfc.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt index 2c901286d818..d3404b5d4d17 100644 --- a/Documentation/devicetree/bindings/media/s5p-mfc.txt +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt @@ -28,7 +28,7 @@ Optional properties: - memory-region : from reserved memory binding: phandles to two reserved memory regions, first is for "left" mfc memory bus interfaces, second if for the "right" mfc memory bus, used when no SYSMMU - support is available + support is available; used only by MFC v5 present in Exynos4 SoCs Obsolete properties: - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 45b8cdef94b0..5fa080649e2a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1182,9 +1182,12 @@ static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - unsigned long mem_size = SZ_8M; + unsigned long mem_size = SZ_4M; unsigned int bitmap_size; + if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev)) + mem_size = SZ_8M; + if (mfc_mem_size) mem_size = memparse(mfc_mem_size, NULL); @@ -1244,7 +1247,7 @@ static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) { struct device *dev = &mfc_dev->plat_dev->dev; - if (exynos_is_iommu_available(dev)) + if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev)) return s5p_mfc_configure_common_memory(mfc_dev); else return s5p_mfc_configure_2port_memory(mfc_dev); @@ -1255,7 +1258,7 @@ static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) struct device *dev = &mfc_dev->plat_dev->dev; s5p_mfc_release_firmware(mfc_dev); - if (exynos_is_iommu_available(dev)) + if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev)) s5p_mfc_unconfigure_common_memory(mfc_dev); else s5p_mfc_unconfigure_2port_memory(mfc_dev); From ed9a8f44137b88a7e1356de7aa2480abe8aaff85 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:41 +0100 Subject: [PATCH 32/35] media: s5p-mfc: Rename BANK1/2 to BANK_L/R to better match documentation Documentation for MFC hardware still uses 'left' and 'right' names for the memory channel/banks, so replace BANK1/2 defines with more appropriate BANK_L/R names. Suggested-by: Shuah Khan Signed-off-by: Marek Szyprowski Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 54 +++++++++---------- .../media/platform/s5p-mfc/s5p_mfc_common.h | 4 +- drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c | 13 ++--- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 8 +-- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 10 ++-- .../media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 28 +++++----- .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 6 +-- 7 files changed, 62 insertions(+), 61 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 5fa080649e2a..00c7118b466d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1123,34 +1123,34 @@ static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) * Create and initialize virtual devices for accessing * reserved memory regions. */ - mfc_dev->mem_dev[BANK1_CTX] = s5p_mfc_alloc_memdev(dev, "left", - BANK1_CTX); - if (!mfc_dev->mem_dev[BANK1_CTX]) + mfc_dev->mem_dev[BANK_L_CTX] = s5p_mfc_alloc_memdev(dev, "left", + BANK_L_CTX); + if (!mfc_dev->mem_dev[BANK_L_CTX]) return -ENODEV; - mfc_dev->mem_dev[BANK2_CTX] = s5p_mfc_alloc_memdev(dev, "right", - BANK2_CTX); - if (!mfc_dev->mem_dev[BANK2_CTX]) { - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + mfc_dev->mem_dev[BANK_R_CTX] = s5p_mfc_alloc_memdev(dev, "right", + BANK_R_CTX); + if (!mfc_dev->mem_dev[BANK_R_CTX]) { + device_unregister(mfc_dev->mem_dev[BANK_L_CTX]); return -ENODEV; } /* Allocate memory for firmware and initialize both banks addresses */ ret = s5p_mfc_alloc_firmware(mfc_dev); if (ret) { - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_R_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_L_CTX]); return ret; } - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->fw_buf.dma; + mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->fw_buf.dma; - bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, - &bank2_dma_addr, GFP_KERNEL); + bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK_R_CTX], + align_size, &bank2_dma_addr, GFP_KERNEL); if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); s5p_mfc_release_firmware(mfc_dev); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_R_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_L_CTX]); return -ENOMEM; } @@ -1158,14 +1158,14 @@ static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ - mfc_dev->dma_base[BANK2_CTX] = bank2_dma_addr - align_size; + mfc_dev->dma_base[BANK_R_CTX] = bank2_dma_addr - align_size; - dma_free_coherent(mfc_dev->mem_dev[BANK2_CTX], align_size, bank2_virt, + dma_free_coherent(mfc_dev->mem_dev[BANK_R_CTX], align_size, bank2_virt, bank2_dma_addr); - vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK1_CTX], + vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX], DMA_BIT_MASK(32)); - vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK2_CTX], + vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX], DMA_BIT_MASK(32)); return 0; @@ -1173,10 +1173,10 @@ static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev) static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev) { - device_unregister(mfc_dev->mem_dev[BANK1_CTX]); - device_unregister(mfc_dev->mem_dev[BANK2_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK1_CTX]); - vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK2_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_L_CTX]); + device_unregister(mfc_dev->mem_dev[BANK_R_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX]); + vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX]); } static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) @@ -1206,8 +1206,8 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) return -ENOMEM; } mfc_dev->mem_size = mem_size; - mfc_dev->dma_base[BANK1_CTX] = mfc_dev->mem_base; - mfc_dev->dma_base[BANK2_CTX] = mfc_dev->mem_base; + mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->mem_base; + mfc_dev->dma_base[BANK_R_CTX] = mfc_dev->mem_base; /* * MFC hardware cannot handle 0 as a base address, so mark first 128K @@ -1217,14 +1217,14 @@ static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev) unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER; bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT); - mfc_dev->dma_base[BANK1_CTX] += offset; - mfc_dev->dma_base[BANK2_CTX] += offset; + mfc_dev->dma_base[BANK_L_CTX] += offset; + mfc_dev->dma_base[BANK_R_CTX] += offset; } /* Firmware allocation cannot fail in this case */ s5p_mfc_alloc_firmware(mfc_dev); - mfc_dev->mem_dev[BANK1_CTX] = mfc_dev->mem_dev[BANK2_CTX] = dev; + mfc_dev->mem_dev[BANK_L_CTX] = mfc_dev->mem_dev[BANK_R_CTX] = dev; vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n", diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index a209a7a52907..4a33370d8887 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -33,8 +33,8 @@ * while mmaping */ #define DST_QUEUE_OFF_BASE (1 << 30) -#define BANK1_CTX 0 -#define BANK2_CTX 1 +#define BANK_L_CTX 0 +#define BANK_R_CTX 1 #define BANK_CTX_NUM 2 #define MFC_BANK1_ALIGN_ORDER 13 diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c index a1811ee538bd..69ef9c23a99a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c @@ -36,7 +36,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) return -ENOMEM; } - err = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->fw_buf); + err = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->fw_buf); if (err) { mfc_err("Allocating bitprocessor buffer failed\n"); return err; @@ -177,17 +177,18 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev) static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) { if (IS_MFCV6_PLUS(dev)) { - mfc_write(dev, dev->dma_base[BANK1_CTX], + mfc_write(dev, dev->dma_base[BANK_L_CTX], S5P_FIMV_RISC_BASE_ADDRESS_V6); mfc_debug(2, "Base Address : %pad\n", - &dev->dma_base[BANK1_CTX]); + &dev->dma_base[BANK_L_CTX]); } else { - mfc_write(dev, dev->dma_base[BANK1_CTX], + mfc_write(dev, dev->dma_base[BANK_L_CTX], S5P_FIMV_MC_DRAMBASE_ADR_A); - mfc_write(dev, dev->dma_base[BANK2_CTX], + mfc_write(dev, dev->dma_base[BANK_R_CTX], S5P_FIMV_MC_DRAMBASE_ADR_B); mfc_debug(2, "Bank1: %pad, Bank2: %pad\n", - &dev->dma_base[BANK1_CTX], &dev->dma_base[BANK2_CTX]); + &dev->dma_base[BANK_L_CTX], + &dev->dma_base[BANK_R_CTX]); } } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index d470f0f7b1a0..87dd4f2b9b37 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -935,14 +935,14 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; else - alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX]; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) { psize[0] = ctx->dec_src_buf_size; - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; } else { mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); return -EINVAL; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 5747dc453f10..0a44feee7ffc 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1845,7 +1845,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, if (*buf_count > MFC_MAX_BUFFERS) *buf_count = MFC_MAX_BUFFERS; psize[0] = ctx->enc_dst_buf_size; - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->src_fmt) *plane_count = ctx->src_fmt->num_planes; @@ -1861,11 +1861,11 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq, psize[1] = ctx->chroma_size; if (IS_MFCV6_PLUS(dev)) { - alloc_devs[0] = ctx->dev->mem_dev[BANK1_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK1_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX]; } else { - alloc_devs[0] = ctx->dev->mem_dev[BANK2_CTX]; - alloc_devs[1] = ctx->dev->mem_dev[BANK2_CTX]; + alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX]; + alloc_devs[1] = ctx->dev->mem_dev[BANK_R_CTX]; } } else { mfc_err("invalid queue type: %d\n", vq->type); diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c index 20e8a1bdc984..b41ee608c171 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c @@ -30,8 +30,8 @@ #include #include -#define OFFSETA(x) (((x) - dev->dma_base[BANK1_CTX]) >> MFC_OFFSET_SHIFT) -#define OFFSETB(x) (((x) - dev->dma_base[BANK2_CTX]) >> MFC_OFFSET_SHIFT) +#define OFFSETA(x) (((x) - dev->dma_base[BANK_L_CTX]) >> MFC_OFFSET_SHIFT) +#define OFFSETB(x) (((x) - dev->dma_base[BANK_R_CTX]) >> MFC_OFFSET_SHIFT) /* Allocate temporary buffers for decoding */ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) @@ -41,7 +41,7 @@ static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx) int ret; ctx->dsc.size = buf_size->dsc; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->dsc); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->dsc); if (ret) { mfc_err("Failed to allocate temporary buffer\n"); return ret; @@ -172,7 +172,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 temporary buffer\n"); return ret; @@ -181,7 +181,7 @@ static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx) } /* Allocate only if memory from bank 2 is necessary */ if (ctx->bank2.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK2_CTX, &ctx->bank2); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_R_CTX, &ctx->bank2); if (ret) { mfc_err("Failed to allocate Bank2 temporary buffer\n"); s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); @@ -212,7 +212,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) else ctx->ctx.size = buf_size->non_h264_ctx; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -225,7 +225,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) /* Initialize shared memory */ ctx->shm.size = buf_size->shm; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->shm); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->shm); if (ret) { mfc_err("Failed to allocate shared memory buffer\n"); s5p_mfc_release_priv_buf(dev, &ctx->ctx); @@ -233,7 +233,7 @@ static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx) } /* shared memory offset only keeps the offset from base (port a) */ - ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK1_CTX]; + ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK_L_CTX]; BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1)); memset(ctx->shm.virt, 0, buf_size->shm); @@ -532,9 +532,9 @@ static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx, { struct s5p_mfc_dev *dev = ctx->dev; - *y_addr = dev->dma_base[BANK2_CTX] + + *y_addr = dev->dma_base[BANK_R_CTX] + (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT); - *c_addr = dev->dma_base[BANK2_CTX] + + *c_addr = dev->dma_base[BANK_R_CTX] + (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT); } @@ -1212,8 +1212,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) } if (list_empty(&ctx->src_queue)) { /* send null frame */ - s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK2_CTX], - dev->dma_base[BANK2_CTX]); + s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK_R_CTX], + dev->dma_base[BANK_R_CTX]); src_mb = NULL; } else { src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, @@ -1222,8 +1222,8 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) if (src_mb->b->vb2_buf.planes[0].bytesused == 0) { /* send null frame */ s5p_mfc_set_enc_frame_buffer_v5(ctx, - dev->dma_base[BANK2_CTX], - dev->dma_base[BANK2_CTX]); + dev->dma_base[BANK_R_CTX], + dev->dma_base[BANK_R_CTX]); ctx->state = MFCINST_FINISHING; } else { src_y_addr = vb2_dma_contig_plane_dma_addr( diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index 4e5ead236455..c6ab89ac62b9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,7 +239,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->bank1); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -291,7 +291,7 @@ static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx) break; } - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &ctx->ctx); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx); if (ret) { mfc_err("Failed to allocate instance buffer\n"); return ret; @@ -320,7 +320,7 @@ static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev) mfc_debug_enter(); dev->ctx_buf.size = buf_size->dev_ctx; - ret = s5p_mfc_alloc_priv_buf(dev, BANK1_CTX, &dev->ctx_buf); + ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->ctx_buf); if (ret) { mfc_err("Failed to allocate device context buffer\n"); return ret; From 95919cb260e25b507db37afd1e5d537674d90797 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 20 Mar 2017 11:56:42 +0100 Subject: [PATCH 33/35] ARM: dts: exynos: Remove MFC reserved buffers During my research I found that some of the requirements for the memory buffers for MFC v6+ devices were blindly copied from the previous (v5) version and simply turned out to be excessive. The relaxed requirements are applied by the recent patches to the MFC driver and the driver is now fully functional even without the reserved memory blocks for all v6+ variants. This patch removes those reserved memory nodes from all boards having MFC v6+ hardware block. Signed-off-by: Marek Szyprowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Acked-by: Andrzej Hajda Tested-by: Smitha T Murthy Signed-off-by: memeka Signed-off-by: Ard van Breemen --- arch/arm/boot/dts/exynos5250-arndale.dts | 1 - arch/arm/boot/dts/exynos5250-smdk5250.dts | 1 - arch/arm/boot/dts/exynos5250-spring.dts | 1 - arch/arm/boot/dts/exynos5420-arndale-octa.dts | 1 - arch/arm/boot/dts/exynos5420-peach-pit.dts | 1 - arch/arm/boot/dts/exynos5420-smdk5420.dts | 1 - arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 1 - arch/arm/boot/dts/exynos5800-peach-pi.dts | 1 - 8 files changed, 8 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 6098dacd09f1..6a432460eb77 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -14,7 +14,6 @@ #include #include #include "exynos5250.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Insignal Arndale evaluation board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index a97a785ccc6b..6632f657394e 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -13,7 +13,6 @@ #include #include #include "exynos5250.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index 4d7bdb735ed3..95c3bcace9dc 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -14,7 +14,6 @@ #include #include #include "exynos5250.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Spring"; diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index 9cc83c51c925..ee1bb9b8b366 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -16,7 +16,6 @@ #include #include #include -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Insignal Arndale Octa evaluation board based on EXYNOS5420"; diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index ec4a00f1ce01..672f49ee27e2 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -16,7 +16,6 @@ #include #include "exynos5420.dtsi" #include "exynos5420-cpus.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Peach Pit Rev 6+"; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index aaccd0da41e5..08c8ab173e87 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -13,7 +13,6 @@ #include "exynos5420.dtsi" #include "exynos5420-cpus.dtsi" #include -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Samsung SMDK5420 board based on EXYNOS5420"; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi index 3cd7cb3626e1..6412070b6344 100755 --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi @@ -19,7 +19,6 @@ #include #include "exynos5800.dtsi" #include "exynos5422-cpus.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { revision = <0x0100>; diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 01f466816fea..6f2364e12607 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -16,7 +16,6 @@ #include #include "exynos5800.dtsi" #include "exynos5420-cpus.dtsi" -#include "exynos-mfc-reserved-memory.dtsi" / { model = "Google Peach Pi Rev 10+"; From 0f47ba7335e83e8ea9864ac8981ba77594cc89a5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 22 Mar 2017 11:34:28 +0100 Subject: [PATCH 34/35] media: s5p-mfc: Don't allocate codec buffers from pre-allocated region Further investigation revealed that codec buffers also don't need to be allocated at higher addresses than firmware base for MFC v6+ hardware. Those buffers can be quite large and its size depends on the selected format and framesize. This patch changes the way the codec buffers are allocated - driver will use generic allocator for them instead of the pre-allocated buffer for firmware and contexts. Signed-off-by: Marek Szyprowski Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 28 +++++++++++++++++++ drivers/media/platform/s5p-mfc/s5p_mfc_opr.h | 4 +++ .../media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 4 +-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c index 34a66189d980..7f33cf23947f 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c @@ -79,6 +79,25 @@ no_mem: return -ENOMEM; } +int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, + struct s5p_mfc_priv_buf *b) +{ + struct device *mem_dev = dev->mem_dev[mem_ctx]; + + mfc_debug(3, "Allocating generic buf: %zu\n", b->size); + + b->ctx = mem_ctx; + b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL); + if (!b->virt) + goto no_mem; + + mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma); + return 0; +no_mem: + mfc_err("Allocating generic buffer of size %zu failed\n", b->size); + return -ENOMEM; +} + void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_priv_buf *b) { @@ -97,3 +116,12 @@ void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, b->size = 0; } +void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev, + struct s5p_mfc_priv_buf *b) +{ + struct device *mem_dev = dev->mem_dev[b->ctx]; + dma_free_coherent(mem_dev, b->size, b->virt, b->dma); + b->virt = NULL; + b->dma = 0; + b->size = 0; +} diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h index 108e59382e0c..16d553fcff08 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h @@ -319,6 +319,10 @@ int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, struct s5p_mfc_priv_buf *b); void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_priv_buf *b); +int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx, + struct s5p_mfc_priv_buf *b); +void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev, + struct s5p_mfc_priv_buf *b); #endif /* S5P_MFC_OPR_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c index c6ab89ac62b9..b2528165c1b4 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c @@ -239,7 +239,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Allocate only if memory from bank 1 is necessary */ if (ctx->bank1.size > 0) { - ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1); + ret = s5p_mfc_alloc_generic_buf(dev, BANK_L_CTX, &ctx->bank1); if (ret) { mfc_err("Failed to allocate Bank1 memory\n"); return ret; @@ -252,7 +252,7 @@ static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx) /* Release buffers allocated for codec */ static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx) { - s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1); + s5p_mfc_release_generic_buf(ctx->dev, &ctx->bank1); } /* Allocate memory for instance data buffer */ From 8518369cad7ff65fd8ff171753944977a3ed8abf Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 22 Mar 2017 08:53:57 +0100 Subject: [PATCH 35/35] media: s5p-mfc: Fix unbalanced call to clock management Clock should be turned off after calling s5p_mfc_init_hw() from the watchdog worker, like it is already done in the s5p_mfc_open() which also calls this function. Signed-off-by: Marek Szyprowski Fixes: af93574678108 ("[media] MFC: Add MFC 5.1 V4L2 driver") CC: stable@vger.kernel.org # v3.7+ Signed-off-by: memeka Signed-off-by: Ard van Breemen --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 00c7118b466d..ba2233f1f0d7 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -211,6 +211,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) } s5p_mfc_clock_on(); ret = s5p_mfc_init_hw(dev); + s5p_mfc_clock_off(); if (ret) mfc_err("Failed to reinit FW\n"); }