diff options
Diffstat (limited to 'drivers/media/platform/chips-media/wave5/wave5-vdi.c')
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vdi.c | 151 |
1 files changed, 61 insertions, 90 deletions
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index e829feee2b26..beae8c747b3d 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -2,7 +2,7 @@ /* * Wave5 series multi-standard codec IP - low level access functions * - * Copyright (C) 2021 CHIPS&MEDIA INC + * Copyright (C) 2021-2023 CHIPS&MEDIA INC */ #include <linux/bug.h> @@ -10,11 +10,17 @@ #include "wave5-vpu.h" #include "wave5-regdefine.h" #include <linux/delay.h> -#include <soc/sifive/sifive_l2_cache.h> +extern void sifive_l2_flush64_range(unsigned long start, unsigned long len); +extern void sifive_ccache_flush_entire(void); -#define VDI_SYSTEM_ENDIAN VDI_LITTLE_ENDIAN -#define VDI_128BIT_BUS_SYSTEM_ENDIAN VDI_128BIT_LITTLE_ENDIAN +void wave5_flush_l2_cache(unsigned long start, unsigned long len) +{ + if (len >= 0x80000) + sifive_ccache_flush_entire(); + else + sifive_l2_flush64_range(start, len); +} static int wave5_vdi_allocate_common_memory(struct device *dev) { @@ -50,11 +56,11 @@ int wave5_vdi_init(struct device *dev) if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code); - return 0; + return -EOPNOTSUPP; } - // if BIT processor is not running. - if (wave5_vdi_readl(vpu_dev, W5_VCPU_CUR_PC) == 0) { + /* if BIT processor is not running. */ + if (wave5_vdi_read_register(vpu_dev, W5_VCPU_CUR_PC) == 0) { int i; for (i = 0; i < 64; i++) @@ -81,7 +87,7 @@ void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data) writel(data, vpu_dev->vdb_register + addr); } -unsigned int wave5_vdi_readl(struct vpu_device *vpu_dev, u32 addr) +unsigned int wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr) { return readl(vpu_dev->vdb_register + addr); } @@ -94,15 +100,12 @@ int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) } memset(vb->vaddr, 0, vb->size); - sifive_l2_flush64_range(vb->daddr, vb->size); + wave5_flush_l2_cache(vb->daddr, vb->size); return vb->size; } -static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len, - unsigned int endian); - int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset, - u8 *data, size_t len, unsigned int endian) + u8 *data, size_t len) { if (!vb || !vb->vaddr) { dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__); @@ -114,9 +117,8 @@ int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_ return -ENOSPC; } - wave5_swap_endian(vpu_dev, data, len, endian); memcpy(vb->vaddr + offset, data, len); - sifive_l2_flush64_range(vb->daddr + offset, len); + wave5_flush_l2_cache(vb->daddr + offset, len); return len; } @@ -137,15 +139,15 @@ int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb vb->vaddr = vaddr; vb->daddr = daddr; - sifive_l2_flush64_range(daddr, vb->size); + wave5_flush_l2_cache(daddr, vb->size); return 0; } -void wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) +int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) { if (vb->size == 0) - return; + return -EINVAL; if (!vb->vaddr) dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__); @@ -153,97 +155,66 @@ void wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr); memset(vb, 0, sizeof(*vb)); + + return 0; } -unsigned int wave5_vdi_convert_endian(struct vpu_device *vpu_dev, unsigned int endian) +int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count, + size_t size) { - if (PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { - switch (endian) { - case VDI_LITTLE_ENDIAN: - endian = 0x00; - break; - case VDI_BIG_ENDIAN: - endian = 0x0f; - break; - case VDI_32BIT_LITTLE_ENDIAN: - endian = 0x04; - break; - case VDI_32BIT_BIG_ENDIAN: - endian = 0x03; - break; - } - } + struct vpu_buf vb_buf; + int i, ret = 0; - return (endian & 0x0f); -} + vb_buf.size = size; -static void byte_swap(unsigned char *data, size_t len) -{ - unsigned int i; + for (i = 0; i < count; i++) { + if (array[i].size == size) + continue; - for (i = 0; i < len; i += 2) - swap(data[i], data[i + 1]); -} + if (array[i].size != 0) + wave5_vdi_free_dma_memory(vpu_dev, &array[i]); -static void word_swap(unsigned char *data, size_t len) -{ - u16 *ptr = (u16 *)data; - unsigned int i; - size_t size = len / sizeof(uint16_t); + ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_buf); + if (ret) + return -ENOMEM; + array[i] = vb_buf; + } + + for (i = count; i < MAX_REG_FRAME; i++) + wave5_vdi_free_dma_memory(vpu_dev, &array[i]); - for (i = 0; i < size; i += 2) - swap(ptr[i], ptr[i + 1]); + return 0; } -static void dword_swap(unsigned char *data, size_t len) +void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev) { - u32 *ptr = (u32 *)data; - size_t size = len / sizeof(u32); - unsigned int i; + struct vpu_buf *vb = &vpu_dev->sram_buf; - for (i = 0; i < size; i += 2) - swap(ptr[i], ptr[i + 1]); -} + if (!vpu_dev->sram_pool || !vpu_dev->sram_size) + return; -static void lword_swap(unsigned char *data, size_t len) -{ - u64 *ptr = (u64 *)data; - size_t size = len / sizeof(uint64_t); - unsigned int i; + if (!vb->vaddr) { + vb->size = vpu_dev->sram_size; + vb->vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, vb->size, + &vb->daddr); + if (!vb->vaddr) + vb->size = 0; + } - for (i = 0; i < size; i += 2) - swap(ptr[i], ptr[i + 1]); + dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n", + __func__, &vb->daddr, vb->size, vb->vaddr); } -static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len, - unsigned int endian) +void wave5_vdi_free_sram(struct vpu_device *vpu_dev) { - int changes; - unsigned int sys_endian = VDI_128BIT_BUS_SYSTEM_ENDIAN; - bool byte_change, word_change, dword_change, lword_change; + struct vpu_buf *vb = &vpu_dev->sram_buf; - if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { - dev_err(vpu_dev->dev, "unknown product id: %08x\n", vpu_dev->product_code); + if (!vb->size || !vb->vaddr) return; - } - endian = wave5_vdi_convert_endian(vpu_dev, endian); - sys_endian = wave5_vdi_convert_endian(vpu_dev, sys_endian); - if (endian == sys_endian) - return; + if (vb->vaddr) + gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, + vb->size); - changes = endian ^ sys_endian; - byte_change = changes & 0x01; - word_change = ((changes & 0x02) == 0x02); - dword_change = ((changes & 0x04) == 0x04); - lword_change = ((changes & 0x08) == 0x08); - - if (byte_change) - byte_swap(data, len); - if (word_change) - word_swap(data, len); - if (dword_change) - dword_swap(data, len); - if (lword_change) - lword_swap(data, len); + memset(vb, 0, sizeof(*vb)); } |