Commit 45d1a2b9 authored by Nas Chung's avatar Nas Chung Committed by Hans Verkuil

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: default avatarSebastian Fricke <sebastian.fricke@collabora.com>
Signed-off-by: default avatarNicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: default avatarDafna Hirschfeld <dafna.hirschfeld@collabora.com>
Signed-off-by: default avatarRobert Beckett <bob.beckett@collabora.com>
Signed-off-by: default avatarNas Chung <nas.chung@chipsnmedia.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent 02a8b425
This diff is collapsed.
This diff is collapsed.
// 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));
}
/* 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_
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - product config definitions
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef _VPU_CONFIG_H_
#define _VPU_CONFIG_H_
#define WAVE517_CODE 0x5170
#define WAVE537_CODE 0x5370
#define WAVE511_CODE 0x5110
#define WAVE521_CODE 0x5210
#define WAVE521C_CODE 0x521c
#define WAVE521C_DUAL_CODE 0x521d // wave521 dual core
#define WAVE521E1_CODE 0x5211
#define PRODUCT_CODE_W_SERIES(x) ({ \
int c = x; \
((c) == WAVE517_CODE || (c) == WAVE537_CODE || \
(c) == WAVE511_CODE || (c) == WAVE521_CODE || \
(c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \
(c) == WAVE521C_DUAL_CODE); \
})
#define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024)
#define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC 40K
#define WAVE521DEC_WORKBUF_SIZE (1784 * 1024)
#define MAX_NUM_INSTANCE 32
#define W5_MIN_ENC_PIC_WIDTH 256
#define W5_MIN_ENC_PIC_HEIGHT 128
#define W5_MAX_ENC_PIC_WIDTH 8192
#define W5_MAX_ENC_PIC_HEIGHT 8192
// application specific configuration
#define VPU_ENC_TIMEOUT 60000
#define VPU_DEC_TIMEOUT 60000
// for WAVE encoder
#define USE_SRC_PRP_AXI 0
#define USE_SRC_PRI_AXI 1
#define DEFAULT_SRC_AXI USE_SRC_PRP_AXI
/************************************************************************/
/* VPU COMMON MEMORY */
/************************************************************************/
#define VLC_BUF_NUM (2)
#define COMMAND_QUEUE_DEPTH (2)
#define W5_REMAP_INDEX0 0
#define W5_REMAP_INDEX1 1
#define W5_REMAP_MAX_SIZE (1024 * 1024)
#define WAVE5_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
#define WAVE5_TEMPBUF_OFFSET WAVE5_MAX_CODE_BUF_SIZE
#define WAVE5_TEMPBUF_SIZE (1024 * 1024)
#define SIZE_COMMON (WAVE5_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
//=====4. VPU REPORT MEMORY ======================//
#define WAVE5_UPPER_PROC_AXI_ID 0x0
#define WAVE5_PROC_AXI_ID 0x0
#define WAVE5_PRP_AXI_ID 0x0
#define WAVE5_FBD_Y_AXI_ID 0x0
#define WAVE5_FBC_Y_AXI_ID 0x0
#define WAVE5_FBD_C_AXI_ID 0x0
#define WAVE5_FBC_C_AXI_ID 0x0
#define WAVE5_SEC_AXI_ID 0x0
#define WAVE5_PRI_AXI_ID 0x0
#endif /* _VPU_CONFIG_H_ */
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - wave5 backend definitions
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef __WAVE5_FUNCTION_H__
#define __WAVE5_FUNCTION_H__
#define WAVE5_SUBSAMPLED_ONE_SIZE(_w, _h) (ALIGN((_w) / 4, 16) * ALIGN((_h) / 4, 8))
#define WAVE5_SUBSAMPLED_ONE_SIZE_AVC(_w, _h) (ALIGN((_w) / 4, 32) * ALIGN((_h) / 4, 4))
/*
* Bitstream buffer option: Explicit End
* When set to 1 the VPU assumes that the bitstream has at least one frame and
* will read until the end of the bitstream buffer.
* When set to 0 the VPU will not read the last few bytes.
* This option can be set anytime but cannot be cleared during processing.
* It can be set to force finish decoding even though there is not enough
* bitstream data for a full frame.
*/
#define BSOPTION_ENABLE_EXPLICIT_END BIT(0)
#define BSOPTION_HIGHLIGHT_STREAM_END BIT(1)
/*
* Currently the driver only supports hardware with little endian but for source
* picture format, the bitstream and the report parameter the hardware works
* with the opposite endianness, thus hard-code big endian for the register
* writes
*/
#define PIC_SRC_ENDIANNESS_BIG_ENDIAN 0xf
#define BITSTREAM_ENDIANNESS_BIG_ENDIAN 0xf
#define REPORT_PARAM_ENDIANNESS_BIG_ENDIAN 0xf
#define WTL_RIGHT_JUSTIFIED 0
#define WTL_LEFT_JUSTIFIED 1
#define WTL_PIXEL_8BIT 0
#define WTL_PIXEL_16BIT 1
#define WTL_PIXEL_32BIT 2
/* Mirror & rotation modes of the PRP (pre-processing) module */
#define NONE_ROTATE 0x0
#define ROT_CLOCKWISE_90 0x3
#define ROT_CLOCKWISE_180 0x5
#define ROT_CLOCKWISE_270 0x7
#define MIR_HOR_FLIP 0x11
#define MIR_VER_FLIP 0x9
#define MIR_HOR_VER_FLIP (MIR_HOR_FLIP | MIR_VER_FLIP)
bool wave5_vpu_is_init(struct vpu_device *vpu_dev);
unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev);
int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision);
int wave5_vpu_init(struct device *dev, u8 *fw, size_t size);
int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode);
int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, struct dec_open_param *param);
int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos);
int wave5_vpu_hw_flush_instance(struct vpu_instance *inst);
int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst,
struct frame_buffer *fb_arr, enum tiled_map_type map_type,
unsigned int count);
int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size);
int wave5_vpu_dec_init_seq(struct vpu_instance *inst);
int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info);
int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res);
int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result);
int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res);
int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index);
int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index);
int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags);
dma_addr_t wave5_dec_get_rd_ptr(struct vpu_instance *inst);
int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr);
/***< WAVE5 encoder >******/
int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst,
struct enc_open_param *open_param);
int wave5_vpu_enc_init_seq(struct vpu_instance *inst);
int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info);
int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst,
struct frame_buffer *fb_arr, enum tiled_map_type map_type,
unsigned int count);
int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res);
int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result);
int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res);
int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param);
#endif /* __WAVE5_FUNCTION_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment