summaryrefslogtreecommitdiff
path: root/drivers/media/platform/chips-media/wave5/wave5-vdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/chips-media/wave5/wave5-vdi.c')
-rw-r--r--drivers/media/platform/chips-media/wave5/wave5-vdi.c151
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));
}