-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
media: chips-media: wave5: Add vpuapi layer
Add the vpuapi layer of the wave5 codec driver. This layer is used to configure the hardware according to the parameters. Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com> Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Signed-off-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com> Signed-off-by: Robert Beckett <bob.beckett@collabora.com> Signed-off-by: Nas Chung <nas.chung@chipsnmedia.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
- Loading branch information
Nas Chung
authored and
Hans Verkuil
committed
Nov 16, 2023
1 parent
02a8b42
commit 45d1a2b
Showing
9 changed files
with
5,839 additions
and
0 deletions.
There are no files selected for viewing
2,554 changes: 2,554 additions & 0 deletions
2,554
drivers/media/platform/chips-media/wave5/wave5-hw.c
Large diffs are not rendered by default.
Oops, something went wrong.
732 changes: 732 additions & 0 deletions
732
drivers/media/platform/chips-media/wave5/wave5-regdefine.h
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) | ||
/* | ||
* Wave5 series multi-standard codec IP - low level access functions | ||
* | ||
* Copyright (C) 2021-2023 CHIPS&MEDIA INC | ||
*/ | ||
|
||
#include <linux/bug.h> | ||
#include "wave5-vdi.h" | ||
#include "wave5-vpu.h" | ||
#include "wave5-regdefine.h" | ||
#include <linux/delay.h> | ||
|
||
static int wave5_vdi_allocate_common_memory(struct device *dev) | ||
{ | ||
struct vpu_device *vpu_dev = dev_get_drvdata(dev); | ||
|
||
if (!vpu_dev->common_mem.vaddr) { | ||
int ret; | ||
|
||
vpu_dev->common_mem.size = SIZE_COMMON; | ||
ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem); | ||
if (ret) { | ||
dev_err(dev, "unable to allocate common buffer\n"); | ||
return ret; | ||
} | ||
} | ||
|
||
dev_dbg(dev, "[VDI] common_mem: daddr=%pad size=%zu vaddr=0x%p\n", | ||
&vpu_dev->common_mem.daddr, vpu_dev->common_mem.size, vpu_dev->common_mem.vaddr); | ||
|
||
return 0; | ||
} | ||
|
||
int wave5_vdi_init(struct device *dev) | ||
{ | ||
struct vpu_device *vpu_dev = dev_get_drvdata(dev); | ||
int ret; | ||
|
||
ret = wave5_vdi_allocate_common_memory(dev); | ||
if (ret < 0) { | ||
dev_err(dev, "[VDI] failed to get vpu common buffer from driver\n"); | ||
return ret; | ||
} | ||
|
||
if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { | ||
WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code); | ||
return -EOPNOTSUPP; | ||
} | ||
|
||
/* 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++) | ||
wave5_vdi_write_register(vpu_dev, (i * 4) + 0x100, 0x0); | ||
} | ||
|
||
dev_dbg(dev, "[VDI] driver initialized successfully\n"); | ||
|
||
return 0; | ||
} | ||
|
||
int wave5_vdi_release(struct device *dev) | ||
{ | ||
struct vpu_device *vpu_dev = dev_get_drvdata(dev); | ||
|
||
vpu_dev->vdb_register = NULL; | ||
wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem); | ||
|
||
return 0; | ||
} | ||
|
||
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_read_register(struct vpu_device *vpu_dev, u32 addr) | ||
{ | ||
return readl(vpu_dev->vdb_register + addr); | ||
} | ||
|
||
int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) | ||
{ | ||
if (!vb || !vb->vaddr) { | ||
dev_err(vpu_dev->dev, "%s: unable to clear unmapped buffer\n", __func__); | ||
return -EINVAL; | ||
} | ||
|
||
memset(vb->vaddr, 0, vb->size); | ||
return vb->size; | ||
} | ||
|
||
int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset, | ||
u8 *data, size_t len) | ||
{ | ||
if (!vb || !vb->vaddr) { | ||
dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__); | ||
return -EINVAL; | ||
} | ||
|
||
if (offset > vb->size || len > vb->size || offset + len > vb->size) { | ||
dev_err(vpu_dev->dev, "%s: buffer too small\n", __func__); | ||
return -ENOSPC; | ||
} | ||
|
||
memcpy(vb->vaddr + offset, data, len); | ||
|
||
return len; | ||
} | ||
|
||
int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) | ||
{ | ||
void *vaddr; | ||
dma_addr_t daddr; | ||
|
||
if (!vb->size) { | ||
dev_err(vpu_dev->dev, "%s: requested size==0\n", __func__); | ||
return -EINVAL; | ||
} | ||
|
||
vaddr = dma_alloc_coherent(vpu_dev->dev, vb->size, &daddr, GFP_KERNEL); | ||
if (!vaddr) | ||
return -ENOMEM; | ||
vb->vaddr = vaddr; | ||
vb->daddr = daddr; | ||
|
||
return 0; | ||
} | ||
|
||
int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) | ||
{ | ||
if (vb->size == 0) | ||
return -EINVAL; | ||
|
||
if (!vb->vaddr) | ||
dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__); | ||
else | ||
dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr); | ||
|
||
memset(vb, 0, sizeof(*vb)); | ||
|
||
return 0; | ||
} | ||
|
||
int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count, | ||
size_t size) | ||
{ | ||
struct vpu_buf vb_buf; | ||
int i, ret = 0; | ||
|
||
vb_buf.size = size; | ||
|
||
for (i = 0; i < count; i++) { | ||
if (array[i].size == size) | ||
continue; | ||
|
||
if (array[i].size != 0) | ||
wave5_vdi_free_dma_memory(vpu_dev, &array[i]); | ||
|
||
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]); | ||
|
||
return 0; | ||
} | ||
|
||
void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev) | ||
{ | ||
struct vpu_buf *vb = &vpu_dev->sram_buf; | ||
|
||
if (!vpu_dev->sram_pool || !vpu_dev->sram_size) | ||
return; | ||
|
||
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; | ||
} | ||
|
||
dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n", | ||
__func__, &vb->daddr, vb->size, vb->vaddr); | ||
} | ||
|
||
void wave5_vdi_free_sram(struct vpu_device *vpu_dev) | ||
{ | ||
struct vpu_buf *vb = &vpu_dev->sram_buf; | ||
|
||
if (!vb->size || !vb->vaddr) | ||
return; | ||
|
||
if (vb->vaddr) | ||
gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, | ||
vb->size); | ||
|
||
memset(vb, 0, sizeof(*vb)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ | ||
/* | ||
* Wave5 series multi-standard codec IP - low level access functions | ||
* | ||
* Copyright (C) 2021-2023 CHIPS&MEDIA INC | ||
*/ | ||
|
||
#ifndef _VDI_H_ | ||
#define _VDI_H_ | ||
|
||
#include "wave5-vpuconfig.h" | ||
#include <linux/string.h> | ||
#include <linux/slab.h> | ||
#include <linux/device.h> | ||
|
||
/************************************************************************/ | ||
/* COMMON REGISTERS */ | ||
/************************************************************************/ | ||
#define VPU_PRODUCT_CODE_REGISTER 0x1044 | ||
|
||
/* system register write */ | ||
#define vpu_write_reg(VPU_INST, ADDR, DATA) wave5_vdi_write_register(VPU_INST, ADDR, DATA) | ||
/* system register read */ | ||
#define vpu_read_reg(CORE, ADDR) wave5_vdi_read_register(CORE, ADDR) | ||
|
||
struct vpu_buf { | ||
size_t size; | ||
dma_addr_t daddr; | ||
void *vaddr; | ||
}; | ||
|
||
int wave5_vdi_init(struct device *dev); | ||
int wave5_vdi_release(struct device *dev); //this function may be called only at system off. | ||
|
||
#endif //#ifndef _VDI_H_ |
Oops, something went wrong.