From deca8a9c70292c0a33c16e5b463d2a2f64de0689 Mon Sep 17 00:00:00 2001 From: jintao xu Date: Thu, 19 Oct 2017 16:32:29 +0800 Subject: [PATCH] ion_dev: add codec_mm heap for omx. [3/3] PD#152137: add codec_mm heap for omx codec_mm_cma 308M; ion_dev_dma 92M; Change-Id: I804d16c19e6133ec41bd51a7b2c328339a8d0fd7 Signed-off-by: jintao xu --- MAINTAINERS | 4 + arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxl_skt.dts | 5 +- arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts | 5 +- arch/arm64/boot/dts/amlogic/gxm_skt.dts | 5 +- drivers/amlogic/media/common/ion_dev/dev_ion.c | 6 +- drivers/staging/android/ion/Makefile | 2 +- drivers/staging/android/ion/ion_codec_mm_heap.c | 169 ++++++++++++++++++++++++ drivers/staging/android/ion/ion_heap.c | 6 + drivers/staging/android/ion/ion_priv.h | 13 ++ 14 files changed, 220 insertions(+), 20 deletions(-) create mode 100644 drivers/staging/android/ion/ion_codec_mm_heap.c diff --git a/MAINTAINERS b/MAINTAINERS index 99caf2a..84c35ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14092,3 +14092,7 @@ F: scripts/amlogic/configs/meson64_audio_defconfig AMLOGIC gpio key wakeup function M: Hong Guo F: drivers/amlogic/input/keyboard/* + +AMLOGIC ION_DEV ADD CODEC_MM +M: JinTao Xu +F: drivers/staging/android/ion/ion_codec_mm_heap.c \ No newline at end of file diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts index 969fb74..1cee44d 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts @@ -88,7 +88,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x8000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -118,7 +118,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts index d246013..02b0a61 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p212_2g.dts @@ -97,7 +97,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x8000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -127,7 +127,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts index ab38487..92b7a1a 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p230_2g.dts @@ -89,7 +89,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x8000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -119,7 +119,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts index 047e032..773718c 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_1g.dts @@ -89,7 +89,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x7000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -119,7 +119,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts index e8b4b75..5bf32dc 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_p231_2g.dts @@ -89,7 +89,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x7000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -119,7 +119,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxl_skt.dts b/arch/arm64/boot/dts/amlogic/gxl_skt.dts index eeb57bb..518ec8d 100644 --- a/arch/arm64/boot/dts/amlogic/gxl_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxl_skt.dts @@ -88,7 +88,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x7000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -118,7 +118,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts index acb2cdd..02ac8e2 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_q200_2g.dts @@ -88,7 +88,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x7000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -118,7 +118,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x11400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/arch/arm64/boot/dts/amlogic/gxm_skt.dts b/arch/arm64/boot/dts/amlogic/gxm_skt.dts index c955ddb..e81b923 100644 --- a/arch/arm64/boot/dts/amlogic/gxm_skt.dts +++ b/arch/arm64/boot/dts/amlogic/gxm_skt.dts @@ -88,7 +88,7 @@ ion_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x7000000>; + size = <0x0 0x5C00000>; alignment = <0x0 0x400000>; }; @@ -118,7 +118,8 @@ codec_mm_cma:linux,codec_mm_cma { compatible = "shared-dma-pool"; reusable; - size = <0x0 0x10400000>; + /* ion_codec_mm max can alloc size 80M*/ + size = <0x0 0x13400000>; alignment = <0x0 0x400000>; linux,contiguous-region; }; diff --git a/drivers/amlogic/media/common/ion_dev/dev_ion.c b/drivers/amlogic/media/common/ion_dev/dev_ion.c index 595dd54..8a5e706 100644 --- a/drivers/amlogic/media/common/ion_dev/dev_ion.c +++ b/drivers/amlogic/media/common/ion_dev/dev_ion.c @@ -189,14 +189,14 @@ int dev_ion_probe(struct platform_device *pdev) my_ion_heap[num_heaps].name = "vmalloc_ion"; num_heaps++; -#ifdef CONFIG_AMLOGIC_ION_CODEC_MM my_ion_heap[num_heaps].type = ION_HEAP_TYPE_CUSTOM; my_ion_heap[num_heaps].id = ION_HEAP_TYPE_CUSTOM; my_ion_heap[num_heaps].name = "codec_mm_ion"; my_ion_heap[num_heaps].base = (ion_phys_addr_t) NULL; - my_ion_heap[num_heaps].size = 32 * 1024 * 1024; + /* limit the maximum alloc total size 80M */ + my_ion_heap[num_heaps].size = 80 * 1024 * 1024; num_heaps++; -#endif + /*add CMA ion heap*/ my_ion_heap[num_heaps].type = ION_HEAP_TYPE_DMA; my_ion_heap[num_heaps].id = ION_HEAP_TYPE_DMA; diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 5d630a0..9fc3120 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ ion_page_pool.o ion_system_heap.o \ - ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o + ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o ion_codec_mm_heap.o obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT obj-$(CONFIG_ION) += compat_ion.o diff --git a/drivers/staging/android/ion/ion_codec_mm_heap.c b/drivers/staging/android/ion/ion_codec_mm_heap.c new file mode 100644 index 0000000..074992f --- /dev/null +++ b/drivers/staging/android/ion/ion_codec_mm_heap.c @@ -0,0 +1,169 @@ +/* + * drivers/staging/android/ion/ion_codec_mm_heap.c + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" +#include + +struct ion_codec_mm_heap { + struct ion_heap heap; + int max_can_alloc_size; + int alloced_size; +}; + +#define CODEC_MM_ION "ION" + +ion_phys_addr_t ion_codec_mm_allocate(struct ion_heap *heap, + unsigned long size, + unsigned long align) +{ + struct ion_codec_mm_heap *codec_heap = + container_of(heap, struct ion_codec_mm_heap, heap); + unsigned long offset; + + if (codec_heap->alloced_size + size > codec_heap->max_can_alloc_size) { + pr_err( + "ion_codec_mm_allocate failed out size %ld,alloced %d\n", + size, + codec_heap->alloced_size); + return ION_CODEC_MM_ALLOCATE_FAIL; + } + + offset = codec_mm_alloc_for_dma( + CODEC_MM_ION, + size / PAGE_SIZE, + 0, + CODEC_MM_FLAGS_DMA_CPU); + + if (!offset) { + pr_err("ion_codec_mm_allocate failed out size %d\n", (int)size); + return ION_CODEC_MM_ALLOCATE_FAIL; + } + codec_heap->alloced_size += size; + return offset; +} + +void ion_codec_mm_free(struct ion_heap *heap, ion_phys_addr_t addr, + unsigned long size) +{ + struct ion_codec_mm_heap *codec_heap = + container_of(heap, struct ion_codec_mm_heap, heap); + + if (addr == ION_CODEC_MM_ALLOCATE_FAIL) + return; + codec_mm_free_for_dma(CODEC_MM_ION, addr); + codec_heap->alloced_size -= size; +} + +static int ion_codec_mm_heap_allocate(struct ion_heap *heap, + struct ion_buffer *buffer, + unsigned long size, unsigned long align, + unsigned long flags) +{ + struct sg_table *table; + ion_phys_addr_t paddr; + int ret; + + if (align > PAGE_SIZE) + return -EINVAL; + + table = kzalloc(sizeof(*table), GFP_KERNEL); + if (!table) + return -ENOMEM; + ret = sg_alloc_table(table, 1, GFP_KERNEL); + if (ret) + goto err_free; + + paddr = ion_codec_mm_allocate(heap, size, align); + if (paddr == ION_CODEC_MM_ALLOCATE_FAIL) { + ret = -ENOMEM; + goto err_free_table; + } + + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(paddr)), size, 0); + buffer->priv_virt = table; + buffer->sg_table = table; + + return 0; + +err_free_table: + sg_free_table(table); +err_free: + kfree(table); + return ret; +} + +static void ion_codec_mm_heap_free(struct ion_buffer *buffer) +{ + struct ion_heap *heap = buffer->heap; + struct sg_table *table = buffer->priv_virt; + struct page *page = sg_page(table->sgl); + ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); + + ion_heap_buffer_zero(buffer); + + if (ion_buffer_cached(buffer)) + dma_sync_sg_for_device( + NULL, + table->sgl, + table->nents, + DMA_BIDIRECTIONAL); + + ion_codec_mm_free(heap, paddr, buffer->size); + sg_free_table(table); + kfree(table); +} + +static struct ion_heap_ops codec_mm_heap_ops = { + .allocate = ion_codec_mm_heap_allocate, + .free = ion_codec_mm_heap_free, + .map_user = ion_heap_map_user, + .map_kernel = ion_heap_map_kernel, + .unmap_kernel = ion_heap_unmap_kernel, +}; + +struct ion_heap *ion_codec_mm_heap_create(struct ion_platform_heap *heap_data) +{ + struct ion_codec_mm_heap *codec_heap; + /* int ret; */ + codec_heap = kzalloc(sizeof(*codec_heap), GFP_KERNEL); + if (!codec_heap) + return ERR_PTR(-ENOMEM); + + codec_heap->max_can_alloc_size = heap_data->size; + codec_heap->alloced_size = 0; + codec_heap->heap.ops = &codec_mm_heap_ops; + codec_heap->heap.type = ION_HEAP_TYPE_CUSTOM; + codec_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; + return &codec_heap->heap; +} + +void ion_codec_mm_heap_destroy(struct ion_heap *heap) +{ + struct ion_codec_mm_heap *codec_heap = + container_of(heap, struct ion_codec_mm_heap, heap); + + kfree(codec_heap); + codec_heap = NULL; +} diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 4e5c0f1..908b2f1 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -335,6 +335,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_DMA: heap = ion_cma_heap_create(heap_data); break; + case ION_HEAP_TYPE_CUSTOM: + heap = ion_codec_mm_heap_create(heap_data); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type); @@ -375,6 +378,9 @@ void ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_DMA: ion_cma_heap_destroy(heap); break; + case ION_HEAP_TYPE_CUSTOM: + ion_codec_mm_heap_destroy(heap); + break; default: pr_err("%s: Invalid heap type %d\n", __func__, heap->type); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 3c3b324..0dd87813 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -388,6 +388,19 @@ struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *); void ion_cma_heap_destroy(struct ion_heap *); /** + * The codec_mm heap returns physical addresses, since 0 may be a valid + * physical address, this is used to indicate allocation failed + */ +#define ION_CODEC_MM_ALLOCATE_FAIL -1 + +/* + * Amlogic: + * Alloc from codec_mm support + */ +struct ion_heap *ion_codec_mm_heap_create(struct ion_platform_heap *heap_data); +void ion_codec_mm_heap_destroy(struct ion_heap *heap); + +/** * functions for creating and destroying a heap pool -- allows you * to keep a pool of pre allocated memory to use from your heap. Keeping * a pool of memory that is ready for dma, ie any cached mapping have been -- 2.7.4