Commit 6aa08291 authored by Ivan Bornyakov's avatar Ivan Bornyakov Committed by Hans Verkuil

media: chips-media: wave5: support Wave515 decoder

Add initial support for the Wave515 multi-decoder IP. For now it is only
able to decode HEVC Main/Main10 profile videos into YUV420.

This was tested on FPGA prototype, so wave5_dt_ids[] was not expanded.
Users of the real hardware with Wave515 IP will have to
 * provide firmware specific to their SoC
 * add struct wave5_match_data like this:

	static const struct wave5_match_data platform_name_wave515_data = {
		.flags = WAVE5_IS_DEC,
		.fw_name = "cnm/wave515_platform_name_fw.bin",
		.sram_size = (71 * 1024),
	};

 * add item to wave5_dt_ids[] like this:

	{
		.compatible = "vendor,soc-wave515",
		.data = &platform_name_wave515_data,
	},

 * describe new compatible in
   Documentation/devicetree/bindings/media/cnm,wave521c.yaml
Signed-off-by: default avatarIvan Bornyakov <brnkv.i1@gmail.com>
Signed-off-by: default avatarSebastian Fricke <sebastian.fricke@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent a83d4a68
......@@ -29,7 +29,13 @@ void wave5_cleanup_instance(struct vpu_instance *inst)
{
int i;
if (list_is_singular(&inst->list))
/*
* For Wave515 SRAM memory is allocated at
* wave5_vpu_dec_register_device() and freed at
* wave5_vpu_dec_unregister_device().
*/
if (list_is_singular(&inst->list) &&
inst->dev->product_code != WAVE515_CODE)
wave5_vdi_free_sram(inst->dev);
for (i = 0; i < inst->fbc_buf_count; i++)
......
......@@ -205,6 +205,9 @@ enum query_opt {
#define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C)
#define W5_TEMP_SIZE (W5_REG_BASE + 0x0120)
#define W5_HW_OPTION (W5_REG_BASE + 0x012C)
#define W5_CMD_INIT_NUM_TASK_BUF (W5_REG_BASE + 0x0134)
#define W5_CMD_INIT_ADDR_TASK_BUF0 (W5_REG_BASE + 0x0138)
#define W5_CMD_INIT_TASK_BUF_SIZE (W5_REG_BASE + 0x0178)
#define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180)
/************************************************************************/
......@@ -216,7 +219,9 @@ enum query_opt {
#define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120)
#define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124)
#define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130)
#define W515_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0124)
#define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134)
#define W515_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0128)
#define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138)
#define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C)
#define W5_CMD_ERR_CONCEAL (W5_REG_BASE + 0x0140)
......
......@@ -18,7 +18,11 @@ static int wave5_vdi_allocate_common_memory(struct device *dev)
if (!vpu_dev->common_mem.vaddr) {
int ret;
vpu_dev->common_mem.size = SIZE_COMMON;
if (vpu_dev->product_code == WAVE515_CODE)
vpu_dev->common_mem.size = WAVE515_SIZE_COMMON;
else
vpu_dev->common_mem.size = WAVE521_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");
......
......@@ -1868,7 +1868,12 @@ static int wave5_vpu_open_dec(struct file *filp)
goto cleanup_inst;
}
wave5_vdi_allocate_sram(inst->dev);
/*
* For Wave515 SRAM memory was already allocated
* at wave5_vpu_dec_register_device()
*/
if (inst->dev->product_code != WAVE515_CODE)
wave5_vdi_allocate_sram(inst->dev);
ret = mutex_lock_interruptible(&dev->dev_lock);
if (ret)
......@@ -1908,6 +1913,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev)
struct video_device *vdev_dec;
int ret;
/*
* Secondary AXI setup for Wave515 is done by INIT_VPU command,
* i.e. wave5_vpu_init(), that's why we allocate SRAM memory early.
*/
if (dev->product_code == WAVE515_CODE)
wave5_vdi_allocate_sram(dev);
vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL);
if (!vdev_dec)
return -ENOMEM;
......@@ -1941,6 +1953,13 @@ int wave5_vpu_dec_register_device(struct vpu_device *dev)
void wave5_vpu_dec_unregister_device(struct vpu_device *dev)
{
/*
* Here is a freeing pair for Wave515 SRAM memory allocation
* happened at wave5_vpu_dec_register_device().
*/
if (dev->product_code == WAVE515_CODE)
wave5_vdi_free_sram(dev);
video_unregister_device(dev->video_dev_dec);
if (dev->v4l2_m2m_dec_dev)
v4l2_m2m_release(dev->v4l2_m2m_dec_dev);
......
......@@ -1247,7 +1247,7 @@ static int initialize_sequence(struct vpu_instance *inst)
__func__, initial_info.min_frame_buffer_count,
initial_info.min_src_frame_count);
inst->min_src_buf_count = initial_info.min_src_frame_count +
COMMAND_QUEUE_DEPTH;
WAVE521_COMMAND_QUEUE_DEPTH;
ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
V4L2_CID_MIN_BUFFERS_FOR_OUTPUT);
......
......@@ -63,7 +63,13 @@ static void wave5_vpu_handle_irq(void *dev_id)
if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
if (seq_done & BIT(inst->id)) {
if (dev->product_code == WAVE515_CODE &&
(cmd_done & BIT(inst->id))) {
cmd_done &= ~BIT(inst->id);
wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST,
cmd_done);
complete(&inst->irq_done);
} else if (seq_done & BIT(inst->id)) {
seq_done &= ~BIT(inst->id);
wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO,
seq_done);
......
......@@ -18,6 +18,7 @@
#include "wave5-vdi.h"
enum product_id {
PRODUCT_ID_515,
PRODUCT_ID_521,
PRODUCT_ID_511,
PRODUCT_ID_517,
......
......@@ -8,6 +8,7 @@
#ifndef _VPU_CONFIG_H_
#define _VPU_CONFIG_H_
#define WAVE515_CODE 0x5150
#define WAVE517_CODE 0x5170
#define WAVE537_CODE 0x5370
#define WAVE511_CODE 0x5110
......@@ -21,12 +22,13 @@
((c) == WAVE517_CODE || (c) == WAVE537_CODE || \
(c) == WAVE511_CODE || (c) == WAVE521_CODE || \
(c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \
(c) == WAVE521C_DUAL_CODE); \
(c) == WAVE521C_DUAL_CODE) || (c) == WAVE515_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 WAVE515DEC_WORKBUF_SIZE (2 * 1024 * 1024)
#define MAX_NUM_INSTANCE 32
......@@ -49,17 +51,21 @@
/************************************************************************/
#define VLC_BUF_NUM (2)
#define COMMAND_QUEUE_DEPTH (2)
#define WAVE521_COMMAND_QUEUE_DEPTH (2)
#define WAVE515_COMMAND_QUEUE_DEPTH (4)
#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 WAVE521_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
#define WAVE515_MAX_CODE_BUF_SIZE (1024 * 1024)
#define WAVE5_TEMPBUF_SIZE (1024 * 1024)
#define SIZE_COMMON (WAVE5_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
#define WAVE521_SIZE_COMMON (WAVE521_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
#define WAVE515_ONE_TASKBUF_SIZE (8 * 1024 * 1024)
#define WAVE515_SIZE_COMMON (WAVE515_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE + \
WAVE515_COMMAND_QUEUE_DEPTH * WAVE515_ONE_TASKBUF_SIZE)
//=====4. VPU REPORT MEMORY ======================//
......
......@@ -22,6 +22,12 @@
*/
#define BSOPTION_ENABLE_EXPLICIT_END BIT(0)
#define BSOPTION_HIGHLIGHT_STREAM_END BIT(1)
/*
* When RD_PTR_VALID_FLAG is 0 Wave515 ignores RD_PTR value and starts to
* decode from the access unit end position of the last decoded picture in
* bitstream buffer.
*/
#define BSOPTION_RD_PTR_VALID_FLAG BIT(31)
/*
* Currently the driver only supports hardware with little endian but for source
......
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