Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
comment "Chips&Media media platform drivers"
source "drivers/media/platform/chips-media/coda/Kconfig"
source "drivers/media/platform/chips-media/wave5/Kconfig"
@@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += coda/
obj-y += wave5/
@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_CODA
tristate "Chips&Media Coda multi-standard codec IP"
depends on V4L_MEM2MEM_DRIVERS
depends on VIDEO_DEV && OF && (ARCH_MXC || COMPILE_TEST)
select SRAM
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
select V4L2_JPEG_HELPER
select V4L2_MEM2MEM_DEV
select GENERIC_ALLOCATOR
help
Coda is a range of video codec IPs that supports
H.264, MPEG-4, and other video formats.
config VIDEO_IMX_VDOA
def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
coda-vpu-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-mpeg2.o coda-mpeg4.o coda-jpeg.o
obj-$(CONFIG_VIDEO_CODA) += coda-vpu.o
obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Coda multi-standard codec IP
*
* Copyright (C) 2014 Philipp Zabel, Pengutronix
*/
#include <linux/bitops.h>
#include "coda.h"
#define XY2_INVERT BIT(7)
#define XY2_ZERO BIT(6)
#define XY2_TB_XOR BIT(5)
#define XY2_XYSEL BIT(4)
#define XY2_Y (1 << 4)
#define XY2_X (0 << 4)
#define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \
(((XY2_##luma_sel) | (luma_bit)) << 8 | \
(XY2_##chroma_sel) | (chroma_bit))
static const u16 xy2ca_zero_map[16] = {
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
};
static const u16 xy2ca_tiled_map[16] = {
XY2(Y, 0, Y, 0),
XY2(Y, 1, Y, 1),
XY2(Y, 2, Y, 2),
XY2(Y, 3, X, 3),
XY2(X, 3, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
XY2(ZERO, 0, ZERO, 0),
};
/*
* RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock
* start offset (macroblock size is 16x16 for luma, 16x8 for chroma).
* Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused.
*/
#define RBC_CA (0 << 4)
#define RBC_BA (1 << 4)
#define RBC_RA (2 << 4)
#define RBC_ZERO (3 << 4)
#define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \
(((RBC_##luma_sel) | (luma_bit)) << 6 | \
(RBC_##chroma_sel) | (chroma_bit))
static const u16 rbc2axi_tiled_map[32] = {
RBC(ZERO, 0, ZERO, 0),
RBC(ZERO, 0, ZERO, 0),
RBC(ZERO, 0, ZERO, 0),
RBC(CA, 0, CA, 0),
RBC(CA, 1, CA, 1),
RBC(CA, 2, CA, 2),
RBC(CA, 3, CA, 3),
RBC(CA, 4, CA, 8),
RBC(CA, 8, CA, 9),
RBC(CA, 9, CA, 10),
RBC(CA, 10, CA, 11),
RBC(CA, 11, CA, 12),
RBC(CA, 12, CA, 13),
RBC(CA, 13, CA, 14),
RBC(CA, 14, CA, 15),
RBC(CA, 15, RA, 0),
RBC(RA, 0, RA, 1),
RBC(RA, 1, RA, 2),
RBC(RA, 2, RA, 3),
RBC(RA, 3, RA, 4),
RBC(RA, 4, RA, 5),
RBC(RA, 5, RA, 6),
RBC(RA, 6, RA, 7),
RBC(RA, 7, RA, 8),
RBC(RA, 8, RA, 9),
RBC(RA, 9, RA, 10),
RBC(RA, 10, RA, 11),
RBC(RA, 11, RA, 12),
RBC(RA, 12, RA, 13),
RBC(RA, 13, RA, 14),
RBC(RA, 14, RA, 15),
RBC(RA, 15, ZERO, 0),
};
void coda_set_gdi_regs(struct coda_ctx *ctx)
{
struct coda_dev *dev = ctx->dev;
const u16 *xy2ca_map;
u32 xy2rbc_config;
int i;
switch (ctx->tiled_map_type) {
case GDI_LINEAR_FRAME_MAP:
default:
xy2ca_map = xy2ca_zero_map;
xy2rbc_config = 0;
break;
case GDI_TILED_FRAME_MB_RASTER_MAP:
xy2ca_map = xy2ca_tiled_map;
xy2rbc_config = CODA9_XY2RBC_TILED_MAP |
CODA9_XY2RBC_CA_INC_HOR |
(16 - 1) << 12 | (8 - 1) << 4;
break;
}
for (i = 0; i < 16; i++)
coda_write(dev, xy2ca_map[i],
CODA9_GDI_XY2_CAS_0 + 4 * i);
for (i = 0; i < 4; i++)
coda_write(dev, XY2(ZERO, 0, ZERO, 0),
CODA9_GDI_XY2_BA_0 + 4 * i);
for (i = 0; i < 16; i++)
coda_write(dev, XY2(ZERO, 0, ZERO, 0),
CODA9_GDI_XY2_RAS_0 + 4 * i);
coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
if (xy2rbc_config) {
for (i = 0; i < 32; i++)
coda_write(dev, rbc2axi_tiled_map[i],
CODA9_GDI_RBC2_AXI_0 + 4 * i);
}
}
@@ -0,0 +1,429 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Coda multi-standard codec IP - H.264 helper functions
*
* Copyright (C) 2012 Vista Silicon S.L.
* Javier Martin, <javier.martin@vista-silicon.com>
* Xavier Duret
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/videodev2.h>
#include "coda.h"
static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
{
u32 val = 0xffffffff;
do {
val = val << 8 | *buf++;
if (buf >= end)
return NULL;
} while (val != 0x00000001);
return buf;
}
int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
{
const u8 *buf = vb2_plane_vaddr(vb, 0);
const u8 *end = buf + vb2_get_plane_payload(vb, 0);
/* Find SPS header */
do {
buf = coda_find_nal_header(buf, end);
if (!buf)
return -EINVAL;
} while ((*buf++ & 0x1f) != 0x7);
ctx->params.h264_profile_idc = buf[0];
ctx->params.h264_level_idc = buf[2];
return 0;
}
int coda_h264_filler_nal(int size, char *p)
{
if (size < 6)
return -EINVAL;
p[0] = 0x00;
p[1] = 0x00;
p[2] = 0x00;
p[3] = 0x01;
p[4] = 0x0c;
memset(p + 5, 0xff, size - 6);
/* Add rbsp stop bit and trailing at the end */
p[size - 1] = 0x80;
return 0;
}
int coda_h264_padding(int size, char *p)
{
int nal_size;
int diff;
diff = size - (size & ~0x7);
if (diff == 0)
return 0;
nal_size = coda_filler_size[diff];
coda_h264_filler_nal(nal_size, p);
return nal_size;
}
int coda_h264_profile(int profile_idc)
{
switch (profile_idc) {
case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
default: return -EINVAL;
}
}
int coda_h264_level(int level_idc)
{
switch (level_idc) {
case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
case 9: return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
default: return -EINVAL;
}
}
struct rbsp {
char *buf;
int size;
int pos;
};
static inline int rbsp_read_bit(struct rbsp *rbsp)
{
int shift = 7 - (rbsp->pos % 8);
int ofs = rbsp->pos++ / 8;
if (ofs >= rbsp->size)
return -EINVAL;
return (rbsp->buf[ofs] >> shift) & 1;
}
static inline int rbsp_write_bit(struct rbsp *rbsp, int bit)
{
int shift = 7 - (rbsp->pos % 8);
int ofs = rbsp->pos++ / 8;
if (ofs >= rbsp->size)
return -EINVAL;
rbsp->buf[ofs] &= ~(1 << shift);
rbsp->buf[ofs] |= bit << shift;
return 0;
}
static inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val)
{
int i, ret;
int tmp = 0;
if (num > 32)
return -EINVAL;
for (i = 0; i < num; i++) {
ret = rbsp_read_bit(rbsp);
if (ret < 0)
return ret;
tmp |= ret << (num - i - 1);
}
if (val)
*val = tmp;
return 0;
}
static int rbsp_write_bits(struct rbsp *rbsp, int num, int value)
{
int ret;
while (num--) {
ret = rbsp_write_bit(rbsp, (value >> num) & 1);
if (ret)
return ret;
}
return 0;
}
static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val)
{
int leading_zero_bits = 0;
unsigned int tmp = 0;
int ret;
while ((ret = rbsp_read_bit(rbsp)) == 0)
leading_zero_bits++;
if (ret < 0)
return ret;
if (leading_zero_bits > 0) {
ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp);
if (ret)
return ret;
}
if (val)
*val = (1 << leading_zero_bits) - 1 + tmp;
return 0;
}
static int rbsp_write_uev(struct rbsp *rbsp, unsigned int value)
{
int i;
int ret;
int tmp = value + 1;
int leading_zero_bits = fls(tmp) - 1;
for (i = 0; i < leading_zero_bits; i++) {
ret = rbsp_write_bit(rbsp, 0);
if (ret)
return ret;
}
return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp);
}
static int rbsp_read_sev(struct rbsp *rbsp, int *val)
{
unsigned int tmp;
int ret;
ret = rbsp_read_uev(rbsp, &tmp);
if (ret)
return ret;
if (val) {
if (tmp & 1)
*val = (tmp + 1) / 2;
else
*val = -(tmp / 2);
}
return 0;
}
/**
* coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS
* @ctx: encoder context
* @width: visible width
* @height: visible height
* @buf: buffer containing h.264 SPS RBSP, starting with NAL header
* @size: modified RBSP size return value
* @max_size: available size in buf
*
* Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the
* given visible width and height.
*/
int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
int *size, int max_size)
{
int profile_idc;
unsigned int pic_order_cnt_type;
int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1;
int frame_mbs_only_flag, frame_cropping_flag;
int vui_parameters_present_flag;
unsigned int crop_right, crop_bottom;
struct rbsp sps;
int pos;
int ret;
if (*size < 8 || *size >= max_size)
return -EINVAL;
sps.buf = buf + 5; /* Skip NAL header */
sps.size = *size - 5;
profile_idc = sps.buf[0];
/* Skip constraint_set[0-5]_flag, reserved_zero_2bits */
/* Skip level_idc */
sps.pos = 24;
/* seq_parameter_set_id */
ret = rbsp_read_uev(&sps, NULL);
if (ret)
return ret;
if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
profile_idc == 138 || profile_idc == 139 || profile_idc == 134 ||
profile_idc == 135) {
dev_err(ctx->fh.vdev->dev_parent,
"%s: Handling profile_idc %d not implemented\n",
__func__, profile_idc);
return -EINVAL;
}
/* log2_max_frame_num_minus4 */
ret = rbsp_read_uev(&sps, NULL);
if (ret)
return ret;
ret = rbsp_read_uev(&sps, &pic_order_cnt_type);
if (ret)
return ret;
if (pic_order_cnt_type == 0) {
/* log2_max_pic_order_cnt_lsb_minus4 */
ret = rbsp_read_uev(&sps, NULL);
if (ret)
return ret;
} else if (pic_order_cnt_type == 1) {
unsigned int i, num_ref_frames_in_pic_order_cnt_cycle;
/* delta_pic_order_always_zero_flag */
ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
/* offset_for_non_ref_pic */
ret = rbsp_read_sev(&sps, NULL);
if (ret)
return ret;
/* offset_for_top_to_bottom_field */
ret = rbsp_read_sev(&sps, NULL);
if (ret)
return ret;
ret = rbsp_read_uev(&sps,
&num_ref_frames_in_pic_order_cnt_cycle);
if (ret)
return ret;
for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
/* offset_for_ref_frame */
ret = rbsp_read_sev(&sps, NULL);
if (ret)
return ret;
}
}
/* max_num_ref_frames */
ret = rbsp_read_uev(&sps, NULL);
if (ret)
return ret;
/* gaps_in_frame_num_value_allowed_flag */
ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1);
if (ret)
return ret;
ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1);
if (ret)
return ret;
frame_mbs_only_flag = ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
if (!frame_mbs_only_flag) {
/* mb_adaptive_frame_field_flag */
ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
}
/* direct_8x8_inference_flag */
ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
/* Mark position of the frame cropping flag */
pos = sps.pos;
frame_cropping_flag = ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
if (frame_cropping_flag) {
unsigned int crop_left, crop_top;
ret = rbsp_read_uev(&sps, &crop_left);
if (ret)
return ret;
ret = rbsp_read_uev(&sps, &crop_right);
if (ret)
return ret;
ret = rbsp_read_uev(&sps, &crop_top);
if (ret)
return ret;
ret = rbsp_read_uev(&sps, &crop_bottom);
if (ret)
return ret;
}
vui_parameters_present_flag = ret = rbsp_read_bit(&sps);
if (ret < 0)
return ret;
if (vui_parameters_present_flag) {
dev_err(ctx->fh.vdev->dev_parent,
"%s: Handling vui_parameters not implemented\n",
__func__);
return -EINVAL;
}
crop_right = round_up(width, 16) - width;
crop_bottom = round_up(height, 16) - height;
crop_right /= 2;
if (frame_mbs_only_flag)
crop_bottom /= 2;
else
crop_bottom /= 4;
sps.size = max_size - 5;
sps.pos = pos;
frame_cropping_flag = 1;
ret = rbsp_write_bit(&sps, frame_cropping_flag);
if (ret)
return ret;
ret = rbsp_write_uev(&sps, 0); /* crop_left */
if (ret)
return ret;
ret = rbsp_write_uev(&sps, crop_right);
if (ret)
return ret;
ret = rbsp_write_uev(&sps, 0); /* crop_top */
if (ret)
return ret;
ret = rbsp_write_uev(&sps, crop_bottom);
if (ret)
return ret;
ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */
if (ret)
return ret;
ret = rbsp_write_bit(&sps, 1);
if (ret)
return ret;
*size = 5 + DIV_ROUND_UP(sps.pos, 8);
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Coda multi-standard codec IP - MPEG-2 helper functions
*
* Copyright (C) 2019 Pengutronix, Philipp Zabel
*/
#include <linux/kernel.h>
#include <linux/videodev2.h>
#include "coda.h"
int coda_mpeg2_profile(int profile_idc)
{
switch (profile_idc) {
case 5:
return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE;
case 4:
return V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN;
case 3:
return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE;
case 2:
return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE;
case 1:
return V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH;
default:
return -EINVAL;
}
}
int coda_mpeg2_level(int level_idc)
{
switch (level_idc) {
case 10:
return V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW;
case 8:
return V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN;
case 6:
return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440;
case 4:
return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH;
default:
return -EINVAL;
}
}
/*
* Check if the buffer starts with the MPEG-2 sequence header (with or without
* quantization matrix) and extension header, for example:
*
* 00 00 01 b3 2d 01 e0 34 08 8b a3 81
* 10 11 11 12 12 12 13 13 13 13 14 14 14 14 14 15
* 15 15 15 15 15 16 16 16 16 16 16 16 17 17 17 17
* 17 17 17 17 18 18 18 19 18 18 18 19 1a 1a 1a 1a
* 19 1b 1b 1b 1b 1b 1c 1c 1c 1c 1e 1e 1e 1f 1f 21
* 00 00 01 b5 14 8a 00 01 00 00
*
* or:
*
* 00 00 01 b3 08 00 40 15 ff ff e0 28
* 00 00 01 b5 14 8a 00 01 00 00
*
* Returns the detected header size in bytes or 0.
*/
u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
{
static const u8 sequence_header_start[4] = { 0x00, 0x00, 0x01, 0xb3 };
static const union {
u8 extension_start[4];
u8 start_code_prefix[3];
} u = { { 0x00, 0x00, 0x01, 0xb5 } };
if (size < 22 ||
memcmp(buf, sequence_header_start, 4) != 0)
return 0;
if ((size == 22 ||
(size >= 25 && memcmp(buf + 22, u.start_code_prefix, 3) == 0)) &&
memcmp(buf + 12, u.extension_start, 4) == 0)
return 22;
if ((size == 86 ||
(size > 89 && memcmp(buf + 86, u.start_code_prefix, 3) == 0)) &&
memcmp(buf + 76, u.extension_start, 4) == 0)
return 86;
return 0;
}
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Coda multi-standard codec IP - MPEG-4 helper functions
*
* Copyright (C) 2019 Pengutronix, Philipp Zabel
*/
#include <linux/kernel.h>
#include <linux/videodev2.h>
#include "coda.h"
int coda_mpeg4_profile(int profile_idc)
{
switch (profile_idc) {
case 0:
return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
case 15:
return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
case 2:
return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE;
case 1:
return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE;
case 11:
return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY;
default:
return -EINVAL;
}
}
int coda_mpeg4_level(int level_idc)
{
switch (level_idc) {
case 0:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0;
case 1:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1;
case 2:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2;
case 3:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3;
case 4:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4;
case 5:
return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5;
default:
return -EINVAL;
}
}
/*
* Check if the buffer starts with the MPEG-4 visual object sequence and visual
* object headers, for example:
*
* 00 00 01 b0 f1
* 00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08
* d4 8d 88 00 f5 04 04 08 14 30 3f
*
* Returns the detected header size in bytes or 0.
*/
u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
{
static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 };
static const union {
u8 vo_start[4];
u8 start_code_prefix[3];
} u = { { 0x00, 0x00, 0x01, 0xb5 } };
if (size < 30 ||
memcmp(buf, vos_start, 4) != 0 ||
memcmp(buf + 5, u.vo_start, 4) != 0)
return 0;
if (size == 30 ||
(size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0))
return 30;
if (size == 31 ||
(size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0))
return 31;
if (size == 32 ||
(size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0))
return 32;
return 0;
}
@@ -0,0 +1,403 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Coda multi-standard codec IP
*
* Copyright (C) 2012 Vista Silicon S.L.
* Javier Martin, <javier.martin@vista-silicon.com>
* Xavier Duret
* Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
*/
#ifndef __CODA_H__
#define __CODA_H__
#include <linux/debugfs.h>
#include <linux/idr.h>
#include <linux/irqreturn.h>
#include <linux/mutex.h>
#include <linux/kfifo.h>
#include <linux/videodev2.h>
#include <linux/ratelimit.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/videobuf2-v4l2.h>
#include "coda_regs.h"
#define CODA_MAX_FRAMEBUFFERS 19
#define FMO_SLICE_SAVE_BUF_SIZE (32)
/*
* This control allows applications to read the per-stream
* (i.e. per-context) Macroblocks Error Count. This value
* is CODA specific.
*/
#define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0)
enum {
V4L2_M2M_SRC = 0,
V4L2_M2M_DST = 1,
};
enum coda_inst_type {
CODA_INST_ENCODER,
CODA_INST_DECODER,
};
enum coda_product {
CODA_DX6 = 0xf001,
CODA_HX4 = 0xf00a,
CODA_7541 = 0xf012,
CODA_960 = 0xf020,
};
struct coda_video_device;
struct coda_devtype {
char *firmware[3];
enum coda_product product;
const struct coda_codec *codecs;
unsigned int num_codecs;
const struct coda_video_device **vdevs;
unsigned int num_vdevs;
size_t workbuf_size;
size_t tempbuf_size;
size_t iram_size;
};
struct coda_aux_buf {
void *vaddr;
dma_addr_t paddr;
u32 size;
struct debugfs_blob_wrapper blob;
struct dentry *dentry;
};
struct coda_dev {
struct v4l2_device v4l2_dev;
struct video_device vfd[6];
struct device *dev;
const struct coda_devtype *devtype;
int firmware;
struct vdoa_data *vdoa;
void __iomem *regs_base;
struct clk *clk_per;
struct clk *clk_ahb;
struct reset_control *rstc;
struct coda_aux_buf codebuf;
struct coda_aux_buf tempbuf;
struct coda_aux_buf workbuf;
struct gen_pool *iram_pool;
struct coda_aux_buf iram;
struct mutex dev_mutex;
struct mutex coda_mutex;
struct workqueue_struct *workqueue;
struct v4l2_m2m_dev *m2m_dev;
struct ida ida;
struct dentry *debugfs_root;
struct ratelimit_state mb_err_rs;
};
struct coda_codec {
u32 mode;
u32 src_fourcc;
u32 dst_fourcc;
u32 max_w;
u32 max_h;
};
struct coda_huff_tab;
struct coda_params {
u8 rot_mode;
u8 h264_intra_qp;
u8 h264_inter_qp;
u8 h264_min_qp;
u8 h264_max_qp;
u8 h264_disable_deblocking_filter_idc;
s8 h264_slice_alpha_c0_offset_div2;
s8 h264_slice_beta_offset_div2;
bool h264_constrained_intra_pred_flag;
s8 h264_chroma_qp_index_offset;
u8 h264_profile_idc;
u8 h264_level_idc;
u8 mpeg2_profile_idc;
u8 mpeg2_level_idc;
u8 mpeg4_intra_qp;
u8 mpeg4_inter_qp;
u8 gop_size;
int intra_refresh;
enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling;
u8 jpeg_quality;
u8 jpeg_restart_interval;
u8 *jpeg_qmat_tab[3];
int jpeg_qmat_index[3];
int jpeg_huff_dc_index[3];
int jpeg_huff_ac_index[3];
u32 *jpeg_huff_data;
struct coda_huff_tab *jpeg_huff_tab;
int codec_mode;
int codec_mode_aux;
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
u32 framerate;
u16 bitrate;
u16 vbv_delay;
u32 vbv_size;
u32 slice_max_bits;
u32 slice_max_mb;
bool force_ipicture;
bool gop_size_changed;
bool bitrate_changed;
bool framerate_changed;
bool h264_intra_qp_changed;
bool intra_refresh_changed;
bool slice_mode_changed;
bool frame_rc_enable;
bool mb_rc_enable;
};
struct coda_buffer_meta {
struct list_head list;
u32 sequence;
struct v4l2_timecode timecode;
u64 timestamp;
unsigned int start;
unsigned int end;
bool last;
};
/* Per-queue, driver-specific private data */
struct coda_q_data {
unsigned int width;
unsigned int height;
unsigned int bytesperline;
unsigned int sizeimage;
unsigned int fourcc;
struct v4l2_rect rect;
};
struct coda_iram_info {
u32 axi_sram_use;
phys_addr_t buf_bit_use;
phys_addr_t buf_ip_ac_dc_use;
phys_addr_t buf_dbk_y_use;
phys_addr_t buf_dbk_c_use;
phys_addr_t buf_ovl_use;
phys_addr_t buf_btp_use;
phys_addr_t search_ram_paddr;
int search_ram_size;
int remaining;
phys_addr_t next_paddr;
};
#define GDI_LINEAR_FRAME_MAP 0
#define GDI_TILED_FRAME_MB_RASTER_MAP 1
struct coda_ctx;
struct coda_context_ops {
int (*queue_init)(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq);
int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb);
int (*start_streaming)(struct coda_ctx *ctx);
int (*prepare_run)(struct coda_ctx *ctx);
void (*finish_run)(struct coda_ctx *ctx);
void (*run_timeout)(struct coda_ctx *ctx);
void (*seq_init_work)(struct work_struct *work);
void (*seq_end_work)(struct work_struct *work);
void (*release)(struct coda_ctx *ctx);
};
struct coda_internal_frame {
struct coda_aux_buf buf;
struct coda_buffer_meta meta;
u32 type;
u32 error;
};
struct coda_ctx {
struct coda_dev *dev;
struct mutex buffer_mutex;
struct work_struct pic_run_work;
struct work_struct seq_init_work;
struct work_struct seq_end_work;
struct completion completion;
const struct coda_video_device *cvd;
const struct coda_context_ops *ops;
int aborting;
int initialized;
int streamon_out;
int streamon_cap;
u32 qsequence;
u32 osequence;
u32 sequence_offset;
struct coda_q_data q_data[2];
enum coda_inst_type inst_type;
const struct coda_codec *codec;
enum v4l2_colorspace colorspace;
enum v4l2_xfer_func xfer_func;
enum v4l2_ycbcr_encoding ycbcr_enc;
enum v4l2_quantization quantization;
struct coda_params params;
struct v4l2_ctrl_handler ctrls;
struct v4l2_ctrl *h264_profile_ctrl;
struct v4l2_ctrl *h264_level_ctrl;
struct v4l2_ctrl *mpeg2_profile_ctrl;
struct v4l2_ctrl *mpeg2_level_ctrl;
struct v4l2_ctrl *mpeg4_profile_ctrl;
struct v4l2_ctrl *mpeg4_level_ctrl;
struct v4l2_ctrl *mb_err_cnt_ctrl;
struct v4l2_fh fh;
int gopcounter;
int runcounter;
int jpeg_ecs_offset;
char vpu_header[3][64];
int vpu_header_size[3];
struct kfifo bitstream_fifo;
struct mutex bitstream_mutex;
struct coda_aux_buf bitstream;
bool hold;
struct coda_aux_buf parabuf;
struct coda_aux_buf psbuf;
struct coda_aux_buf slicebuf;
struct coda_internal_frame internal_frames[CODA_MAX_FRAMEBUFFERS];
struct list_head buffer_meta_list;
spinlock_t buffer_meta_lock;
int num_metas;
unsigned int first_frame_sequence;
struct coda_aux_buf workbuf;
int num_internal_frames;
int idx;
int reg_idx;
struct coda_iram_info iram_info;
int tiled_map_type;
u32 bit_stream_param;
u32 frm_dis_flg;
u32 frame_mem_ctrl;
u32 para_change;
int display_idx;
struct dentry *debugfs_entry;
bool use_bit;
bool use_vdoa;
struct vdoa_ctx *vdoa;
/*
* wakeup mutex used to serialize encoder stop command and finish_run,
* ensures that finish_run always either flags the last returned buffer
* or wakes up the capture queue to signal EOS afterwards.
*/
struct mutex wakeup_mutex;
};
extern int coda_debug;
#define coda_dbg(level, ctx, fmt, arg...) \
do { \
if (coda_debug >= (level)) \
v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \
"%u: " fmt, (ctx)->idx, ##arg); \
} while (0)
void coda_write(struct coda_dev *dev, u32 data, u32 reg);
unsigned int coda_read(struct coda_dev *dev, u32 reg);
void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
struct vb2_v4l2_buffer *buf, unsigned int reg_y);
int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
size_t size, const char *name, struct dentry *parent);
void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf);
int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq);
int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq);
int coda_hw_reset(struct coda_ctx *ctx);
void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list);
void coda_set_gdi_regs(struct coda_ctx *ctx);
static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx,
enum v4l2_buf_type type)
{
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
return &(ctx->q_data[V4L2_M2M_SRC]);
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
return &(ctx->q_data[V4L2_M2M_DST]);
default:
return NULL;
}
}
const char *coda_product_name(int product);
int coda_check_firmware(struct coda_dev *dev);
static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
{
return kfifo_len(&ctx->bitstream_fifo);
}
/*
* The bitstream prefetcher needs to read at least 2 256 byte periods past
* the desired bitstream position for all data to reach the decoder.
*/
static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx,
unsigned int pos)
{
return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512;
}
bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos);
int coda_bitstream_flush(struct coda_ctx *ctx);
void coda_bit_stream_end_flag(struct coda_ctx *ctx);
void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
enum vb2_buffer_state state);
int coda_h264_filler_nal(int size, char *p);
int coda_h264_padding(int size, char *p);
int coda_h264_profile(int profile_idc);
int coda_h264_level(int level_idc);
int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
int *size, int max_size);
int coda_mpeg2_profile(int profile_idc);
int coda_mpeg2_level(int level_idc);
u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
int coda_mpeg4_profile(int profile_idc);
int coda_mpeg4_level(int level_idc);
u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
u8 level_idc);
static inline int coda_jpeg_scale(int src, int dst)
{
return (dst <= src / 8) ? 3 :
(dst <= src / 4) ? 2 :
(dst <= src / 2) ? 1 : 0;
}
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
int coda_jpeg_write_tables(struct coda_ctx *ctx);
void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
extern const struct coda_context_ops coda_bit_encode_ops;
extern const struct coda_context_ops coda_bit_decode_ops;
extern const struct coda_context_ops coda9_jpeg_encode_ops;
extern const struct coda_context_ops coda9_jpeg_decode_ops;
irqreturn_t coda_irq_handler(int irq, void *data);
irqreturn_t coda9_jpeg_irq_handler(int irq, void *data);
#endif /* __CODA_H__ */
@@ -0,0 +1,563 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* linux/drivers/media/platform/chips-media/coda_regs.h
*
* Copyright (C) 2012 Vista Silicon SL
* Javier Martin <javier.martin@vista-silicon.com>
* Xavier Duret
*/
#ifndef _REGS_CODA_H_
#define _REGS_CODA_H_
/* HW registers */
#define CODA_REG_BIT_CODE_RUN 0x000
#define CODA_REG_RUN_ENABLE (1 << 0)
#define CODA_REG_BIT_CODE_DOWN 0x004
#define CODA_DOWN_ADDRESS_SET(x) (((x) & 0xffff) << 16)
#define CODA_DOWN_DATA_SET(x) ((x) & 0xffff)
#define CODA_REG_BIT_HOST_IN_REQ 0x008
#define CODA_REG_BIT_INT_CLEAR 0x00c
#define CODA_REG_BIT_INT_CLEAR_SET 0x1
#define CODA_REG_BIT_INT_STATUS 0x010
#define CODA_REG_BIT_CODE_RESET 0x014
#define CODA_REG_RESET_ENABLE (1 << 0)
#define CODA_REG_BIT_CUR_PC 0x018
#define CODA9_REG_BIT_SW_RESET 0x024
#define CODA9_SW_RESET_BPU_CORE 0x008
#define CODA9_SW_RESET_BPU_BUS 0x010
#define CODA9_SW_RESET_VCE_CORE 0x020
#define CODA9_SW_RESET_VCE_BUS 0x040
#define CODA9_SW_RESET_GDI_CORE 0x080
#define CODA9_SW_RESET_GDI_BUS 0x100
#define CODA9_REG_BIT_SW_RESET_STATUS 0x034
/* Static SW registers */
#define CODA_REG_BIT_CODE_BUF_ADDR 0x100
#define CODA_REG_BIT_WORK_BUF_ADDR 0x104
#define CODA_REG_BIT_PARA_BUF_ADDR 0x108
#define CODA_REG_BIT_STREAM_CTRL 0x10c
#define CODA7_STREAM_BUF_PIC_RESET (1 << 4)
#define CODADX6_STREAM_BUF_PIC_RESET (1 << 3)
#define CODA7_STREAM_BUF_PIC_FLUSH (1 << 3)
#define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2)
#define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5)
#define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4)
#define CODADX6_STREAM_CHKDIS_OFFSET (1 << 1)
#define CODA7_STREAM_SEL_64BITS_ENDIAN (1 << 1)
#define CODA_STREAM_ENDIAN_SELECT (1 << 0)
#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110
#define CODA9_FRAME_ENABLE_BWB (1 << 12)
#define CODA9_FRAME_TILED2LINEAR (1 << 11)
#define CODA_FRAME_CHROMA_INTERLEAVE (1 << 2)
#define CODA_IMAGE_ENDIAN_SELECT (1 << 0)
#define CODA_REG_BIT_BIT_STREAM_PARAM 0x114
#define CODA_BIT_STREAM_END_FLAG (1 << 2)
#define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0)
#define CODA_REG_BIT_TEMP_BUF_ADDR 0x118
#define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x))
#define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x))
#define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x))
#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140
#define CODA7_REG_BIT_AXI_SRAM_USE 0x140
#define CODA9_USE_HOST_BTP_ENABLE (1 << 13)
#define CODA9_USE_HOST_OVL_ENABLE (1 << 12)
#define CODA7_USE_HOST_ME_ENABLE (1 << 11)
#define CODA9_USE_HOST_DBK_ENABLE (3 << 10)
#define CODA7_USE_HOST_OVL_ENABLE (1 << 10)
#define CODA7_USE_HOST_DBK_ENABLE (1 << 9)
#define CODA9_USE_HOST_IP_ENABLE (1 << 9)
#define CODA7_USE_HOST_IP_ENABLE (1 << 8)
#define CODA9_USE_HOST_BIT_ENABLE (1 << 8)
#define CODA7_USE_HOST_BIT_ENABLE (1 << 7)
#define CODA9_USE_BTP_ENABLE (1 << 5)
#define CODA7_USE_ME_ENABLE (1 << 4)
#define CODA9_USE_OVL_ENABLE (1 << 4)
#define CODA7_USE_OVL_ENABLE (1 << 3)
#define CODA9_USE_DBK_ENABLE (3 << 2)
#define CODA7_USE_DBK_ENABLE (1 << 2)
#define CODA7_USE_IP_ENABLE (1 << 1)
#define CODA7_USE_BIT_ENABLE (1 << 0)
#define CODA_REG_BIT_BUSY 0x160
#define CODA_REG_BIT_BUSY_FLAG 1
#define CODA_REG_BIT_RUN_COMMAND 0x164
#define CODA_COMMAND_SEQ_INIT 1
#define CODA_COMMAND_SEQ_END 2
#define CODA_COMMAND_PIC_RUN 3
#define CODA_COMMAND_SET_FRAME_BUF 4
#define CODA_COMMAND_ENCODE_HEADER 5
#define CODA_COMMAND_ENC_PARA_SET 6
#define CODA_COMMAND_DEC_PARA_SET 7
#define CODA_COMMAND_DEC_BUF_FLUSH 8
#define CODA_COMMAND_RC_CHANGE_PARAMETER 9
#define CODA_COMMAND_FIRMWARE_GET 0xf
#define CODA_REG_BIT_RUN_INDEX 0x168
#define CODA_INDEX_SET(x) ((x) & 0x3)
#define CODA_REG_BIT_RUN_COD_STD 0x16c
#define CODADX6_MODE_DECODE_MP4 0
#define CODADX6_MODE_ENCODE_MP4 1
#define CODADX6_MODE_DECODE_H264 2
#define CODADX6_MODE_ENCODE_H264 3
#define CODA7_MODE_DECODE_H264 0
#define CODA7_MODE_DECODE_VC1 1
#define CODA7_MODE_DECODE_MP2 2
#define CODA7_MODE_DECODE_MP4 3
#define CODA7_MODE_DECODE_DV3 3
#define CODA7_MODE_DECODE_RV 4
#define CODA7_MODE_DECODE_MJPG 5
#define CODA7_MODE_ENCODE_H264 8
#define CODA7_MODE_ENCODE_MP4 11
#define CODA7_MODE_ENCODE_MJPG 13
#define CODA9_MODE_DECODE_H264 0
#define CODA9_MODE_DECODE_VC1 1
#define CODA9_MODE_DECODE_MP2 2
#define CODA9_MODE_DECODE_MP4 3
#define CODA9_MODE_DECODE_DV3 3
#define CODA9_MODE_DECODE_RV 4
#define CODA9_MODE_DECODE_AVS 5
#define CODA9_MODE_DECODE_MJPG 6
#define CODA9_MODE_DECODE_VPX 7
#define CODA9_MODE_ENCODE_H264 8
#define CODA9_MODE_ENCODE_MP4 11
#define CODA9_MODE_ENCODE_MJPG 13
#define CODA_MODE_INVALID 0xffff
#define CODA_REG_BIT_INT_ENABLE 0x170
#define CODA_INT_INTERRUPT_ENABLE (1 << 3)
#define CODA_REG_BIT_INT_REASON 0x174
#define CODA7_REG_BIT_RUN_AUX_STD 0x178
#define CODA_MP4_AUX_MPEG4 0
#define CODA_MP4_AUX_DIVX3 1
#define CODA_VPX_AUX_THO 0
#define CODA_VPX_AUX_VP6 1
#define CODA_VPX_AUX_VP8 2
#define CODA_H264_AUX_AVC 0
#define CODA_H264_AUX_MVC 1
/*
* Commands' mailbox:
* registers with offsets in the range 0x180-0x1d0
* have different meaning depending on the command being
* issued.
*/
/* Decoder Sequence Initialization */
#define CODA_CMD_DEC_SEQ_BB_START 0x180
#define CODA_CMD_DEC_SEQ_BB_SIZE 0x184
#define CODA_CMD_DEC_SEQ_OPTION 0x188
#define CODA_NO_INT_ENABLE (1 << 10)
#define CODA_REORDER_ENABLE (1 << 1)
#define CODADX6_QP_REPORT (1 << 0)
#define CODA7_MP4_DEBLK_ENABLE (1 << 0)
#define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c
#define CODA_CMD_DEC_SEQ_START_BYTE 0x190
#define CODA_CMD_DEC_SEQ_PS_BB_START 0x194
#define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198
#define CODA_CMD_DEC_SEQ_JPG_THUMB_EN 0x19c
#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c
#define CODA_MP4_CLASS_MPEG4 0
#define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c
#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0
#define CODA7_RET_DEC_SEQ_ASPECT 0x1b0
#define CODA9_RET_DEC_SEQ_BITRATE 0x1b4
#define CODA_RET_DEC_SEQ_SUCCESS 0x1c0
#define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */
#define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4
#define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8
#define CODA9_RET_DEC_SEQ_ASPECT 0x1c8
#define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc
#define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0
#define CODA_RET_DEC_SEQ_INFO 0x1d4
#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8
#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc
#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0
#define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0
#define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4
#define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8
#define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4
#define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8
#define CODA7_RET_DEC_SEQ_HEADER_REPORT 0x1ec
/* Decoder Picture Run */
#define CODA_CMD_DEC_PIC_ROT_MODE 0x180
#define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184
#define CODA9_CMD_DEC_PIC_ROT_INDEX 0x184
#define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188
#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y 0x188
#define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c
#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB 0x18c
#define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190
#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR 0x190
#define CODA9_CMD_DEC_PIC_ROT_STRIDE 0x1b8
#define CODA_CMD_DEC_PIC_OPTION 0x194
#define CODA_PRE_SCAN_EN (1 << 0)
#define CODA_PRE_SCAN_MODE_DECODE (0 << 1)
#define CODA_PRE_SCAN_MODE_RETURN (1 << 1)
#define CODA_IFRAME_SEARCH_EN (1 << 2)
#define CODA_SKIP_FRAME_MODE (0x3 << 3)
#define CODA_CMD_DEC_PIC_SKIP_NUM 0x198
#define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c
#define CODA_CMD_DEC_PIC_BB_START 0x1a0
#define CODA_CMD_DEC_PIC_START_BYTE 0x1a4
#define CODA_RET_DEC_PIC_SIZE 0x1bc
#define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0
#define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4
#define CODA_RET_DEC_PIC_ERR_MB 0x1c8
#define CODA_RET_DEC_PIC_TYPE 0x1cc
#define CODA_PIC_TYPE_MASK 0x7
#define CODA_PIC_TYPE_MASK_VC1 0x3f
#define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3)
#define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6)
#define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16)
#define CODA7_PIC_TYPE_INTERLACED (1 << 18)
#define CODA_RET_DEC_PIC_POST 0x1d0
#define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0
#define CODA_RET_DEC_PIC_OPTION 0x1d4
#define CODA_RET_DEC_PIC_SUCCESS 0x1d8
#define CODA_RET_DEC_PIC_CUR_IDX 0x1dc
#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0
#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4
#define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec
#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT 0x1e8
#define CODA9_RET_DEC_PIC_ASPECT 0x1f0
#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO 0x1f0
#define CODA9_RET_DEC_PIC_FRATE_NR 0x1f4
#define CODA9_RET_DEC_PIC_FRATE_DR 0x1f8
/* Encoder Sequence Initialization */
#define CODA_CMD_ENC_SEQ_BB_START 0x180
#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184
#define CODA_CMD_ENC_SEQ_OPTION 0x188
#define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9
#define CODA9_OPTION_MVC_PREFIX_NAL_OFFSET 9
#define CODA7_OPTION_GAMMA_OFFSET 8
#define CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET 8
#define CODA7_OPTION_RCQPMAX_OFFSET 7
#define CODA9_OPTION_GAMMA_OFFSET 7
#define CODADX6_OPTION_GAMMA_OFFSET 7
#define CODA7_OPTION_RCQPMIN_OFFSET 6
#define CODA9_OPTION_RCQPMAX_OFFSET 6
#define CODA_OPTION_LIMITQP_OFFSET 6
#define CODA_OPTION_RCINTRAQP_OFFSET 5
#define CODA_OPTION_FMO_OFFSET 4
#define CODA9_OPTION_MVC_INTERVIEW_OFFSET 4
#define CODA_OPTION_AVC_AUD_OFFSET 2
#define CODA_OPTION_SLICEREPORT_OFFSET 1
#define CODA_CMD_ENC_SEQ_COD_STD 0x18c
#define CODA_STD_MPEG4 0
#define CODA9_STD_H264 0
#define CODA_STD_H263 1
#define CODA_STD_H264 2
#define CODA9_STD_MPEG4 3
#define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190
#define CODA7_PICWIDTH_OFFSET 16
#define CODA7_PICWIDTH_MASK 0xffff
#define CODADX6_PICWIDTH_OFFSET 10
#define CODADX6_PICWIDTH_MASK 0x3ff
#define CODA_PICHEIGHT_OFFSET 0
#define CODADX6_PICHEIGHT_MASK 0x3ff
#define CODA7_PICHEIGHT_MASK 0xffff
#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194
#define CODA_FRATE_RES_OFFSET 0
#define CODA_FRATE_RES_MASK 0xffff
#define CODA_FRATE_DIV_OFFSET 16
#define CODA_FRATE_DIV_MASK 0xffff
#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198
#define CODA_MP4PARAM_VERID_OFFSET 6
#define CODA_MP4PARAM_VERID_MASK 0x01
#define CODA_MP4PARAM_INTRADCVLCTHR_OFFSET 2
#define CODA_MP4PARAM_INTRADCVLCTHR_MASK 0x07
#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET 1
#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK 0x01
#define CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET 0
#define CODA_MP4PARAM_DATAPARTITIONENABLE_MASK 0x01
#define CODA_CMD_ENC_SEQ_263_PARA 0x19c
#define CODA_263PARAM_ANNEXJENABLE_OFFSET 2
#define CODA_263PARAM_ANNEXJENABLE_MASK 0x01
#define CODA_263PARAM_ANNEXKENABLE_OFFSET 1
#define CODA_263PARAM_ANNEXKENABLE_MASK 0x01
#define CODA_263PARAM_ANNEXTENABLE_OFFSET 0
#define CODA_263PARAM_ANNEXTENABLE_MASK 0x01
#define CODA_CMD_ENC_SEQ_264_PARA 0x1a0
#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET 12
#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK 0x0f
#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET 8
#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK 0x0f
#define CODA_264PARAM_DISABLEDEBLK_OFFSET 6
#define CODA_264PARAM_DISABLEDEBLK_MASK 0x03
#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET 5
#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK 0x01
#define CODA_264PARAM_CHROMAQPOFFSET_OFFSET 0
#define CODA_264PARAM_CHROMAQPOFFSET_MASK 0x1f
#define CODA_CMD_ENC_SEQ_SLICE_MODE 0x1a4
#define CODA_SLICING_SIZE_OFFSET 2
#define CODA_SLICING_SIZE_MASK 0x3fffffff
#define CODA_SLICING_UNIT_OFFSET 1
#define CODA_SLICING_UNIT_MASK 0x01
#define CODA_SLICING_MODE_OFFSET 0
#define CODA_SLICING_MODE_MASK 0x01
#define CODA_CMD_ENC_SEQ_GOP_SIZE 0x1a8
#define CODA_GOP_SIZE_OFFSET 0
#define CODA_GOP_SIZE_MASK 0x3f
#define CODA_CMD_ENC_SEQ_RC_PARA 0x1ac
#define CODA_RATECONTROL_AUTOSKIP_OFFSET 31
#define CODA_RATECONTROL_AUTOSKIP_MASK 0x01
#define CODA_RATECONTROL_INITIALDELAY_OFFSET 16
#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7fff
#define CODA_RATECONTROL_BITRATE_OFFSET 1
#define CODA_RATECONTROL_BITRATE_MASK 0x7fff
#define CODA_RATECONTROL_ENABLE_OFFSET 0
#define CODA_RATECONTROL_ENABLE_MASK 0x01
#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE 0x1b0
#define CODA_CMD_ENC_SEQ_INTRA_REFRESH 0x1b4
#define CODADX6_CMD_ENC_SEQ_FMO 0x1b8
#define CODA_FMOPARAM_TYPE_OFFSET 4
#define CODA_FMOPARAM_TYPE_MASK 1
#define CODA_FMOPARAM_SLICENUM_OFFSET 0
#define CODA_FMOPARAM_SLICENUM_MASK 0x0f
#define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc
#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8
#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc
#define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4
#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX 0x1c8
#define CODA_QPMIN_OFFSET 8
#define CODA_QPMIN_MASK 0x3f
#define CODA_QPMAX_OFFSET 0
#define CODA_QPMAX_MASK 0x3f
#define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc
#define CODA_GAMMA_OFFSET 0
#define CODA_GAMMA_MASK 0xffff
#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE 0x1d0
#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT 0x1d4
#define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8
#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0
#define CODA_CMD_ENC_SEQ_JPG_PARA 0x198
#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL 0x19C
#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN 0x1a0
#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE 0x1a4
#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET 0x1a8
/* Encoder Parameter Change */
#define CODA_CMD_ENC_PARAM_CHANGE_ENABLE 0x180
#define CODA_PARAM_CHANGE_RC_GOP BIT(0)
#define CODA_PARAM_CHANGE_RC_INTRA_QP BIT(1)
#define CODA_PARAM_CHANGE_RC_BITRATE BIT(2)
#define CODA_PARAM_CHANGE_RC_FRAME_RATE BIT(3)
#define CODA_PARAM_CHANGE_INTRA_MB_NUM BIT(4)
#define CODA_PARAM_CHANGE_SLICE_MODE BIT(5)
#define CODA_PARAM_CHANGE_HEC_MODE BIT(6)
#define CODA_CMD_ENC_PARAM_RC_GOP 0x184
#define CODA_CMD_ENC_PARAM_RC_INTRA_QP 0x188
#define CODA_CMD_ENC_PARAM_RC_BITRATE 0x18c
#define CODA_CMD_ENC_PARAM_RC_FRAME_RATE 0x190
#define CODA_CMD_ENC_PARAM_INTRA_MB_NUM 0x194
#define CODA_CMD_ENC_PARAM_SLICE_MODE 0x198
#define CODA_CMD_ENC_PARAM_HEC_MODE 0x19c
#define CODA_RET_ENC_PARAM_CHANGE_SUCCESS 0x1c0
/* Encoder Picture Run */
#define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180
#define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184
#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC 0x1a4
#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y 0x1a8
#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB 0x1ac
#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR 0x1b0
#define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180
#define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184
#define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188
#define CODA_CMD_ENC_PIC_QS 0x18c
#define CODA_CMD_ENC_PIC_ROT_MODE 0x190
#define CODA_ROT_MIR_ENABLE (1 << 4)
#define CODA_ROT_0 (0x0 << 0)
#define CODA_ROT_90 (0x1 << 0)
#define CODA_ROT_180 (0x2 << 0)
#define CODA_ROT_270 (0x3 << 0)
#define CODA_MIR_NONE (0x0 << 2)
#define CODA_MIR_VER (0x1 << 2)
#define CODA_MIR_HOR (0x2 << 2)
#define CODA_MIR_VER_HOR (0x3 << 2)
#define CODA_CMD_ENC_PIC_OPTION 0x194
#define CODA_FORCE_IPICTURE BIT(1)
#define CODA_REPORT_MB_INFO BIT(3)
#define CODA_REPORT_MV_INFO BIT(4)
#define CODA_REPORT_SLICE_INFO BIT(5)
#define CODA_CMD_ENC_PIC_BB_START 0x198
#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c
#define CODA_RET_ENC_FRAME_NUM 0x1c0
#define CODA_RET_ENC_PIC_TYPE 0x1c4
#define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8
#define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc
#define CODA_RET_ENC_PIC_FLAG 0x1d0
#define CODA_RET_ENC_PIC_SUCCESS 0x1d8
/* Set Frame Buffer */
#define CODA_CMD_SET_FRAME_BUF_NUM 0x180
#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184
#define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188
#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c
#define CODA9_CMD_SET_FRAME_SUBSAMP_A 0x188
#define CODA9_CMD_SET_FRAME_SUBSAMP_B 0x18c
#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190
#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194
#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198
#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c
#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0
#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4
#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR 0x1a4
#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8
#define CODA9_CMD_SET_FRAME_CACHE_SIZE 0x1a8
#define CODA9_CMD_SET_FRAME_CACHE_CONFIG 0x1ac
#define CODA9_CACHE_BYPASS_OFFSET 28
#define CODA9_CACHE_DUALCONF_OFFSET 26
#define CODA9_CACHE_PAGEMERGE_OFFSET 24
#define CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET 16
#define CODA9_CACHE_CB_BUFFER_SIZE_OFFSET 8
#define CODA9_CACHE_CR_BUFFER_SIZE_OFFSET 0
#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC 0x1b0
#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC 0x1b4
#define CODA9_CMD_SET_FRAME_DP_BUF_BASE 0x1b0
#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE 0x1b4
#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE 0x1b8
#define CODA9_CMD_SET_FRAME_DELAY 0x1bc
/* Encoder Header */
#define CODA_CMD_ENC_HEADER_CODE 0x180
#define CODA_GAMMA_OFFSET 0
#define CODA_HEADER_H264_SPS 0
#define CODA_HEADER_H264_PPS 1
#define CODA_HEADER_MP4V_VOL 0
#define CODA_HEADER_MP4V_VOS 1
#define CODA_HEADER_MP4V_VIS 2
#define CODA9_HEADER_FRAME_CROP (1 << 3)
#define CODA_CMD_ENC_HEADER_BB_START 0x184
#define CODA_CMD_ENC_HEADER_BB_SIZE 0x188
#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H 0x18c
#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V 0x190
/* Get Version */
#define CODA_CMD_FIRMWARE_VERNUM 0x1c0
#define CODA_FIRMWARE_PRODUCT(x) (((x) >> 16) & 0xffff)
#define CODA_FIRMWARE_MAJOR(x) (((x) >> 12) & 0x0f)
#define CODA_FIRMWARE_MINOR(x) (((x) >> 8) & 0x0f)
#define CODA_FIRMWARE_RELEASE(x) ((x) & 0xff)
#define CODA_FIRMWARE_VERNUM(product, major, minor, release) \
((product) << 16 | ((major) << 12) | \
((minor) << 8) | (release))
#define CODA9_CMD_FIRMWARE_CODE_REV 0x1c4
#define CODA9_GDMA_BASE 0x1000
#define CODA9_GDI_CONTROL (CODA9_GDMA_BASE + 0x034)
#define CODA9_GDI_PIC_INIT_HOST (CODA9_GDMA_BASE + 0x038)
#define CODA9_GDI_STATUS (CODA9_GDMA_BASE + 0x080)
#define CODA9_GDI_WPROT_ERR_CLR (CODA9_GDMA_BASE + 0x0a0)
#define CODA9_GDI_WPROT_RGN_EN (CODA9_GDMA_BASE + 0x0ac)
#define CODA9_GDI_BUS_CTRL (CODA9_GDMA_BASE + 0x0f0)
#define CODA9_GDI_BUS_STATUS (CODA9_GDMA_BASE + 0x0f4)
#define CODA9_GDI_INFO_CONTROL (CODA9_GDMA_BASE + 0x400)
#define CODA9_GDI_INFO_PIC_SIZE (CODA9_GDMA_BASE + 0x404)
#define CODA9_GDI_INFO_BASE_Y (CODA9_GDMA_BASE + 0x408)
#define CODA9_GDI_INFO_BASE_CB (CODA9_GDMA_BASE + 0x40c)
#define CODA9_GDI_INFO_BASE_CR (CODA9_GDMA_BASE + 0x410)
#define CODA9_GDI_XY2_CAS_0 (CODA9_GDMA_BASE + 0x800)
#define CODA9_GDI_XY2_CAS_F (CODA9_GDMA_BASE + 0x83c)
#define CODA9_GDI_XY2_BA_0 (CODA9_GDMA_BASE + 0x840)
#define CODA9_GDI_XY2_BA_1 (CODA9_GDMA_BASE + 0x844)
#define CODA9_GDI_XY2_BA_2 (CODA9_GDMA_BASE + 0x848)
#define CODA9_GDI_XY2_BA_3 (CODA9_GDMA_BASE + 0x84c)
#define CODA9_GDI_XY2_RAS_0 (CODA9_GDMA_BASE + 0x850)
#define CODA9_GDI_XY2_RAS_F (CODA9_GDMA_BASE + 0x88c)
#define CODA9_GDI_XY2_RBC_CONFIG (CODA9_GDMA_BASE + 0x890)
#define CODA9_XY2RBC_SEPARATE_MAP BIT(19)
#define CODA9_XY2RBC_TOP_BOT_SPLIT BIT(18)
#define CODA9_XY2RBC_TILED_MAP BIT(17)
#define CODA9_XY2RBC_CA_INC_HOR BIT(16)
#define CODA9_GDI_RBC2_AXI_0 (CODA9_GDMA_BASE + 0x8a0)
#define CODA9_GDI_RBC2_AXI_1F (CODA9_GDMA_BASE + 0x91c)
#define CODA9_GDI_TILEDBUF_BASE (CODA9_GDMA_BASE + 0x920)
#define CODA9_JPEG_BASE 0x3000
#define CODA9_REG_JPEG_PIC_START (CODA9_JPEG_BASE + 0x000)
#define CODA9_REG_JPEG_PIC_STATUS (CODA9_JPEG_BASE + 0x004)
#define CODA9_JPEG_STATUS_OVERFLOW BIT(3)
#define CODA9_JPEG_STATUS_BBC_INT BIT(2)
#define CODA9_JPEG_STATUS_ERROR BIT(1)
#define CODA9_JPEG_STATUS_DONE BIT(0)
#define CODA9_REG_JPEG_PIC_ERRMB (CODA9_JPEG_BASE + 0x008)
#define CODA9_JPEG_ERRMB_RESTART_IDX_MASK (0xf << 24)
#define CODA9_JPEG_ERRMB_MCU_POS_X_MASK (0xfff << 12)
#define CODA9_JPEG_ERRMB_MCU_POS_Y_MASK 0xfff
#define CODA9_REG_JPEG_PIC_CTRL (CODA9_JPEG_BASE + 0x010)
#define CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN BIT(6)
#define CODA9_JPEG_PIC_CTRL_TC_DIRECTION BIT(4)
#define CODA9_JPEG_PIC_CTRL_ENCODER_EN BIT(3)
#define CODA9_REG_JPEG_PIC_SIZE (CODA9_JPEG_BASE + 0x014)
#define CODA9_REG_JPEG_MCU_INFO (CODA9_JPEG_BASE + 0x018)
#define CODA9_JPEG_MCU_BLOCK_NUM_OFFSET 16
#define CODA9_JPEG_COMP_NUM_OFFSET 12
#define CODA9_JPEG_COMP0_INFO_OFFSET 8
#define CODA9_JPEG_COMP1_INFO_OFFSET 4
#define CODA9_JPEG_COMP2_INFO_OFFSET 0
#define CODA9_REG_JPEG_ROT_INFO (CODA9_JPEG_BASE + 0x01c)
#define CODA9_JPEG_ROT_MIR_ENABLE BIT(4)
#define CODA9_JPEG_ROT_MIR_MODE_MASK 0xf
#define CODA9_REG_JPEG_SCL_INFO (CODA9_JPEG_BASE + 0x020)
#define CODA9_JPEG_SCL_ENABLE BIT(4)
#define CODA9_JPEG_SCL_HOR_MODE_MASK (0x3 << 2)
#define CODA9_JPEG_SCL_VER_MODE_MASK (0x3 << 0)
#define CODA9_REG_JPEG_IF_INFO (CODA9_JPEG_BASE + 0x024)
#define CODA9_JPEG_SENS_IF_CLR BIT(1)
#define CODA9_JPEG_DISP_IF_CLR BIT(0)
#define CODA9_REG_JPEG_OP_INFO (CODA9_JPEG_BASE + 0x02c)
#define CODA9_JPEG_BUS_REQ_NUM_OFFSET 0
#define CODA9_JPEG_BUS_REQ_NUM_MASK 0x7
#define CODA9_REG_JPEG_DPB_CONFIG (CODA9_JPEG_BASE + 0x030)
#define CODA9_REG_JPEG_DPB_BASE00 (CODA9_JPEG_BASE + 0x040)
#define CODA9_REG_JPEG_HUFF_CTRL (CODA9_JPEG_BASE + 0x080)
#define CODA9_REG_JPEG_HUFF_ADDR (CODA9_JPEG_BASE + 0x084)
#define CODA9_REG_JPEG_HUFF_DATA (CODA9_JPEG_BASE + 0x088)
#define CODA9_REG_JPEG_QMAT_CTRL (CODA9_JPEG_BASE + 0x090)
#define CODA9_REG_JPEG_QMAT_ADDR (CODA9_JPEG_BASE + 0x094)
#define CODA9_REG_JPEG_QMAT_DATA (CODA9_JPEG_BASE + 0x098)
#define CODA9_REG_JPEG_RST_INTVAL (CODA9_JPEG_BASE + 0x0b0)
#define CODA9_REG_JPEG_RST_INDEX (CODA9_JPEG_BASE + 0x0b4)
#define CODA9_REG_JPEG_RST_COUNT (CODA9_JPEG_BASE + 0x0b8)
#define CODA9_REG_JPEG_DPCM_DIFF_Y (CODA9_JPEG_BASE + 0x0f0)
#define CODA9_REG_JPEG_DPCM_DIFF_CB (CODA9_JPEG_BASE + 0x0f4)
#define CODA9_REG_JPEG_DPCM_DIFF_CR (CODA9_JPEG_BASE + 0x0f8)
#define CODA9_REG_JPEG_GBU_CTRL (CODA9_JPEG_BASE + 0x100)
#define CODA9_REG_JPEG_GBU_BT_PTR (CODA9_JPEG_BASE + 0x110)
#define CODA9_REG_JPEG_GBU_WD_PTR (CODA9_JPEG_BASE + 0x114)
#define CODA9_REG_JPEG_GBU_TT_CNT (CODA9_JPEG_BASE + 0x118)
#define CODA9_REG_JPEG_GBU_BBSR (CODA9_JPEG_BASE + 0x140)
#define CODA9_REG_JPEG_GBU_BBER (CODA9_JPEG_BASE + 0x144)
#define CODA9_REG_JPEG_GBU_BBIR (CODA9_JPEG_BASE + 0x148)
#define CODA9_REG_JPEG_GBU_BBHR (CODA9_JPEG_BASE + 0x14c)
#define CODA9_REG_JPEG_GBU_BCNT (CODA9_JPEG_BASE + 0x158)
#define CODA9_REG_JPEG_GBU_FF_RPTR (CODA9_JPEG_BASE + 0x160)
#define CODA9_REG_JPEG_GBU_FF_WPTR (CODA9_JPEG_BASE + 0x164)
#define CODA9_REG_JPEG_BBC_END_ADDR (CODA9_JPEG_BASE + 0x208)
#define CODA9_REG_JPEG_BBC_WR_PTR (CODA9_JPEG_BASE + 0x20c)
#define CODA9_REG_JPEG_BBC_RD_PTR (CODA9_JPEG_BASE + 0x210)
#define CODA9_REG_JPEG_BBC_EXT_ADDR (CODA9_JPEG_BASE + 0x214)
#define CODA9_REG_JPEG_BBC_INT_ADDR (CODA9_JPEG_BASE + 0x218)
#define CODA9_REG_JPEG_BBC_DATA_CNT (CODA9_JPEG_BASE + 0x21c)
#define CODA9_REG_JPEG_BBC_COMMAND (CODA9_JPEG_BASE + 0x220)
#define CODA9_REG_JPEG_BBC_BUSY (CODA9_JPEG_BASE + 0x224)
#define CODA9_REG_JPEG_BBC_CTRL (CODA9_JPEG_BASE + 0x228)
#define CODA9_REG_JPEG_BBC_CUR_POS (CODA9_JPEG_BASE + 0x22c)
#define CODA9_REG_JPEG_BBC_BAS_ADDR (CODA9_JPEG_BASE + 0x230)
#define CODA9_REG_JPEG_BBC_STRM_CTRL (CODA9_JPEG_BASE + 0x234)
#define CODA9_REG_JPEG_BBC_FLUSH_CMD (CODA9_JPEG_BASE + 0x238)
#endif
@@ -0,0 +1,345 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* i.MX6 Video Data Order Adapter (VDOA)
*
* Copyright (C) 2014 Philipp Zabel
* Copyright (C) 2016 Pengutronix, Michael Tretter <kernel@pengutronix.de>
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/slab.h>
#include "imx-vdoa.h"
#define VDOA_NAME "imx-vdoa"
#define VDOAC 0x00
#define VDOASRR 0x04
#define VDOAIE 0x08
#define VDOAIST 0x0c
#define VDOAFP 0x10
#define VDOAIEBA00 0x14
#define VDOAIEBA01 0x18
#define VDOAIEBA02 0x1c
#define VDOAIEBA10 0x20
#define VDOAIEBA11 0x24
#define VDOAIEBA12 0x28
#define VDOASL 0x2c
#define VDOAIUBO 0x30
#define VDOAVEBA0 0x34
#define VDOAVEBA1 0x38
#define VDOAVEBA2 0x3c
#define VDOAVUBO 0x40
#define VDOASR 0x44
#define VDOAC_ISEL BIT(6)
#define VDOAC_PFS BIT(5)
#define VDOAC_SO BIT(4)
#define VDOAC_SYNC BIT(3)
#define VDOAC_NF BIT(2)
#define VDOAC_BNDM_MASK 0x3
#define VDOAC_BAND_HEIGHT_8 0x0
#define VDOAC_BAND_HEIGHT_16 0x1
#define VDOAC_BAND_HEIGHT_32 0x2
#define VDOASRR_START BIT(1)
#define VDOASRR_SWRST BIT(0)
#define VDOAIE_EITERR BIT(1)
#define VDOAIE_EIEOT BIT(0)
#define VDOAIST_TERR BIT(1)
#define VDOAIST_EOT BIT(0)
#define VDOAFP_FH_MASK (0x1fff << 16)
#define VDOAFP_FW_MASK (0x3fff)
#define VDOASL_VSLY_MASK (0x3fff << 16)
#define VDOASL_ISLY_MASK (0x7fff)
#define VDOASR_ERRW BIT(4)
#define VDOASR_EOB BIT(3)
#define VDOASR_CURRENT_FRAME (0x3 << 1)
#define VDOASR_CURRENT_BUFFER BIT(1)
enum {
V4L2_M2M_SRC = 0,
V4L2_M2M_DST = 1,
};
struct vdoa_data {
struct vdoa_ctx *curr_ctx;
struct device *dev;
struct clk *vdoa_clk;
void __iomem *regs;
};
struct vdoa_q_data {
unsigned int width;
unsigned int height;
unsigned int bytesperline;
unsigned int sizeimage;
u32 pixelformat;
};
struct vdoa_ctx {
struct vdoa_data *vdoa;
struct completion completion;
struct vdoa_q_data q_data[2];
unsigned int submitted_job;
unsigned int completed_job;
};
static irqreturn_t vdoa_irq_handler(int irq, void *data)
{
struct vdoa_data *vdoa = data;
struct vdoa_ctx *curr_ctx;
u32 val;
/* Disable interrupts */
writel(0, vdoa->regs + VDOAIE);
curr_ctx = vdoa->curr_ctx;
if (!curr_ctx) {
dev_warn(vdoa->dev,
"Instance released before the end of transaction\n");
return IRQ_HANDLED;
}
val = readl(vdoa->regs + VDOAIST);
writel(val, vdoa->regs + VDOAIST);
if (val & VDOAIST_TERR) {
val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW;
dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read");
} else if (!(val & VDOAIST_EOT)) {
dev_warn(vdoa->dev, "Spurious interrupt\n");
}
curr_ctx->completed_job++;
complete(&curr_ctx->completion);
return IRQ_HANDLED;
}
int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
{
struct vdoa_data *vdoa = ctx->vdoa;
if (ctx->submitted_job == ctx->completed_job)
return 0;
if (!wait_for_completion_timeout(&ctx->completion,
msecs_to_jiffies(300))) {
dev_err(vdoa->dev,
"Timeout waiting for transfer result\n");
return -ETIMEDOUT;
}
return 0;
}
EXPORT_SYMBOL(vdoa_wait_for_completion);
void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src)
{
struct vdoa_q_data *src_q_data, *dst_q_data;
struct vdoa_data *vdoa = ctx->vdoa;
u32 val;
if (vdoa->curr_ctx)
vdoa_wait_for_completion(vdoa->curr_ctx);
vdoa->curr_ctx = ctx;
reinit_completion(&ctx->completion);
ctx->submitted_job++;
src_q_data = &ctx->q_data[V4L2_M2M_SRC];
dst_q_data = &ctx->q_data[V4L2_M2M_DST];
/* Progressive, no sync, 1 frame per run */
if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV)
val = VDOAC_PFS;
else
val = 0;
writel(val, vdoa->regs + VDOAC);
writel(dst_q_data->height << 16 | dst_q_data->width,
vdoa->regs + VDOAFP);
val = dst;
writel(val, vdoa->regs + VDOAIEBA00);
writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline,
vdoa->regs + VDOASL);
if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 ||
dst_q_data->pixelformat == V4L2_PIX_FMT_NV21)
val = dst_q_data->bytesperline * dst_q_data->height;
else
val = 0;
writel(val, vdoa->regs + VDOAIUBO);
val = src;
writel(val, vdoa->regs + VDOAVEBA0);
val = round_up(src_q_data->bytesperline * src_q_data->height, 4096);
writel(val, vdoa->regs + VDOAVUBO);
/* Enable interrupts and start transfer */
writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE);
writel(VDOASRR_START, vdoa->regs + VDOASRR);
}
EXPORT_SYMBOL(vdoa_device_run);
struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
{
struct vdoa_ctx *ctx;
int err;
ctx = kzalloc_obj(*ctx);
if (!ctx)
return NULL;
err = clk_prepare_enable(vdoa->vdoa_clk);
if (err) {
kfree(ctx);
return NULL;
}
init_completion(&ctx->completion);
ctx->vdoa = vdoa;
return ctx;
}
EXPORT_SYMBOL(vdoa_context_create);
void vdoa_context_destroy(struct vdoa_ctx *ctx)
{
struct vdoa_data *vdoa = ctx->vdoa;
if (vdoa->curr_ctx == ctx) {
vdoa_wait_for_completion(vdoa->curr_ctx);
vdoa->curr_ctx = NULL;
}
clk_disable_unprepare(vdoa->vdoa_clk);
kfree(ctx);
}
EXPORT_SYMBOL(vdoa_context_destroy);
int vdoa_context_configure(struct vdoa_ctx *ctx,
unsigned int width, unsigned int height,
u32 pixelformat)
{
struct vdoa_q_data *src_q_data;
struct vdoa_q_data *dst_q_data;
if (width < 16 || width > 8192 || width % 16 != 0 ||
height < 16 || height > 4096 || height % 16 != 0)
return -EINVAL;
if (pixelformat != V4L2_PIX_FMT_YUYV &&
pixelformat != V4L2_PIX_FMT_NV12)
return -EINVAL;
/* If no context is passed, only check if the format is valid */
if (!ctx)
return 0;
src_q_data = &ctx->q_data[V4L2_M2M_SRC];
dst_q_data = &ctx->q_data[V4L2_M2M_DST];
src_q_data->width = width;
src_q_data->height = height;
src_q_data->bytesperline = width;
src_q_data->sizeimage =
round_up(src_q_data->bytesperline * height, 4096) +
src_q_data->bytesperline * height / 2;
dst_q_data->width = width;
dst_q_data->height = height;
dst_q_data->pixelformat = pixelformat;
switch (pixelformat) {
case V4L2_PIX_FMT_YUYV:
dst_q_data->bytesperline = width * 2;
dst_q_data->sizeimage = dst_q_data->bytesperline * height;
break;
case V4L2_PIX_FMT_NV12:
default:
dst_q_data->bytesperline = width;
dst_q_data->sizeimage =
dst_q_data->bytesperline * height * 3 / 2;
break;
}
return 0;
}
EXPORT_SYMBOL(vdoa_context_configure);
static int vdoa_probe(struct platform_device *pdev)
{
struct vdoa_data *vdoa;
int ret;
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "DMA enable failed\n");
return ret;
}
vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
if (!vdoa)
return -ENOMEM;
vdoa->dev = &pdev->dev;
vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL);
if (IS_ERR(vdoa->vdoa_clk)) {
dev_err(vdoa->dev, "Failed to get clock\n");
return PTR_ERR(vdoa->vdoa_clk);
}
vdoa->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(vdoa->regs))
return PTR_ERR(vdoa->regs);
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
ret = devm_request_threaded_irq(&pdev->dev, ret, NULL,
vdoa_irq_handler, IRQF_ONESHOT,
"vdoa", vdoa);
if (ret < 0) {
dev_err(vdoa->dev, "Failed to get irq\n");
return ret;
}
platform_set_drvdata(pdev, vdoa);
return 0;
}
static const struct of_device_id vdoa_dt_ids[] = {
{ .compatible = "fsl,imx6q-vdoa" },
{}
};
MODULE_DEVICE_TABLE(of, vdoa_dt_ids);
static struct platform_driver vdoa_driver = {
.probe = vdoa_probe,
.driver = {
.name = VDOA_NAME,
.of_match_table = vdoa_dt_ids,
},
};
module_platform_driver(vdoa_driver);
MODULE_DESCRIPTION("Video Data Order Adapter");
MODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
MODULE_ALIAS("platform:imx-vdoa");
MODULE_LICENSE("GPL");
@@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2016 Pengutronix
*/
#ifndef IMX_VDOA_H
#define IMX_VDOA_H
struct vdoa_data;
struct vdoa_ctx;
#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE)
struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa);
int vdoa_context_configure(struct vdoa_ctx *ctx,
unsigned int width, unsigned int height,
u32 pixelformat);
void vdoa_context_destroy(struct vdoa_ctx *ctx);
void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src);
int vdoa_wait_for_completion(struct vdoa_ctx *ctx);
#else
static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
{
return NULL;
}
static inline int vdoa_context_configure(struct vdoa_ctx *ctx,
unsigned int width,
unsigned int height,
u32 pixelformat)
{
return 0;
}
static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { };
static inline void vdoa_device_run(struct vdoa_ctx *ctx,
dma_addr_t dst, dma_addr_t src) { };
static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
{
return 0;
};
#endif
#endif /* IMX_VDOA_H */
@@ -0,0 +1,175 @@
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM coda
#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
#define __CODA_TRACE_H__
#include <linux/tracepoint.h>
#include <media/videobuf2-v4l2.h>
#include "coda.h"
TRACE_EVENT(coda_bit_run,
TP_PROTO(struct coda_ctx *ctx, int cmd),
TP_ARGS(ctx, cmd),
TP_STRUCT__entry(
__field(int, minor)
__field(int, ctx)
__field(int, cmd)
),
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
__entry->ctx = ctx->idx;
__entry->cmd = cmd;
),
TP_printk("minor = %d, ctx = %d, cmd = %d",
__entry->minor, __entry->ctx, __entry->cmd)
);
TRACE_EVENT(coda_bit_done,
TP_PROTO(struct coda_ctx *ctx),
TP_ARGS(ctx),
TP_STRUCT__entry(
__field(int, minor)
__field(int, ctx)
),
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
__entry->ctx = ctx->idx;
),
TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx)
);
DECLARE_EVENT_CLASS(coda_buf_class,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf),
TP_STRUCT__entry(
__field(int, minor)
__field(int, index)
__field(int, ctx)
),
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
__entry->index = buf->vb2_buf.index;
__entry->ctx = ctx->idx;
),
TP_printk("minor = %d, index = %d, ctx = %d",
__entry->minor, __entry->index, __entry->ctx)
);
DEFINE_EVENT(coda_buf_class, coda_enc_pic_run,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
DEFINE_EVENT(coda_buf_class, coda_enc_pic_done,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
DECLARE_EVENT_CLASS(coda_buf_meta_class,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta),
TP_STRUCT__entry(
__field(int, minor)
__field(int, index)
__field(int, start)
__field(int, end)
__field(int, ctx)
),
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
__entry->index = buf->vb2_buf.index;
__entry->start = meta->start & ctx->bitstream_fifo.kfifo.mask;
__entry->end = meta->end & ctx->bitstream_fifo.kfifo.mask;
__entry->ctx = ctx->idx;
),
TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d",
__entry->minor, __entry->index, __entry->start, __entry->end,
__entry->ctx)
);
DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta)
);
DECLARE_EVENT_CLASS(coda_meta_class,
TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
TP_ARGS(ctx, meta),
TP_STRUCT__entry(
__field(int, minor)
__field(int, start)
__field(int, end)
__field(int, ctx)
),
TP_fast_assign(
__entry->minor = ctx->fh.vdev->minor;
__entry->start = meta ? (meta->start &
ctx->bitstream_fifo.kfifo.mask) : 0;
__entry->end = meta ? (meta->end &
ctx->bitstream_fifo.kfifo.mask) : 0;
__entry->ctx = ctx->idx;
),
TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d",
__entry->minor, __entry->start, __entry->end, __entry->ctx)
);
DEFINE_EVENT(coda_meta_class, coda_dec_pic_run,
TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
TP_ARGS(ctx, meta)
);
DEFINE_EVENT(coda_meta_class, coda_dec_pic_done,
TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
TP_ARGS(ctx, meta)
);
DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
struct coda_buffer_meta *meta),
TP_ARGS(ctx, buf, meta)
);
DEFINE_EVENT(coda_buf_class, coda_jpeg_run,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
DEFINE_EVENT(coda_buf_class, coda_jpeg_done,
TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
TP_ARGS(ctx, buf)
);
#endif /* __CODA_TRACE_H__ */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH ../../drivers/media/platform/chips-media/coda
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
/* This part must be outside protection */
#include <trace/define_trace.h>
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_WAVE_VPU
tristate "Chips&Media Wave Codec Driver"
depends on V4L_MEM2MEM_DRIVERS
depends on VIDEO_DEV && OF
depends on ARCH_K3 || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
select V4L2_MEM2MEM_DEV
select GENERIC_ALLOCATOR
help
Chips&Media stateful encoder and decoder driver.
The driver supports HEVC and H264 formats.
To compile this driver as modules, choose M here: the
modules will be called wave5.
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_WAVE_VPU) += wave5.o
wave5-objs += wave5-hw.o \
wave5-vpuapi.o \
wave5-vdi.o \
wave5-vpu-dec.o \
wave5-vpu.o \
wave5-vpu-enc.o \
wave5-helper.o
@@ -0,0 +1,271 @@
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* Wave5 series multi-standard codec IP - decoder interface
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#include "wave5-helper.h"
#define DEFAULT_BS_SIZE(width, height) ((width) * (height) / 8 * 3)
const char *state_to_str(enum vpu_instance_state state)
{
switch (state) {
case VPU_INST_STATE_NONE:
return "NONE";
case VPU_INST_STATE_OPEN:
return "OPEN";
case VPU_INST_STATE_INIT_SEQ:
return "INIT_SEQ";
case VPU_INST_STATE_PIC_RUN:
return "PIC_RUN";
case VPU_INST_STATE_STOP:
return "STOP";
default:
return "UNKNOWN";
}
}
int wave5_kfifo_alloc(struct vpu_instance *inst)
{
return kfifo_alloc(&inst->irq_status, 16 * sizeof(int), GFP_KERNEL);
}
void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp)
{
int i;
/*
* 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++)
wave5_vpu_dec_reset_framebuffer(inst, i);
wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf);
v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl);
if (inst->v4l2_fh.vdev) {
v4l2_fh_del(&inst->v4l2_fh, filp);
v4l2_fh_exit(&inst->v4l2_fh);
}
kfifo_free(&inst->irq_status);
ida_free(&inst->dev->inst_ida, inst->id);
kfree(inst->codec_info);
kfree(inst);
}
int wave5_vpu_release_device(struct file *filp,
int (*close_func)(struct vpu_instance *inst, u32 *fail_res),
char *name)
{
struct vpu_instance *inst = file_to_vpu_inst(filp);
int ret = 0;
unsigned long flags;
/*
* To prevent Null reference exception, the existing irq handler were
* separated to two modules.
* One is to queue interrupt reason into the irq handler,
* the other is irq_thread to call the wave5_vpu_dec_finish_decode
* to get decoded frame.
* The list of instances should be protected between all flow of the
* decoding process, but to protect the list in the irq_handler, spin lock
* should be used, and mutex should be used in the irq_thread because spin lock
* is not able to be used because mutex is already being used
* in the wave5_vpu_dec_finish_decode.
* So the spin lock and mutex were used to protect the list in the release function.
*/
ret = mutex_lock_interruptible(&inst->dev->irq_lock);
if (ret)
return ret;
spin_lock_irqsave(&inst->dev->irq_spinlock, flags);
list_del_init(&inst->list);
spin_unlock_irqrestore(&inst->dev->irq_spinlock, flags);
mutex_unlock(&inst->dev->irq_lock);
v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx);
if (inst->state != VPU_INST_STATE_NONE) {
u32 fail_res;
ret = close_func(inst, &fail_res);
if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) {
dev_err(inst->dev->dev, "%s close failed, device is still running\n",
name);
return -EBUSY;
}
if (ret && ret != -EIO) {
dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret);
return ret;
}
}
wave5_cleanup_instance(inst, filp);
return ret;
}
int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq,
const struct vb2_ops *ops)
{
struct vpu_instance *inst = priv;
int ret;
src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->ops = ops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->buf_struct_size = sizeof(struct vpu_src_buffer);
src_vq->drv_priv = inst;
src_vq->lock = &inst->dev->dev_lock;
src_vq->dev = inst->dev->v4l2_dev.dev;
ret = vb2_queue_init(src_vq);
if (ret)
return ret;
dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
dst_vq->mem_ops = &vb2_dma_contig_memops;
dst_vq->ops = ops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
dst_vq->buf_struct_size = sizeof(struct vpu_src_buffer);
dst_vq->drv_priv = inst;
dst_vq->lock = &inst->dev->dev_lock;
dst_vq->dev = inst->dev->v4l2_dev.dev;
ret = vb2_queue_init(dst_vq);
if (ret)
return ret;
return 0;
}
int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
{
struct vpu_instance *inst = wave5_to_vpu_inst(fh);
bool is_decoder = inst->type == VPU_INST_TYPE_DEC;
dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__,
is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags);
switch (sub->type) {
case V4L2_EVENT_EOS:
return v4l2_event_subscribe(fh, sub, 0, NULL);
case V4L2_EVENT_SOURCE_CHANGE:
if (is_decoder)
return v4l2_src_change_event_subscribe(fh, sub);
return -EINVAL;
case V4L2_EVENT_CTRL:
return v4l2_ctrl_subscribe_event(fh, sub);
default:
return -EINVAL;
}
}
int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
{
struct vpu_instance *inst = file_to_vpu_inst(file);
int i;
f->fmt.pix_mp.width = inst->src_fmt.width;
f->fmt.pix_mp.height = inst->src_fmt.height;
f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
f->fmt.pix_mp.field = inst->src_fmt.field;
f->fmt.pix_mp.flags = inst->src_fmt.flags;
f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline;
f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage;
}
f->fmt.pix_mp.colorspace = inst->colorspace;
f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
f->fmt.pix_mp.quantization = inst->quantization;
f->fmt.pix_mp.xfer_func = inst->xfer_func;
return 0;
}
const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt,
const struct vpu_format fmt_list[MAX_FMTS])
{
unsigned int index;
for (index = 0; index < MAX_FMTS; index++) {
if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt)
return &fmt_list[index];
}
return NULL;
}
const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
const struct vpu_format fmt_list[MAX_FMTS])
{
if (idx >= MAX_FMTS)
return NULL;
if (!fmt_list[idx].v4l2_pix_fmt)
return NULL;
return &fmt_list[idx];
}
enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type)
{
switch (v4l2_pix_fmt) {
case V4L2_PIX_FMT_H264:
return type == VPU_INST_TYPE_DEC ? W_AVC_DEC : W_AVC_ENC;
case V4L2_PIX_FMT_HEVC:
return type == VPU_INST_TYPE_DEC ? W_HEVC_DEC : W_HEVC_ENC;
default:
return STD_UNKNOWN;
}
}
void wave5_return_bufs(struct vb2_queue *q, u32 state)
{
struct vpu_instance *inst = vb2_get_drv_priv(q);
struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx;
struct v4l2_ctrl_handler v4l2_ctrl_hdl = inst->v4l2_ctrl_hdl;
struct vb2_v4l2_buffer *vbuf;
for (;;) {
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
vbuf = v4l2_m2m_src_buf_remove(m2m_ctx);
else
vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx);
if (!vbuf)
return;
v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &v4l2_ctrl_hdl);
v4l2_m2m_buf_done(vbuf, state);
}
}
void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp,
int pix_fmt_type,
unsigned int width,
unsigned int height,
const struct v4l2_frmsize_stepwise *frmsize)
{
v4l2_apply_frmsize_constraints(&width, &height, frmsize);
if (pix_fmt_type == VPU_FMT_TYPE_CODEC) {
pix_mp->width = width;
pix_mp->height = height;
pix_mp->num_planes = 1;
pix_mp->plane_fmt[0].bytesperline = 0;
pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_BS_SIZE(width, height),
pix_mp->plane_fmt[0].sizeimage);
} else {
v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, width, height);
}
pix_mp->flags = 0;
pix_mp->field = V4L2_FIELD_NONE;
}
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - basic types
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef __WAVE_HELPER_H__
#define __WAVE_HELPER_H__
#include "wave5-vpu.h"
#define FMT_TYPES 2
#define MAX_FMTS 16
const char *state_to_str(enum vpu_instance_state state);
void wave5_cleanup_instance(struct vpu_instance *inst, struct file *filp);
int wave5_vpu_release_device(struct file *filp,
int (*close_func)(struct vpu_instance *inst, u32 *fail_res),
char *name);
int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq,
const struct vb2_ops *ops);
int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub);
int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f);
const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt,
const struct vpu_format fmt_list[MAX_FMTS]);
const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
const struct vpu_format fmt_list[MAX_FMTS]);
enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type);
void wave5_return_bufs(struct vb2_queue *q, u32 state);
void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp,
int pix_fmt_type,
unsigned int width,
unsigned int height,
const struct v4l2_frmsize_stepwise *frmsize);
int wave5_kfifo_alloc(struct vpu_instance *inst);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,737 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - wave5 register definitions
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef __WAVE5_REGISTER_DEFINE_H__
#define __WAVE5_REGISTER_DEFINE_H__
enum W5_VPU_COMMAND {
W5_INIT_VPU = 0x0001,
W5_WAKEUP_VPU = 0x0002,
W5_SLEEP_VPU = 0x0004,
W5_CREATE_INSTANCE = 0x0008, /* queuing command */
W5_FLUSH_INSTANCE = 0x0010,
W5_DESTROY_INSTANCE = 0x0020, /* queuing command */
W5_INIT_SEQ = 0x0040, /* queuing command */
W5_SET_FB = 0x0080,
W5_DEC_ENC_PIC = 0x0100, /* queuing command */
W5_ENC_SET_PARAM = 0x0200, /* queuing command */
W5_QUERY = 0x4000,
W5_UPDATE_BS = 0x8000,
W5_MAX_VPU_COMD = 0x10000,
};
enum query_opt {
GET_VPU_INFO = 0,
SET_WRITE_PROT = 1,
GET_RESULT = 2,
UPDATE_DISP_FLAG = 3,
GET_BW_REPORT = 4,
GET_BS_RD_PTR = 5, /* for decoder */
GET_BS_WR_PTR = 6, /* for encoder */
GET_SRC_BUF_FLAG = 7, /* for encoder */
SET_BS_RD_PTR = 8, /* for decoder */
GET_DEBUG_INFO = 0x61,
};
#define W5_REG_BASE 0x00000000
#define W5_CMD_REG_BASE 0x00000100
#define W5_CMD_REG_END 0x00000200
/*
* COMMON
*
* ----
*
* Power on configuration
* PO_DEBUG_MODE [0] 1 - power on with debug mode
* USE_PO_CONF [3] 1 - use power-on-configuration
*/
#define W5_PO_CONF (W5_REG_BASE + 0x0000)
#define W5_VCPU_CUR_PC (W5_REG_BASE + 0x0004)
#define W5_VCPU_CUR_LR (W5_REG_BASE + 0x0008)
#define W5_VPU_PDBG_STEP_MASK_V (W5_REG_BASE + 0x000C)
#define W5_VPU_PDBG_CTRL (W5_REG_BASE + 0x0010) /* v_cpu debugger ctrl register */
#define W5_VPU_PDBG_IDX_REG (W5_REG_BASE + 0x0014) /* v_cpu debugger index register */
#define W5_VPU_PDBG_WDATA_REG (W5_REG_BASE + 0x0018) /* v_cpu debugger write data reg */
#define W5_VPU_PDBG_RDATA_REG (W5_REG_BASE + 0x001C) /* v_cpu debugger read data reg */
#define W5_VPU_FIO_CTRL_ADDR (W5_REG_BASE + 0x0020)
#define W5_VPU_FIO_DATA (W5_REG_BASE + 0x0024)
#define W5_VPU_VINT_REASON_USR (W5_REG_BASE + 0x0030)
#define W5_VPU_VINT_REASON_CLR (W5_REG_BASE + 0x0034)
#define W5_VPU_HOST_INT_REQ (W5_REG_BASE + 0x0038)
#define W5_VPU_VINT_CLEAR (W5_REG_BASE + 0x003C)
#define W5_VPU_HINT_CLEAR (W5_REG_BASE + 0x0040)
#define W5_VPU_VPU_INT_STS (W5_REG_BASE + 0x0044)
#define W5_VPU_VINT_ENABLE (W5_REG_BASE + 0x0048)
#define W5_VPU_VINT_REASON (W5_REG_BASE + 0x004C)
#define W5_VPU_RESET_REQ (W5_REG_BASE + 0x0050)
#define W5_RST_BLOCK_CCLK(_core) BIT((_core))
#define W5_RST_BLOCK_CCLK_ALL (0xff)
#define W5_RST_BLOCK_BCLK(_core) (0x100 << (_core))
#define W5_RST_BLOCK_BCLK_ALL (0xff00)
#define W5_RST_BLOCK_ACLK(_core) (0x10000 << (_core))
#define W5_RST_BLOCK_ACLK_ALL (0xff0000)
#define W5_RST_BLOCK_VCPU_ALL (0x3f000000)
#define W5_RST_BLOCK_ALL (0x3fffffff)
#define W5_VPU_RESET_STATUS (W5_REG_BASE + 0x0054)
#define W5_VCPU_RESTART (W5_REG_BASE + 0x0058)
#define W5_VPU_CLK_MASK (W5_REG_BASE + 0x005C)
/* REMAP_CTRL
* PAGE SIZE: [8:0] 0x001 - 4K
* 0x002 - 8K
* 0x004 - 16K
* ...
* 0x100 - 1M
* REGION ATTR1 [10] 0 - normal
* 1 - make bus error for the region
* REGION ATTR2 [11] 0 - normal
* 1 - bypass region
* REMAP INDEX [15:12] - 0 ~ 3
* ENDIAN [19:16] - NOTE: Currently not supported in this driver
* AXI-ID [23:20] - upper AXI-ID
* BUS_ERROR [29] 0 - bypass
* 1 - make BUS_ERROR for unmapped region
* BYPASS_ALL [30] 1 - bypass all
* ENABLE [31] 1 - update control register[30:16]
*/
#define W5_VPU_REMAP_CTRL (W5_REG_BASE + 0x0060)
#define W5_VPU_REMAP_VADDR (W5_REG_BASE + 0x0064)
#define W5_VPU_REMAP_PADDR (W5_REG_BASE + 0x0068)
#define W5_VPU_REMAP_CORE_START (W5_REG_BASE + 0x006C)
#define W5_VPU_BUSY_STATUS (W5_REG_BASE + 0x0070)
#define W5_VPU_HALT_STATUS (W5_REG_BASE + 0x0074)
#define W5_VPU_VCPU_STATUS (W5_REG_BASE + 0x0078)
#define W5_VPU_RET_PRODUCT_VERSION (W5_REG_BASE + 0x0094)
/*
* assign vpu_config0 = {conf_map_converter_reg, // [31]
* conf_map_converter_sig, // [30]
* 8'd0, // [29:22]
* conf_std_switch_en, // [21]
* conf_bg_detect, // [20]
* conf_3dnr_en, // [19]
* conf_one_axi_en, // [18]
* conf_sec_axi_en, // [17]
* conf_bus_info, // [16]
* conf_afbc_en, // [15]
* conf_afbc_version_id, // [14:12]
* conf_fbc_en, // [11]
* conf_fbc_version_id, // [10:08]
* conf_scaler_en, // [07]
* conf_scaler_version_id, // [06:04]
* conf_bwb_en, // [03]
* 3'd0}; // [02:00]
*/
#define W5_VPU_RET_VPU_CONFIG0 (W5_REG_BASE + 0x0098)
/*
* assign vpu_config1 = {4'd0, // [31:28]
* conf_perf_timer_en, // [27]
* conf_multi_core_en, // [26]
* conf_gcu_en, // [25]
* conf_cu_report, // [24]
* 4'd0, // [23:20]
* conf_vcore_id_3, // [19]
* conf_vcore_id_2, // [18]
* conf_vcore_id_1, // [17]
* conf_vcore_id_0, // [16]
* conf_bwb_opt, // [15]
* 7'd0, // [14:08]
* conf_cod_std_en_reserved_7, // [7]
* conf_cod_std_en_reserved_6, // [6]
* conf_cod_std_en_reserved_5, // [5]
* conf_cod_std_en_reserved_4, // [4]
* conf_cod_std_en_reserved_3, // [3]
* conf_cod_std_en_reserved_2, // [2]
* conf_cod_std_en_vp9, // [1]
* conf_cod_std_en_hevc}; // [0]
* }
*/
#define W5_VPU_RET_VPU_CONFIG1 (W5_REG_BASE + 0x009C)
#define W5_VPU_DBG_REG0 (W5_REG_BASE + 0x00f0)
#define W5_VPU_DBG_REG1 (W5_REG_BASE + 0x00f4)
#define W5_VPU_DBG_REG2 (W5_REG_BASE + 0x00f8)
#define W5_VPU_DBG_REG3 (W5_REG_BASE + 0x00fc)
/************************************************************************/
/* PRODUCT INFORMATION */
/************************************************************************/
#define W5_PRODUCT_NAME (W5_REG_BASE + 0x1040)
#define W5_PRODUCT_NUMBER (W5_REG_BASE + 0x1044)
/************************************************************************/
/* DECODER/ENCODER COMMON */
/************************************************************************/
#define W5_COMMAND (W5_REG_BASE + 0x0100)
#define W5_COMMAND_OPTION (W5_REG_BASE + 0x0104)
#define W5_QUERY_OPTION (W5_REG_BASE + 0x0104)
#define W5_RET_SUCCESS (W5_REG_BASE + 0x0108)
#define W5_RET_FAIL_REASON (W5_REG_BASE + 0x010C)
#define W5_RET_QUEUE_FAIL_REASON (W5_REG_BASE + 0x0110)
#define W5_CMD_INSTANCE_INFO (W5_REG_BASE + 0x0110)
#define W5_RET_QUEUE_STATUS (W5_REG_BASE + 0x01E0)
#define W5_RET_BS_EMPTY_INST (W5_REG_BASE + 0x01E4)
#define W5_RET_QUEUE_CMD_DONE_INST (W5_REG_BASE + 0x01E8)
#define W5_RET_STAGE0_INSTANCE_INFO (W5_REG_BASE + 0x01EC)
#define W5_RET_STAGE1_INSTANCE_INFO (W5_REG_BASE + 0x01F0)
#define W5_RET_STAGE2_INSTANCE_INFO (W5_REG_BASE + 0x01F4)
#define W5_RET_SEQ_DONE_INSTANCE_INFO (W5_REG_BASE + 0x01FC)
#define W5_BS_OPTION (W5_REG_BASE + 0x0120)
/* return info when QUERY (GET_RESULT) for en/decoder */
#define W5_RET_VLC_BUF_SIZE (W5_REG_BASE + 0x01B0)
/* return info when QUERY (GET_RESULT) for en/decoder */
#define W5_RET_PARAM_BUF_SIZE (W5_REG_BASE + 0x01B4)
/* set when SET_FB for en/decoder */
#define W5_CMD_SET_FB_ADDR_TASK_BUF (W5_REG_BASE + 0x01D4)
#define W5_CMD_SET_FB_TASK_BUF_SIZE (W5_REG_BASE + 0x01D8)
/************************************************************************/
/* INIT_VPU - COMMON */
/************************************************************************/
/* note: W5_ADDR_CODE_BASE should be aligned to 4KB */
#define W5_ADDR_CODE_BASE (W5_REG_BASE + 0x0110)
#define W5_CODE_SIZE (W5_REG_BASE + 0x0114)
#define W5_CODE_PARAM (W5_REG_BASE + 0x0118)
#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)
/************************************************************************/
/* CREATE_INSTANCE - COMMON */
/************************************************************************/
#define W5_ADDR_WORK_BASE (W5_REG_BASE + 0x0114)
#define W5_WORK_SIZE (W5_REG_BASE + 0x0118)
#define W5_CMD_DEC_BS_START_ADDR (W5_REG_BASE + 0x011C)
#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)
/************************************************************************/
/* DECODER - INIT_SEQ */
/************************************************************************/
#define W5_BS_RD_PTR (W5_REG_BASE + 0x0118)
#define W5_BS_WR_PTR (W5_REG_BASE + 0x011C)
/************************************************************************/
/* SET_FRAME_BUF */
/************************************************************************/
/* SET_FB_OPTION 0x00 REGISTER FRAMEBUFFERS
* 0x01 UPDATE FRAMEBUFFER, just one framebuffer(linear, fbc and mvcol)
*/
#define W5_SFB_OPTION (W5_REG_BASE + 0x0104)
#define W5_COMMON_PIC_INFO (W5_REG_BASE + 0x0118)
#define W5_PIC_SIZE (W5_REG_BASE + 0x011C)
#define W5_SET_FB_NUM (W5_REG_BASE + 0x0120)
#define W5_EXTRA_PIC_INFO (W5_REG_BASE + 0x0124)
#define W5_ADDR_LUMA_BASE0 (W5_REG_BASE + 0x0134)
#define W5_ADDR_CB_BASE0 (W5_REG_BASE + 0x0138)
#define W5_ADDR_CR_BASE0 (W5_REG_BASE + 0x013C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET0 (W5_REG_BASE + 0x013C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET0 (W5_REG_BASE + 0x0140)
#define W5_ADDR_LUMA_BASE1 (W5_REG_BASE + 0x0144)
#define W5_ADDR_CB_ADDR1 (W5_REG_BASE + 0x0148)
#define W5_ADDR_CR_ADDR1 (W5_REG_BASE + 0x014C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET1 (W5_REG_BASE + 0x014C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET1 (W5_REG_BASE + 0x0150)
#define W5_ADDR_LUMA_BASE2 (W5_REG_BASE + 0x0154)
#define W5_ADDR_CB_ADDR2 (W5_REG_BASE + 0x0158)
#define W5_ADDR_CR_ADDR2 (W5_REG_BASE + 0x015C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET2 (W5_REG_BASE + 0x015C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET2 (W5_REG_BASE + 0x0160)
#define W5_ADDR_LUMA_BASE3 (W5_REG_BASE + 0x0164)
#define W5_ADDR_CB_ADDR3 (W5_REG_BASE + 0x0168)
#define W5_ADDR_CR_ADDR3 (W5_REG_BASE + 0x016C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET3 (W5_REG_BASE + 0x016C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET3 (W5_REG_BASE + 0x0170)
#define W5_ADDR_LUMA_BASE4 (W5_REG_BASE + 0x0174)
#define W5_ADDR_CB_ADDR4 (W5_REG_BASE + 0x0178)
#define W5_ADDR_CR_ADDR4 (W5_REG_BASE + 0x017C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET4 (W5_REG_BASE + 0x017C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET4 (W5_REG_BASE + 0x0180)
#define W5_ADDR_LUMA_BASE5 (W5_REG_BASE + 0x0184)
#define W5_ADDR_CB_ADDR5 (W5_REG_BASE + 0x0188)
#define W5_ADDR_CR_ADDR5 (W5_REG_BASE + 0x018C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET5 (W5_REG_BASE + 0x018C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET5 (W5_REG_BASE + 0x0190)
#define W5_ADDR_LUMA_BASE6 (W5_REG_BASE + 0x0194)
#define W5_ADDR_CB_ADDR6 (W5_REG_BASE + 0x0198)
#define W5_ADDR_CR_ADDR6 (W5_REG_BASE + 0x019C)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET6 (W5_REG_BASE + 0x019C)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET6 (W5_REG_BASE + 0x01A0)
#define W5_ADDR_LUMA_BASE7 (W5_REG_BASE + 0x01A4)
#define W5_ADDR_CB_ADDR7 (W5_REG_BASE + 0x01A8)
#define W5_ADDR_CR_ADDR7 (W5_REG_BASE + 0x01AC)
/* compression offset table for luma */
#define W5_ADDR_FBC_Y_OFFSET7 (W5_REG_BASE + 0x01AC)
/* compression offset table for chroma */
#define W5_ADDR_FBC_C_OFFSET7 (W5_REG_BASE + 0x01B0)
#define W5_ADDR_MV_COL0 (W5_REG_BASE + 0x01B4)
#define W5_ADDR_MV_COL1 (W5_REG_BASE + 0x01B8)
#define W5_ADDR_MV_COL2 (W5_REG_BASE + 0x01BC)
#define W5_ADDR_MV_COL3 (W5_REG_BASE + 0x01C0)
#define W5_ADDR_MV_COL4 (W5_REG_BASE + 0x01C4)
#define W5_ADDR_MV_COL5 (W5_REG_BASE + 0x01C8)
#define W5_ADDR_MV_COL6 (W5_REG_BASE + 0x01CC)
#define W5_ADDR_MV_COL7 (W5_REG_BASE + 0x01D0)
/* UPDATE_FB */
/* CMD_SET_FB_STRIDE [15:0] - FBC framebuffer stride
* [31:15] - linear framebuffer stride
*/
#define W5_CMD_SET_FB_STRIDE (W5_REG_BASE + 0x0118)
#define W5_CMD_SET_FB_INDEX (W5_REG_BASE + 0x0120)
#define W5_ADDR_LUMA_BASE (W5_REG_BASE + 0x0134)
#define W5_ADDR_CB_BASE (W5_REG_BASE + 0x0138)
#define W5_ADDR_CR_BASE (W5_REG_BASE + 0x013C)
#define W5_ADDR_MV_COL (W5_REG_BASE + 0x0140)
#define W5_ADDR_FBC_Y_BASE (W5_REG_BASE + 0x0144)
#define W5_ADDR_FBC_C_BASE (W5_REG_BASE + 0x0148)
#define W5_ADDR_FBC_Y_OFFSET (W5_REG_BASE + 0x014C)
#define W5_ADDR_FBC_C_OFFSET (W5_REG_BASE + 0x0150)
/************************************************************************/
/* DECODER - DEC_PIC */
/************************************************************************/
#define W5_CMD_DEC_VCORE_INFO (W5_REG_BASE + 0x0194)
/* sequence change enable mask register
* CMD_SEQ_CHANGE_ENABLE_FLAG [5] profile_idc
* [16] pic_width/height_in_luma_sample
* [19] sps_max_dec_pic_buffering, max_num_reorder, max_latency_increase
*/
#define W5_CMD_SEQ_CHANGE_ENABLE_FLAG (W5_REG_BASE + 0x0128)
#define W5_CMD_DEC_USER_MASK (W5_REG_BASE + 0x012C)
#define W5_CMD_DEC_TEMPORAL_ID_PLUS1 (W5_REG_BASE + 0x0130)
#define W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1 (W5_REG_BASE + 0x0134)
#define W5_USE_SEC_AXI (W5_REG_BASE + 0x0150)
/************************************************************************/
/* DECODER - QUERY : GET_VPU_INFO */
/************************************************************************/
#define W5_RET_FW_VERSION (W5_REG_BASE + 0x0118)
#define W5_RET_PRODUCT_NAME (W5_REG_BASE + 0x011C)
#define W5_RET_PRODUCT_VERSION (W5_REG_BASE + 0x0120)
#define W5_RET_STD_DEF0 (W5_REG_BASE + 0x0124)
#define W5_RET_STD_DEF1 (W5_REG_BASE + 0x0128)
#define W5_RET_CONF_FEATURE (W5_REG_BASE + 0x012C)
#define W5_RET_CONF_DATE (W5_REG_BASE + 0x0130)
#define W5_RET_CONF_REVISION (W5_REG_BASE + 0x0134)
#define W5_RET_CONF_TYPE (W5_REG_BASE + 0x0138)
#define W5_RET_PRODUCT_ID (W5_REG_BASE + 0x013C)
#define W5_RET_CUSTOMER_ID (W5_REG_BASE + 0x0140)
/************************************************************************/
/* DECODER - QUERY : GET_RESULT */
/************************************************************************/
#define W5_CMD_DEC_ADDR_REPORT_BASE (W5_REG_BASE + 0x0114)
#define W5_CMD_DEC_REPORT_SIZE (W5_REG_BASE + 0x0118)
#define W5_CMD_DEC_REPORT_PARAM (W5_REG_BASE + 0x011C)
#define W5_RET_DEC_BS_RD_PTR (W5_REG_BASE + 0x011C)
#define W5_RET_DEC_SEQ_PARAM (W5_REG_BASE + 0x0120)
#define W5_RET_DEC_COLOR_SAMPLE_INFO (W5_REG_BASE + 0x0124)
#define W5_RET_DEC_ASPECT_RATIO (W5_REG_BASE + 0x0128)
#define W5_RET_DEC_BIT_RATE (W5_REG_BASE + 0x012C)
#define W5_RET_DEC_FRAME_RATE_NR (W5_REG_BASE + 0x0130)
#define W5_RET_DEC_FRAME_RATE_DR (W5_REG_BASE + 0x0134)
#define W5_RET_DEC_NUM_REQUIRED_FB (W5_REG_BASE + 0x0138)
#define W5_RET_DEC_NUM_REORDER_DELAY (W5_REG_BASE + 0x013C)
#define W5_RET_DEC_SUB_LAYER_INFO (W5_REG_BASE + 0x0140)
#define W5_RET_DEC_NOTIFICATION (W5_REG_BASE + 0x0144)
/*
* USER_DATA_FLAGS for HEVC/H264 only.
* Bits:
* [1] - User data buffer full boolean
* [2] - VUI parameter flag
* [4] - Pic_timing SEI flag
* [5] - 1st user_data_registed_itu_t_t35 prefix SEI flag
* [6] - user_data_unregistered prefix SEI flag
* [7] - 1st user_data_registed_itu_t_t35 suffix SEI flag
* [8] - user_data_unregistered suffix SEI flag
* [10]- mastering_display_color_volume prefix SEI flag
* [11]- chroma_resampling_display_color_volume prefix SEI flag
* [12]- knee_function_info SEI flag
* [13]- tone_mapping_info prefix SEI flag
* [14]- film_grain_characteristics_info prefix SEI flag
* [15]- content_light_level_info prefix SEI flag
* [16]- color_remapping_info prefix SEI flag
* [28]- 2nd user_data_registed_itu_t_t35 prefix SEI flag
* [29]- 3rd user_data_registed_itu_t_t35 prefix SEI flag
* [30]- 2nd user_data_registed_itu_t_t35 suffix SEI flag
* [31]- 3rd user_data_registed_itu_t_t35 suffix SEI flag
*/
#define W5_RET_DEC_USERDATA_IDC (W5_REG_BASE + 0x0148)
#define W5_RET_DEC_PIC_SIZE (W5_REG_BASE + 0x014C)
#define W5_RET_DEC_CROP_TOP_BOTTOM (W5_REG_BASE + 0x0150)
#define W5_RET_DEC_CROP_LEFT_RIGHT (W5_REG_BASE + 0x0154)
/*
* #define W5_RET_DEC_AU_START_POS (W5_REG_BASE + 0x0158)
* => Access unit (AU) Bitstream start position
* #define W5_RET_DEC_AU_END_POS (W5_REG_BASE + 0x015C)
* => Access unit (AU) Bitstream end position
*/
/*
* Decoded picture type:
* reg_val & 0x7 => picture type
* (reg_val >> 4) & 0x3f => VCL NAL unit type
* (reg_val >> 31) & 0x1 => output_flag
* 16 << ((reg_val >> 10) & 0x3) => ctu_size
*/
#define W5_RET_DEC_PIC_TYPE (W5_REG_BASE + 0x0160)
#define W5_RET_DEC_PIC_POC (W5_REG_BASE + 0x0164)
/*
* #define W5_RET_DEC_RECOVERY_POINT (W5_REG_BASE + 0x0168)
* => HEVC recovery point
* reg_val & 0xff => number of signed recovery picture order counts
* (reg_val >> 16) & 0x1 => exact match flag
* (reg_val >> 17) & 0x1 => broken link flag
* (reg_val >> 18) & 0x1 => exist flag
*/
#define W5_RET_DEC_DEBUG_INDEX (W5_REG_BASE + 0x016C)
#define W5_RET_DEC_DECODED_INDEX (W5_REG_BASE + 0x0170)
#define W5_RET_DEC_DISPLAY_INDEX (W5_REG_BASE + 0x0174)
/*
* #define W5_RET_DEC_REALLOC_INDEX (W5_REG_BASE + 0x0178)
* => display picture index in decoded picture buffer
* reg_val & 0xf => display picture index for FBC buffer (by reordering)
*/
#define W5_RET_DEC_DISP_IDC (W5_REG_BASE + 0x017C)
/*
* #define W5_RET_DEC_ERR_CTB_NUM (W5_REG_BASE + 0x0180)
* => Number of error CTUs
* reg_val >> 16 => erroneous CTUs in bitstream
* reg_val & 0xffff => total CTUs in bitstream
*
* #define W5_RET_DEC_PIC_PARAM (W5_REG_BASE + 0x01A0)
* => Bitstream sequence/picture parameter information (AV1 only)
* reg_val & 0x1 => intrabc tool enable
* (reg_val >> 1) & 0x1 => screen content tools enable
*/
#define W5_RET_DEC_HOST_CMD_TICK (W5_REG_BASE + 0x01B8)
/*
* #define W5_RET_DEC_SEEK_START_TICK (W5_REG_BASE + 0x01BC)
* #define W5_RET_DEC_SEEK_END_TICK (W5_REG_BASE + 0x01C0)
* => Start and end ticks for seeking slices of the picture
* #define W5_RET_DEC_PARSING_START_TICK (W5_REG_BASE + 0x01C4)
* #define W5_RET_DEC_PARSING_END_TICK (W5_REG_BASE + 0x01C8)
* => Start and end ticks for parsing slices of the picture
* #define W5_RET_DEC_DECODING_START_TICK (W5_REG_BASE + 0x01CC)
* => Start tick for decoding slices of the picture
*/
#define W5_RET_DEC_DECODING_ENC_TICK (W5_REG_BASE + 0x01D0)
#define W5_RET_DEC_WARN_INFO (W5_REG_BASE + 0x01D4)
#define W5_RET_DEC_ERR_INFO (W5_REG_BASE + 0x01D8)
#define W5_RET_DEC_DECODING_SUCCESS (W5_REG_BASE + 0x01DC)
/************************************************************************/
/* DECODER - FLUSH_INSTANCE */
/************************************************************************/
#define W5_CMD_FLUSH_INST_OPT (W5_REG_BASE + 0x104)
/************************************************************************/
/* DECODER - QUERY : UPDATE_DISP_FLAG */
/************************************************************************/
#define W5_CMD_DEC_SET_DISP_IDC (W5_REG_BASE + 0x0118)
#define W5_CMD_DEC_CLR_DISP_IDC (W5_REG_BASE + 0x011C)
/************************************************************************/
/* DECODER - QUERY : SET_BS_RD_PTR */
/************************************************************************/
#define W5_RET_QUERY_DEC_SET_BS_RD_PTR (W5_REG_BASE + 0x011C)
/************************************************************************/
/* DECODER - QUERY : GET_BS_RD_PTR */
/************************************************************************/
#define W5_RET_QUERY_DEC_BS_RD_PTR (W5_REG_BASE + 0x011C)
/************************************************************************/
/* QUERY : GET_DEBUG_INFO */
/************************************************************************/
#define W5_RET_QUERY_DEBUG_PRI_REASON (W5_REG_BASE + 0x114)
/************************************************************************/
/* GDI register for debugging */
/************************************************************************/
#define W5_GDI_BASE 0x8800
#define W5_GDI_BUS_CTRL (W5_GDI_BASE + 0x0F0)
#define W5_GDI_BUS_STATUS (W5_GDI_BASE + 0x0F4)
#define W5_BACKBONE_BASE_VCPU 0xFE00
#define W5_BACKBONE_BUS_CTRL_VCPU (W5_BACKBONE_BASE_VCPU + 0x010)
#define W5_BACKBONE_BUS_STATUS_VCPU (W5_BACKBONE_BASE_VCPU + 0x014)
#define W5_BACKBONE_PROG_AXI_ID (W5_BACKBONE_BASE_VCPU + 0x00C)
#define W5_BACKBONE_PROC_EXT_ADDR (W5_BACKBONE_BASE_VCPU + 0x0C0)
#define W5_BACKBONE_AXI_PARAM (W5_BACKBONE_BASE_VCPU + 0x0E0)
#define W5_BACKBONE_BASE_VCORE0 0x8E00
#define W5_BACKBONE_BUS_CTRL_VCORE0 (W5_BACKBONE_BASE_VCORE0 + 0x010)
#define W5_BACKBONE_BUS_STATUS_VCORE0 (W5_BACKBONE_BASE_VCORE0 + 0x014)
#define W5_BACKBONE_BASE_VCORE1 0x9E00 /* for dual-core product */
#define W5_BACKBONE_BUS_CTRL_VCORE1 (W5_BACKBONE_BASE_VCORE1 + 0x010)
#define W5_BACKBONE_BUS_STATUS_VCORE1 (W5_BACKBONE_BASE_VCORE1 + 0x014)
#define W5_COMBINED_BACKBONE_BASE 0xFE00
#define W5_COMBINED_BACKBONE_BUS_CTRL (W5_COMBINED_BACKBONE_BASE + 0x010)
#define W5_COMBINED_BACKBONE_BUS_STATUS (W5_COMBINED_BACKBONE_BASE + 0x014)
/************************************************************************/
/* */
/* for ENCODER */
/* */
/************************************************************************/
#define W5_RET_STAGE3_INSTANCE_INFO (W5_REG_BASE + 0x1F8)
/************************************************************************/
/* ENCODER - CREATE_INSTANCE */
/************************************************************************/
/* 0x114 ~ 0x124 : defined above (CREATE_INSTANCE COMMON) */
#define W5_CMD_ENC_VCORE_INFO (W5_REG_BASE + 0x0194)
#define W5_CMD_ENC_SRC_OPTIONS (W5_REG_BASE + 0x0128)
/************************************************************************/
/* ENCODER - SET_FB */
/************************************************************************/
#define W5_FBC_STRIDE (W5_REG_BASE + 0x128)
#define W5_ADDR_SUB_SAMPLED_FB_BASE (W5_REG_BASE + 0x12C)
#define W5_SUB_SAMPLED_ONE_FB_SIZE (W5_REG_BASE + 0x130)
/************************************************************************/
/* ENCODER - ENC_SET_PARAM (COMMON & CHANGE_PARAM) */
/************************************************************************/
#define W5_CMD_ENC_SEQ_SET_PARAM_OPTION (W5_REG_BASE + 0x104)
#define W5_CMD_ENC_SEQ_SET_PARAM_ENABLE (W5_REG_BASE + 0x118)
#define W5_CMD_ENC_SEQ_SRC_SIZE (W5_REG_BASE + 0x11C)
#define W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN (W5_REG_BASE + 0x120)
#define W5_CMD_ENC_SEQ_SPS_PARAM (W5_REG_BASE + 0x124)
#define W5_CMD_ENC_SEQ_PPS_PARAM (W5_REG_BASE + 0x128)
#define W5_CMD_ENC_SEQ_GOP_PARAM (W5_REG_BASE + 0x12C)
#define W5_CMD_ENC_SEQ_INTRA_PARAM (W5_REG_BASE + 0x130)
#define W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT (W5_REG_BASE + 0x134)
#define W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT (W5_REG_BASE + 0x138)
#define W5_CMD_ENC_SEQ_RDO_PARAM (W5_REG_BASE + 0x13C)
#define W5_CMD_ENC_SEQ_INDEPENDENT_SLICE (W5_REG_BASE + 0x140)
#define W5_CMD_ENC_SEQ_DEPENDENT_SLICE (W5_REG_BASE + 0x144)
#define W5_CMD_ENC_SEQ_INTRA_REFRESH (W5_REG_BASE + 0x148)
#define W5_CMD_ENC_SEQ_INPUT_SRC_PARAM (W5_REG_BASE + 0x14C)
#define W5_CMD_ENC_SEQ_RC_FRAME_RATE (W5_REG_BASE + 0x150)
#define W5_CMD_ENC_SEQ_RC_TARGET_RATE (W5_REG_BASE + 0x154)
#define W5_CMD_ENC_SEQ_RC_PARAM (W5_REG_BASE + 0x158)
#define W5_CMD_ENC_SEQ_RC_MIN_MAX_QP (W5_REG_BASE + 0x15C)
#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3 (W5_REG_BASE + 0x160)
#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7 (W5_REG_BASE + 0x164)
#define W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP (W5_REG_BASE + 0x168)
#define W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM (W5_REG_BASE + 0x16C)
#define W5_CMD_ENC_SEQ_ROT_PARAM (W5_REG_BASE + 0x170)
#define W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK (W5_REG_BASE + 0x174)
#define W5_CMD_ENC_SEQ_TIME_SCALE (W5_REG_BASE + 0x178)
#define W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE (W5_REG_BASE + 0x17C)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU04 (W5_REG_BASE + 0x184)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU08 (W5_REG_BASE + 0x188)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU16 (W5_REG_BASE + 0x18C)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU32 (W5_REG_BASE + 0x190)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU08 (W5_REG_BASE + 0x194)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU16 (W5_REG_BASE + 0x198)
#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU32 (W5_REG_BASE + 0x19C)
#define W5_CMD_ENC_SEQ_NR_PARAM (W5_REG_BASE + 0x1A0)
#define W5_CMD_ENC_SEQ_NR_WEIGHT (W5_REG_BASE + 0x1A4)
#define W5_CMD_ENC_SEQ_BG_PARAM (W5_REG_BASE + 0x1A8)
#define W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR (W5_REG_BASE + 0x1AC)
#define W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR (W5_REG_BASE + 0x1B0)
#define W5_CMD_ENC_SEQ_VUI_HRD_PARAM (W5_REG_BASE + 0x180)
#define W5_CMD_ENC_SEQ_VUI_RBSP_ADDR (W5_REG_BASE + 0x1B8)
#define W5_CMD_ENC_SEQ_HRD_RBSP_ADDR (W5_REG_BASE + 0x1BC)
/************************************************************************/
/* ENCODER - ENC_SET_PARAM (CUSTOM_GOP) */
/************************************************************************/
#define W5_CMD_ENC_CUSTOM_GOP_PARAM (W5_REG_BASE + 0x11C)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_0 (W5_REG_BASE + 0x120)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_1 (W5_REG_BASE + 0x124)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_2 (W5_REG_BASE + 0x128)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_3 (W5_REG_BASE + 0x12C)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_4 (W5_REG_BASE + 0x130)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_5 (W5_REG_BASE + 0x134)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_6 (W5_REG_BASE + 0x138)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_7 (W5_REG_BASE + 0x13C)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_8 (W5_REG_BASE + 0x140)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_9 (W5_REG_BASE + 0x144)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_10 (W5_REG_BASE + 0x148)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_11 (W5_REG_BASE + 0x14C)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_12 (W5_REG_BASE + 0x150)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_13 (W5_REG_BASE + 0x154)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_14 (W5_REG_BASE + 0x158)
#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_15 (W5_REG_BASE + 0x15C)
/************************************************************************/
/* ENCODER - ENC_PIC */
/************************************************************************/
#define W5_CMD_ENC_BS_START_ADDR (W5_REG_BASE + 0x118)
#define W5_CMD_ENC_BS_SIZE (W5_REG_BASE + 0x11C)
#define W5_CMD_ENC_PIC_USE_SEC_AXI (W5_REG_BASE + 0x124)
#define W5_CMD_ENC_PIC_REPORT_PARAM (W5_REG_BASE + 0x128)
#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM (W5_REG_BASE + 0x138)
#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR (W5_REG_BASE + 0x13C)
#define W5_CMD_ENC_PIC_SRC_PIC_IDX (W5_REG_BASE + 0x144)
#define W5_CMD_ENC_PIC_SRC_ADDR_Y (W5_REG_BASE + 0x148)
#define W5_CMD_ENC_PIC_SRC_ADDR_U (W5_REG_BASE + 0x14C)
#define W5_CMD_ENC_PIC_SRC_ADDR_V (W5_REG_BASE + 0x150)
#define W5_CMD_ENC_PIC_SRC_STRIDE (W5_REG_BASE + 0x154)
#define W5_CMD_ENC_PIC_SRC_FORMAT (W5_REG_BASE + 0x158)
#define W5_CMD_ENC_PIC_SRC_AXI_SEL (W5_REG_BASE + 0x160)
#define W5_CMD_ENC_PIC_CODE_OPTION (W5_REG_BASE + 0x164)
#define W5_CMD_ENC_PIC_PIC_PARAM (W5_REG_BASE + 0x168)
#define W5_CMD_ENC_PIC_LONGTERM_PIC (W5_REG_BASE + 0x16C)
#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y (W5_REG_BASE + 0x170)
#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C (W5_REG_BASE + 0x174)
#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y (W5_REG_BASE + 0x178)
#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C (W5_REG_BASE + 0x17C)
#define W5_CMD_ENC_PIC_CF50_Y_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x190)
#define W5_CMD_ENC_PIC_CF50_CB_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x194)
#define W5_CMD_ENC_PIC_CF50_CR_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x198)
#define W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR (W5_REG_BASE + 0x180)
#define W5_CMD_ENC_PIC_PREFIX_SEI_INFO (W5_REG_BASE + 0x184)
#define W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR (W5_REG_BASE + 0x188)
#define W5_CMD_ENC_PIC_SUFFIX_SEI_INFO (W5_REG_BASE + 0x18c)
/************************************************************************/
/* ENCODER - QUERY (GET_RESULT) */
/************************************************************************/
#define W5_RET_ENC_NUM_REQUIRED_FB (W5_REG_BASE + 0x11C)
#define W5_RET_ENC_MIN_SRC_BUF_NUM (W5_REG_BASE + 0x120)
#define W5_RET_ENC_PIC_TYPE (W5_REG_BASE + 0x124)
/*
* #define W5_RET_ENC_PIC_POC (W5_REG_BASE + 0x128)
* => picture order count value of current encoded picture
*/
#define W5_RET_ENC_PIC_IDX (W5_REG_BASE + 0x12C)
/*
* #define W5_RET_ENC_PIC_SLICE_NUM (W5_REG_BASE + 0x130)
* reg_val & 0xffff = total independent slice segment number (16 bits)
* (reg_val >> 16) & 0xffff = total dependent slice segment number (16 bits)
*
* #define W5_RET_ENC_PIC_SKIP (W5_REG_BASE + 0x134)
* reg_val & 0xfe = picture skip flag (7 bits)
*
* #define W5_RET_ENC_PIC_NUM_INTRA (W5_REG_BASE + 0x138)
* => number of intra blocks in 8x8 (32 bits)
*
* #define W5_RET_ENC_PIC_NUM_MERGE (W5_REG_BASE + 0x13C)
* => number of merge blocks in 8x8 (32 bits)
*
* #define W5_RET_ENC_PIC_NUM_SKIP (W5_REG_BASE + 0x144)
* => number of skip blocks in 8x8 (32 bits)
*
* #define W5_RET_ENC_PIC_AVG_CTU_QP (W5_REG_BASE + 0x148)
* => Average CTU QP value (32 bits)
*/
#define W5_RET_ENC_PIC_BYTE (W5_REG_BASE + 0x14C)
/*
* #define W5_RET_ENC_GOP_PIC_IDX (W5_REG_BASE + 0x150)
* => picture index in group of pictures
*/
#define W5_RET_ENC_USED_SRC_IDX (W5_REG_BASE + 0x154)
/*
* #define W5_RET_ENC_PIC_NUM (W5_REG_BASE + 0x158)
* => encoded picture number
*/
#define W5_RET_ENC_VCL_NUT (W5_REG_BASE + 0x15C)
/*
* Only for H264:
* #define W5_RET_ENC_PIC_DIST_LOW (W5_REG_BASE + 0x164)
* => lower 32 bits of the sum of squared difference between source Y picture
* and reconstructed Y picture
* #define W5_RET_ENC_PIC_DIST_HIGH (W5_REG_BASE + 0x168)
* => upper 32 bits of the sum of squared difference between source Y picture
* and reconstructed Y picture
*/
#define W5_RET_ENC_PIC_MAX_LATENCY_PICS (W5_REG_BASE + 0x16C)
#define W5_RET_ENC_HOST_CMD_TICK (W5_REG_BASE + 0x1B8)
/*
* #define W5_RET_ENC_PREPARE_START_TICK (W5_REG_BASE + 0x1BC)
* #define W5_RET_ENC_PREPARE_END_TICK (W5_REG_BASE + 0x1C0)
* => Start and end ticks for preparing slices of the picture
* #define W5_RET_ENC_PROCESSING_START_TICK (W5_REG_BASE + 0x1C4)
* #define W5_RET_ENC_PROCESSING_END_TICK (W5_REG_BASE + 0x1C8)
* => Start and end ticks for processing slices of the picture
* #define W5_RET_ENC_ENCODING_START_TICK (W5_REG_BASE + 0x1CC)
* => Start tick for encoding slices of the picture
*/
#define W5_RET_ENC_ENCODING_END_TICK (W5_REG_BASE + 0x1D0)
#define W5_RET_ENC_WARN_INFO (W5_REG_BASE + 0x1D4)
#define W5_RET_ENC_ERR_INFO (W5_REG_BASE + 0x1D8)
#define W5_RET_ENC_ENCODING_SUCCESS (W5_REG_BASE + 0x1DC)
/************************************************************************/
/* ENCODER - QUERY (GET_BS_WR_PTR) */
/************************************************************************/
#define W5_RET_ENC_RD_PTR (W5_REG_BASE + 0x114)
#define W5_RET_ENC_WR_PTR (W5_REG_BASE + 0x118)
#define W5_CMD_ENC_REASON_SEL (W5_REG_BASE + 0x11C)
/************************************************************************/
/* ENCODER - QUERY (GET_BW_REPORT) */
/************************************************************************/
#define RET_QUERY_BW_PRP_AXI_READ (W5_REG_BASE + 0x118)
#define RET_QUERY_BW_PRP_AXI_WRITE (W5_REG_BASE + 0x11C)
#define RET_QUERY_BW_FBD_Y_AXI_READ (W5_REG_BASE + 0x120)
#define RET_QUERY_BW_FBC_Y_AXI_WRITE (W5_REG_BASE + 0x124)
#define RET_QUERY_BW_FBD_C_AXI_READ (W5_REG_BASE + 0x128)
#define RET_QUERY_BW_FBC_C_AXI_WRITE (W5_REG_BASE + 0x12C)
#define RET_QUERY_BW_PRI_AXI_READ (W5_REG_BASE + 0x130)
#define RET_QUERY_BW_PRI_AXI_WRITE (W5_REG_BASE + 0x134)
#define RET_QUERY_BW_SEC_AXI_READ (W5_REG_BASE + 0x138)
#define RET_QUERY_BW_SEC_AXI_WRITE (W5_REG_BASE + 0x13C)
#define RET_QUERY_BW_PROC_AXI_READ (W5_REG_BASE + 0x140)
#define RET_QUERY_BW_PROC_AXI_WRITE (W5_REG_BASE + 0x144)
#define RET_QUERY_BW_BWB_AXI_WRITE (W5_REG_BASE + 0x148)
#define W5_CMD_BW_OPTION (W5_REG_BASE + 0x14C)
/************************************************************************/
/* ENCODER - QUERY (GET_SRC_FLAG) */
/************************************************************************/
#define W5_RET_RELEASED_SRC_INSTANCE (W5_REG_BASE + 0x1EC)
#define W5_ENC_PIC_SUB_FRAME_SYNC_IF (W5_REG_BASE + 0x0300)
#endif /* __WAVE5_REGISTER_DEFINE_H__ */
@@ -0,0 +1,211 @@
// 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;
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");
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);
wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem);
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;
dma_addr_t daddr;
void *vaddr;
size_t size;
if (!vpu_dev->sram_pool || vb->vaddr)
return;
size = min_t(size_t, vpu_dev->sram_size, gen_pool_avail(vpu_dev->sram_pool));
vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, size, &daddr);
if (vaddr) {
vb->vaddr = vaddr;
vb->daddr = daddr;
vb->size = size;
}
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;
gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, vb->size);
memset(vb, 0, sizeof(*vb));
}
@@ -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_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,484 @@
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* Wave5 series multi-standard codec IP - platform driver
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include "wave5-vpu.h"
#include "wave5-regdefine.h"
#include "wave5-vpuconfig.h"
#include "wave5.h"
#define VPU_PLATFORM_DEVICE_NAME "vdec"
#define VPU_CLK_NAME "vcodec"
#define WAVE5_IS_ENC BIT(0)
#define WAVE5_IS_DEC BIT(1)
struct wave5_match_data {
int flags;
const char *fw_name;
u32 sram_size;
};
static int vpu_poll_interval = 5;
module_param(vpu_poll_interval, int, 0644);
int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout)
{
int ret;
ret = wait_for_completion_timeout(&inst->irq_done,
msecs_to_jiffies(timeout));
if (!ret)
return -ETIMEDOUT;
reinit_completion(&inst->irq_done);
return 0;
}
static void wave5_vpu_handle_irq(void *dev_id)
{
u32 seq_done;
u32 cmd_done;
u32 irq_reason;
u32 irq_subreason;
struct vpu_instance *inst, *tmp;
struct vpu_device *dev = dev_id;
int val;
unsigned long flags;
irq_reason = wave5_vdi_read_register(dev, W5_VPU_VINT_REASON);
seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST);
wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_reason);
wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1);
spin_lock_irqsave(&dev->irq_spinlock, flags);
list_for_each_entry_safe(inst, tmp, &dev->instances, list) {
if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
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);
complete(&inst->irq_done);
}
}
if (irq_reason & BIT(INT_WAVE5_DEC_PIC) ||
irq_reason & BIT(INT_WAVE5_ENC_PIC)) {
if (cmd_done & BIT(inst->id)) {
cmd_done &= ~BIT(inst->id);
if (dev->irq >= 0) {
irq_subreason =
wave5_vdi_read_register(dev, W5_VPU_VINT_REASON);
if (!(irq_subreason & BIT(INT_WAVE5_DEC_PIC)))
wave5_vdi_write_register(dev,
W5_RET_QUEUE_CMD_DONE_INST,
cmd_done);
}
val = BIT(INT_WAVE5_DEC_PIC);
kfifo_in(&inst->irq_status, &val, sizeof(int));
}
}
}
spin_unlock_irqrestore(&dev->irq_spinlock, flags);
if (dev->irq < 0)
up(&dev->irq_sem);
}
static irqreturn_t wave5_vpu_irq(int irq, void *dev_id)
{
struct vpu_device *dev = dev_id;
if (wave5_vdi_read_register(dev, W5_VPU_VPU_INT_STS)) {
wave5_vpu_handle_irq(dev);
return IRQ_WAKE_THREAD;
}
return IRQ_HANDLED;
}
static irqreturn_t wave5_vpu_irq_thread(int irq, void *dev_id)
{
struct vpu_device *dev = dev_id;
struct vpu_instance *inst, *tmp;
int irq_status, ret;
mutex_lock(&dev->irq_lock);
list_for_each_entry_safe(inst, tmp, &dev->instances, list) {
while (kfifo_len(&inst->irq_status)) {
ret = kfifo_out(&inst->irq_status, &irq_status, sizeof(int));
if (!ret)
break;
inst->ops->finish_process(inst);
}
}
mutex_unlock(&dev->irq_lock);
return IRQ_HANDLED;
}
static void wave5_vpu_irq_work_fn(struct kthread_work *work)
{
struct vpu_device *dev = container_of(work, struct vpu_device, work);
if (wave5_vdi_read_register(dev, W5_VPU_VPU_INT_STS))
wave5_vpu_handle_irq(dev);
}
static enum hrtimer_restart wave5_vpu_timer_callback(struct hrtimer *timer)
{
struct vpu_device *dev =
container_of(timer, struct vpu_device, hrtimer);
kthread_queue_work(dev->worker, &dev->work);
hrtimer_forward_now(timer, ns_to_ktime(vpu_poll_interval * NSEC_PER_MSEC));
return HRTIMER_RESTART;
}
static int irq_thread(void *data)
{
struct vpu_device *dev = (struct vpu_device *)data;
struct vpu_instance *inst, *tmp;
int irq_status, ret;
while (!kthread_should_stop()) {
if (down_interruptible(&dev->irq_sem))
continue;
if (kthread_should_stop())
break;
mutex_lock(&dev->irq_lock);
list_for_each_entry_safe(inst, tmp, &dev->instances, list) {
while (kfifo_len(&inst->irq_status)) {
ret = kfifo_out(&inst->irq_status, &irq_status, sizeof(int));
if (!ret)
break;
inst->ops->finish_process(inst);
}
}
mutex_unlock(&dev->irq_lock);
}
return 0;
}
static int wave5_vpu_load_firmware(struct device *dev, const char *fw_name,
u32 *revision)
{
const struct firmware *fw;
int ret;
unsigned int product_id;
ret = request_firmware(&fw, fw_name, dev);
if (ret) {
dev_err(dev, "request_firmware, fail: %d\n", ret);
return ret;
}
ret = wave5_vpu_init_with_bitcode(dev, (u8 *)fw->data, fw->size);
if (ret) {
dev_err(dev, "vpu_init_with_bitcode, fail: %d\n", ret);
release_firmware(fw);
return ret;
}
release_firmware(fw);
ret = wave5_vpu_get_version_info(dev, revision, &product_id);
if (ret) {
dev_err(dev, "vpu_get_version_info fail: %d\n", ret);
return ret;
}
dev_dbg(dev, "%s: enum product_id: %08x, fw revision: %u\n",
__func__, product_id, *revision);
return 0;
}
static __maybe_unused int wave5_pm_suspend(struct device *dev)
{
struct vpu_device *vpu = dev_get_drvdata(dev);
if (pm_runtime_suspended(dev))
return 0;
if (vpu->irq < 0)
hrtimer_cancel(&vpu->hrtimer);
wave5_vpu_sleep_wake(dev, true, NULL, 0);
clk_bulk_disable_unprepare(vpu->num_clks, vpu->clks);
return 0;
}
static __maybe_unused int wave5_pm_resume(struct device *dev)
{
struct vpu_device *vpu = dev_get_drvdata(dev);
int ret = 0;
wave5_vpu_sleep_wake(dev, false, NULL, 0);
ret = clk_bulk_prepare_enable(vpu->num_clks, vpu->clks);
if (ret) {
dev_err(dev, "Enabling clocks, fail: %d\n", ret);
return ret;
}
if (vpu->irq < 0 && !hrtimer_active(&vpu->hrtimer))
hrtimer_start(&vpu->hrtimer, ns_to_ktime(vpu->vpu_poll_interval * NSEC_PER_MSEC),
HRTIMER_MODE_REL_PINNED);
return ret;
}
static const struct dev_pm_ops wave5_pm_ops = {
SET_RUNTIME_PM_OPS(wave5_pm_suspend, wave5_pm_resume, NULL)
};
static int wave5_vpu_probe(struct platform_device *pdev)
{
int ret;
struct vpu_device *dev;
const struct wave5_match_data *match_data;
u32 fw_revision;
match_data = device_get_match_data(&pdev->dev);
if (!match_data) {
dev_err(&pdev->dev, "missing device match data\n");
return -EINVAL;
}
/* physical addresses limited to 32 bits */
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "Failed to set DMA mask: %d\n", ret);
return ret;
}
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->vdb_register = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dev->vdb_register))
return PTR_ERR(dev->vdb_register);
ida_init(&dev->inst_ida);
mutex_init(&dev->dev_lock);
mutex_init(&dev->hw_lock);
mutex_init(&dev->irq_lock);
spin_lock_init(&dev->irq_spinlock);
dev_set_drvdata(&pdev->dev, dev);
dev->dev = &pdev->dev;
dev->resets = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
if (IS_ERR(dev->resets)) {
return dev_err_probe(&pdev->dev, PTR_ERR(dev->resets),
"Failed to get reset control\n");
}
ret = reset_control_deassert(dev->resets);
if (ret)
return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");
ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
/* continue without clock, assume externally managed */
if (ret < 0) {
dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret);
ret = 0;
}
dev->num_clks = ret;
ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
if (ret) {
dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
goto err_reset_assert;
}
dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
if (!dev->sram_pool)
dev_warn(&pdev->dev, "sram node not found\n");
dev->sram_size = match_data->sram_size;
dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER);
ret = wave5_vdi_init(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret);
goto err_clk_dis;
}
dev->product = wave5_vpu_get_product_id(dev);
INIT_LIST_HEAD(&dev->instances);
dev->irq = platform_get_irq(pdev, 0);
if (dev->irq < 0) {
dev_err(&pdev->dev, "failed to get irq resource, falling back to polling\n");
sema_init(&dev->irq_sem, 1);
dev->irq_thread = kthread_run(irq_thread, dev, "irq thread");
hrtimer_setup(&dev->hrtimer, &wave5_vpu_timer_callback, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_PINNED);
dev->worker = kthread_run_worker(0, "vpu_irq_thread");
if (IS_ERR(dev->worker)) {
dev_err(&pdev->dev, "failed to create vpu irq worker\n");
ret = PTR_ERR(dev->worker);
goto err_vdi_release;
}
dev->vpu_poll_interval = vpu_poll_interval;
kthread_init_work(&dev->work, wave5_vpu_irq_work_fn);
} else {
ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave5_vpu_irq,
wave5_vpu_irq_thread, IRQF_ONESHOT, "vpu_irq", dev);
if (ret) {
dev_err(&pdev->dev, "Register interrupt handler, fail: %d\n", ret);
goto err_enc_unreg;
}
}
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
dev_err(&pdev->dev, "v4l2_device_register, fail: %d\n", ret);
goto err_irq_release;
}
if (match_data->flags & WAVE5_IS_DEC) {
ret = wave5_vpu_dec_register_device(dev);
if (ret) {
dev_err(&pdev->dev, "wave5_vpu_dec_register_device, fail: %d\n", ret);
goto err_v4l2_unregister;
}
}
if (match_data->flags & WAVE5_IS_ENC) {
ret = wave5_vpu_enc_register_device(dev);
if (ret) {
dev_err(&pdev->dev, "wave5_vpu_enc_register_device, fail: %d\n", ret);
goto err_dec_unreg;
}
}
ret = wave5_vpu_load_firmware(&pdev->dev, match_data->fw_name, &fw_revision);
if (ret) {
dev_err(&pdev->dev, "wave5_vpu_load_firmware, fail: %d\n", ret);
goto err_enc_unreg;
}
dev_info(&pdev->dev, "Added wave5 driver with caps: %s %s\n",
(match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "",
(match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "");
dev_info(&pdev->dev, "Product Code: 0x%x\n", dev->product_code);
dev_info(&pdev->dev, "Firmware Revision: %u\n", fw_revision);
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
wave5_vpu_sleep_wake(&pdev->dev, true, NULL, 0);
return 0;
err_enc_unreg:
if (match_data->flags & WAVE5_IS_ENC)
wave5_vpu_enc_unregister_device(dev);
err_dec_unreg:
if (match_data->flags & WAVE5_IS_DEC)
wave5_vpu_dec_unregister_device(dev);
err_v4l2_unregister:
v4l2_device_unregister(&dev->v4l2_dev);
err_irq_release:
if (dev->irq < 0)
kthread_destroy_worker(dev->worker);
err_vdi_release:
if (dev->irq_thread) {
kthread_stop(dev->irq_thread);
up(&dev->irq_sem);
dev->irq_thread = NULL;
}
wave5_vdi_release(&pdev->dev);
err_clk_dis:
clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
err_reset_assert:
reset_control_assert(dev->resets);
return ret;
}
static void wave5_vpu_remove(struct platform_device *pdev)
{
struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
wave5_vpu_enc_unregister_device(dev);
wave5_vpu_dec_unregister_device(dev);
v4l2_device_unregister(&dev->v4l2_dev);
if (dev->irq < 0) {
if (dev->irq_thread) {
kthread_stop(dev->irq_thread);
up(&dev->irq_sem);
dev->irq_thread = NULL;
}
hrtimer_cancel(&dev->hrtimer);
kthread_cancel_work_sync(&dev->work);
kthread_destroy_worker(dev->worker);
}
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
mutex_destroy(&dev->dev_lock);
mutex_destroy(&dev->hw_lock);
mutex_destroy(&dev->irq_lock);
reset_control_assert(dev->resets);
clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
wave5_vdi_release(&pdev->dev);
ida_destroy(&dev->inst_ida);
}
static const struct wave5_match_data ti_wave521c_data = {
.flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
.fw_name = "cnm/wave521c_k3_codec_fw.bin",
.sram_size = (64 * 1024),
};
static const struct of_device_id wave5_dt_ids[] = {
{ .compatible = "ti,j721s2-wave521c", .data = &ti_wave521c_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, wave5_dt_ids);
static struct platform_driver wave5_vpu_driver = {
.driver = {
.name = VPU_PLATFORM_DEVICE_NAME,
.of_match_table = of_match_ptr(wave5_dt_ids),
.pm = &wave5_pm_ops,
},
.probe = wave5_vpu_probe,
.remove = wave5_vpu_remove,
};
module_platform_driver(wave5_vpu_driver);
MODULE_DESCRIPTION("chips&media VPU V4L2 driver");
MODULE_LICENSE("Dual BSD/GPL");
@@ -0,0 +1,85 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - basic types
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef __VPU_DRV_H__
#define __VPU_DRV_H__
#include <media/v4l2-ctrls.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-vmalloc.h>
#include "wave5-vpuconfig.h"
#include "wave5-vpuapi.h"
#define VPU_BUF_SYNC_TO_DEVICE 0
#define VPU_BUF_SYNC_FROM_DEVICE 1
struct vpu_src_buffer {
struct v4l2_m2m_buffer v4l2_m2m_buf;
bool consumed;
struct list_head list;
};
struct vpu_dst_buffer {
struct v4l2_m2m_buffer v4l2_m2m_buf;
bool display;
};
enum vpu_fmt_type {
VPU_FMT_TYPE_CODEC = 0,
VPU_FMT_TYPE_RAW = 1
};
struct vpu_format {
unsigned int v4l2_pix_fmt;
const struct v4l2_frmsize_stepwise *v4l2_frmsize;
};
static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh)
{
return container_of(vfh, struct vpu_instance, v4l2_fh);
}
static inline struct vpu_instance *file_to_vpu_inst(struct file *filp)
{
return wave5_to_vpu_inst(file_to_v4l2_fh(filp));
}
static inline struct vpu_instance *wave5_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl)
{
return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl);
}
static inline struct vpu_src_buffer *wave5_to_vpu_src_buf(struct vb2_v4l2_buffer *vbuf)
{
return container_of(vbuf, struct vpu_src_buffer, v4l2_m2m_buf.vb);
}
static inline struct vpu_dst_buffer *wave5_to_vpu_dst_buf(struct vb2_v4l2_buffer *vbuf)
{
return container_of(vbuf, struct vpu_dst_buffer, v4l2_m2m_buf.vb);
}
int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout);
int wave5_vpu_dec_register_device(struct vpu_device *dev);
void wave5_vpu_dec_unregister_device(struct vpu_device *dev);
int wave5_vpu_enc_register_device(struct vpu_device *dev);
void wave5_vpu_enc_unregister_device(struct vpu_device *dev);
static inline bool wave5_vpu_both_queues_are_streaming(struct vpu_instance *inst)
{
struct vb2_queue *vq_cap =
v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
struct vb2_queue *vq_out =
v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
return vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out);
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,892 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - helper definitions
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef VPUAPI_H_INCLUDED
#define VPUAPI_H_INCLUDED
#include <linux/kfifo.h>
#include <linux/idr.h>
#include <linux/genalloc.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-ctrls.h>
#include "wave5-vpuerror.h"
#include "wave5-vpuconfig.h"
#include "wave5-vdi.h"
enum product_id {
PRODUCT_ID_515,
PRODUCT_ID_521,
PRODUCT_ID_511,
PRODUCT_ID_517,
PRODUCT_ID_NONE,
};
struct vpu_attr;
enum vpu_instance_type {
VPU_INST_TYPE_DEC = 0,
VPU_INST_TYPE_ENC = 1
};
enum vpu_instance_state {
VPU_INST_STATE_NONE = 0,
VPU_INST_STATE_OPEN = 1,
VPU_INST_STATE_INIT_SEQ = 2,
VPU_INST_STATE_PIC_RUN = 3,
VPU_INST_STATE_STOP = 4
};
/* Maximum available on hardware. */
#define WAVE5_MAX_FBS 32
#define MAX_REG_FRAME (WAVE5_MAX_FBS * 2)
#define WAVE5_DEC_HEVC_BUF_SIZE(_w, _h) (DIV_ROUND_UP(_w, 64) * DIV_ROUND_UP(_h, 64) * 256 + 64)
#define WAVE5_DEC_AVC_BUF_SIZE(_w, _h) ((((ALIGN(_w, 256) / 16) * (ALIGN(_h, 16) / 16)) + 16) * 80)
#define WAVE5_FBC_LUMA_TABLE_SIZE(_w, _h) (ALIGN(_h, 64) * ALIGN(_w, 256) / 32)
#define WAVE5_FBC_CHROMA_TABLE_SIZE(_w, _h) (ALIGN((_h), 64) * ALIGN((_w) / 2, 256) / 32)
#define WAVE5_ENC_AVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) * ALIGN(_h, 64) / 32)
#define WAVE5_ENC_HEVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) / 64 * ALIGN(_h, 64) / 64 * 128)
/*
* common struct and definition
*/
enum cod_std {
STD_AVC = 0,
STD_HEVC = 12,
STD_MAX
};
enum wave_std {
W_HEVC_DEC = 0x00,
W_HEVC_ENC = 0x01,
W_AVC_DEC = 0x02,
W_AVC_ENC = 0x03,
STD_UNKNOWN = 0xFF
};
enum set_param_option {
OPT_COMMON = 0, /* SET_PARAM command option for encoding sequence */
OPT_CUSTOM_GOP = 1, /* SET_PARAM command option for setting custom GOP */
OPT_CUSTOM_HEADER = 2, /* SET_PARAM command option for setting custom VPS/SPS/PPS */
OPT_VUI = 3, /* SET_PARAM command option for encoding VUI */
OPT_CHANGE_PARAM = 0x10,
};
/************************************************************************/
/* PROFILE & LEVEL */
/************************************************************************/
/* HEVC */
#define HEVC_PROFILE_MAIN 1
#define HEVC_PROFILE_MAIN10 2
#define HEVC_PROFILE_STILLPICTURE 3
#define HEVC_PROFILE_MAIN10_STILLPICTURE 2
/* H.264 profile for encoder*/
#define H264_PROFILE_BP 1
#define H264_PROFILE_MP 2
#define H264_PROFILE_EXTENDED 3
#define H264_PROFILE_HP 4
#define H264_PROFILE_HIGH10 5
#define H264_PROFILE_HIGH422 6
#define H264_PROFILE_HIGH444 7
/************************************************************************/
/* error codes */
/************************************************************************/
/************************************************************************/
/* utility macros */
/************************************************************************/
/* Initialize sequence firmware command mode */
#define INIT_SEQ_NORMAL 1
/* Decode firmware command mode */
#define DEC_PIC_NORMAL 0
/* bit_alloc_mode */
#define BIT_ALLOC_MODE_FIXED_RATIO 2
/* bit_rate */
#define MAX_BIT_RATE 700000000
/* decoding_refresh_type */
#define DEC_REFRESH_TYPE_NON_IRAP 0
#define DEC_REFRESH_TYPE_CRA 1
#define DEC_REFRESH_TYPE_IDR 2
/* depend_slice_mode */
#define DEPEND_SLICE_MODE_RECOMMENDED 1
#define DEPEND_SLICE_MODE_BOOST 2
#define DEPEND_SLICE_MODE_FAST 3
/* hvs_max_delta_qp */
#define MAX_HVS_MAX_DELTA_QP 51
/* intra_refresh_mode */
#define REFRESH_MODE_CTU_ROWS 1
#define REFRESH_MODE_CTU_COLUMNS 2
#define REFRESH_MODE_CTU_STEP_SIZE 3
#define REFRESH_MODE_CTUS 4
/* intra_mb_refresh_mode */
#define REFRESH_MB_MODE_NONE 0
#define REFRESH_MB_MODE_CTU_ROWS 1
#define REFRESH_MB_MODE_CTU_COLUMNS 2
#define REFRESH_MB_MODE_CTU_STEP_SIZE 3
/* intra_qp */
#define MAX_INTRA_QP 63
/* nr_inter_weight_* */
#define MAX_INTER_WEIGHT 31
/* nr_intra_weight_* */
#define MAX_INTRA_WEIGHT 31
/* nr_noise_sigma_* */
#define MAX_NOISE_SIGMA 255
/* bitstream_buffer_size */
#define MIN_BITSTREAM_BUFFER_SIZE 1024
#define MIN_BITSTREAM_BUFFER_SIZE_WAVE521 (1024 * 64)
/* vbv_buffer_size */
#define MIN_VBV_BUFFER_SIZE 10
#define MAX_VBV_BUFFER_SIZE 3000
#define BUFFER_MARGIN 4096
#define MAX_FIRMWARE_CALL_RETRY 10
#define VDI_LITTLE_ENDIAN 0x0
/*
* Parameters of DEC_SET_SEQ_CHANGE_MASK
*/
#define SEQ_CHANGE_ENABLE_PROFILE BIT(5)
#define SEQ_CHANGE_ENABLE_SIZE BIT(16)
#define SEQ_CHANGE_ENABLE_BITDEPTH BIT(18)
#define SEQ_CHANGE_ENABLE_DPB_COUNT BIT(19)
#define SEQ_CHANGE_ENABLE_ASPECT_RATIO BIT(21)
#define SEQ_CHANGE_ENABLE_VIDEO_SIGNAL BIT(23)
#define SEQ_CHANGE_ENABLE_VUI_TIMING_INFO BIT(29)
#define SEQ_CHANGE_ENABLE_ALL_HEVC (SEQ_CHANGE_ENABLE_PROFILE | \
SEQ_CHANGE_ENABLE_SIZE | \
SEQ_CHANGE_ENABLE_BITDEPTH | \
SEQ_CHANGE_ENABLE_DPB_COUNT)
#define SEQ_CHANGE_ENABLE_ALL_AVC (SEQ_CHANGE_ENABLE_SIZE | \
SEQ_CHANGE_ENABLE_BITDEPTH | \
SEQ_CHANGE_ENABLE_DPB_COUNT | \
SEQ_CHANGE_ENABLE_ASPECT_RATIO | \
SEQ_CHANGE_ENABLE_VIDEO_SIGNAL | \
SEQ_CHANGE_ENABLE_VUI_TIMING_INFO)
#define DISPLAY_IDX_FLAG_SEQ_END -1
#define DISPLAY_IDX_FLAG_NO_FB -3
#define DECODED_IDX_FLAG_NO_FB -1
#define DECODED_IDX_FLAG_SKIP -2
#define RECON_IDX_FLAG_ENC_END -1
#define RECON_IDX_FLAG_ENC_DELAY -2
#define RECON_IDX_FLAG_HEADER_ONLY -3
#define RECON_IDX_FLAG_CHANGE_PARAM -4
enum codec_command {
ENABLE_ROTATION,
ENABLE_MIRRORING,
SET_MIRROR_DIRECTION,
SET_ROTATION_ANGLE,
DEC_GET_QUEUE_STATUS,
ENC_GET_QUEUE_STATUS,
DEC_RESET_FRAMEBUF_INFO,
DEC_GET_SEQ_INFO,
};
enum mirror_direction {
MIRDIR_NONE, /* no mirroring */
MIRDIR_VER, /* vertical mirroring */
MIRDIR_HOR, /* horizontal mirroring */
MIRDIR_HOR_VER /* horizontal and vertical mirroring */
};
enum frame_buffer_format {
FORMAT_ERR = -1,
FORMAT_420 = 0, /* 8bit */
FORMAT_422, /* 8bit */
FORMAT_224, /* 8bit */
FORMAT_444, /* 8bit */
FORMAT_400, /* 8bit */
/* little endian perspective */
/* | addr 0 | addr 1 | */
FORMAT_420_P10_16BIT_MSB = 5, /* lsb |000000xx|xxxxxxxx | msb */
FORMAT_420_P10_16BIT_LSB, /* lsb |xxxxxxx |xx000000 | msb */
FORMAT_420_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */
FORMAT_420_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */
/* 4:2:2 packed format */
/* little endian perspective */
/* | addr 0 | addr 1 | */
FORMAT_422_P10_16BIT_MSB, /* lsb |000000xx |xxxxxxxx | msb */
FORMAT_422_P10_16BIT_LSB, /* lsb |xxxxxxxx |xx000000 | msb */
FORMAT_422_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */
FORMAT_422_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */
FORMAT_YUYV, /* 8bit packed format : Y0U0Y1V0 Y2U1Y3V1 ... */
FORMAT_YUYV_P10_16BIT_MSB,
FORMAT_YUYV_P10_16BIT_LSB,
FORMAT_YUYV_P10_32BIT_MSB,
FORMAT_YUYV_P10_32BIT_LSB,
FORMAT_YVYU, /* 8bit packed format : Y0V0Y1U0 Y2V1Y3U1 ... */
FORMAT_YVYU_P10_16BIT_MSB,
FORMAT_YVYU_P10_16BIT_LSB,
FORMAT_YVYU_P10_32BIT_MSB,
FORMAT_YVYU_P10_32BIT_LSB,
FORMAT_UYVY, /* 8bit packed format : U0Y0V0Y1 U1Y2V1Y3 ... */
FORMAT_UYVY_P10_16BIT_MSB,
FORMAT_UYVY_P10_16BIT_LSB,
FORMAT_UYVY_P10_32BIT_MSB,
FORMAT_UYVY_P10_32BIT_LSB,
FORMAT_VYUY, /* 8bit packed format : V0Y0U0Y1 V1Y2U1Y3 ... */
FORMAT_VYUY_P10_16BIT_MSB,
FORMAT_VYUY_P10_16BIT_LSB,
FORMAT_VYUY_P10_32BIT_MSB,
FORMAT_VYUY_P10_32BIT_LSB,
FORMAT_MAX,
};
enum packed_format_num {
NOT_PACKED = 0,
PACKED_YUYV,
PACKED_YVYU,
PACKED_UYVY,
PACKED_VYUY,
};
enum wave5_interrupt_bit {
INT_WAVE5_INIT_VPU = 0,
INT_WAVE5_WAKEUP_VPU = 1,
INT_WAVE5_SLEEP_VPU = 2,
INT_WAVE5_CREATE_INSTANCE = 3,
INT_WAVE5_FLUSH_INSTANCE = 4,
INT_WAVE5_DESTROY_INSTANCE = 5,
INT_WAVE5_INIT_SEQ = 6,
INT_WAVE5_SET_FRAMEBUF = 7,
INT_WAVE5_DEC_PIC = 8,
INT_WAVE5_ENC_PIC = 8,
INT_WAVE5_ENC_SET_PARAM = 9,
INT_WAVE5_DEC_QUERY = 14,
INT_WAVE5_BSBUF_EMPTY = 15,
INT_WAVE5_BSBUF_FULL = 15,
};
enum pic_type {
PIC_TYPE_I = 0,
PIC_TYPE_P = 1,
PIC_TYPE_B = 2,
PIC_TYPE_IDR = 5, /* H.264/H.265 IDR (Instantaneous Decoder Refresh) picture */
PIC_TYPE_MAX /* no meaning */
};
enum sw_reset_mode {
SW_RESET_SAFETY,
SW_RESET_FORCE,
SW_RESET_ON_BOOT
};
enum tiled_map_type {
LINEAR_FRAME_MAP = 0, /* linear frame map type */
COMPRESSED_FRAME_MAP = 17, /* compressed frame map type*/
};
enum temporal_id_mode {
TEMPORAL_ID_MODE_ABSOLUTE,
TEMPORAL_ID_MODE_RELATIVE,
};
struct vpu_attr {
u32 product_id;
char product_name[8]; /* product name in ascii code */
u32 product_version;
u32 fw_version;
u32 customer_id;
u32 support_decoders; /* bitmask */
u32 support_encoders; /* bitmask */
u32 support_backbone: 1;
u32 support_avc10bit_enc: 1;
u32 support_hevc10bit_enc: 1;
u32 support_hevc10bit_dec: 1;
u32 support_vcore_backbone: 1;
u32 support_vcpu_backbone: 1;
};
struct frame_buffer {
dma_addr_t buf_y;
dma_addr_t buf_cb;
dma_addr_t buf_cr;
unsigned int buf_y_size;
unsigned int buf_cb_size;
unsigned int buf_cr_size;
enum tiled_map_type map_type;
unsigned int stride; /* horizontal stride for the given frame buffer */
unsigned int width; /* width of the given frame buffer */
unsigned int height; /* height of the given frame buffer */
size_t size; /* size of the given frame buffer */
unsigned int sequence_no;
bool update_fb_info;
};
struct vpu_rect {
unsigned int left; /* horizontal pixel offset from left edge */
unsigned int top; /* vertical pixel offset from top edge */
unsigned int right; /* horizontal pixel offset from right edge */
unsigned int bottom; /* vertical pixel offset from bottom edge */
};
/*
* decode struct and definition
*/
struct dec_open_param {
dma_addr_t bitstream_buffer;
size_t bitstream_buffer_size;
};
struct dec_initial_info {
u32 pic_width;
u32 pic_height;
struct vpu_rect pic_crop_rect;
u32 min_frame_buffer_count; /* between 1 to 16 */
u32 profile;
u32 luma_bitdepth; /* bit-depth of the luma sample */
u32 chroma_bitdepth; /* bit-depth of the chroma sample */
u32 seq_init_err_reason;
dma_addr_t rd_ptr; /* read pointer of bitstream buffer */
dma_addr_t wr_ptr; /* write pointer of bitstream buffer */
u32 sequence_no;
u32 vlc_buf_size;
u32 param_buf_size;
};
struct dec_output_info {
/**
* This is a frame buffer index for the picture to be displayed at the moment
* among frame buffers which are registered using vpu_dec_register_frame_buffer().
* Frame data that will be displayed is stored in the frame buffer with this index
* When there is no display delay, this index is always the equal to
* index_frame_decoded, however, if displaying is delayed (for display
* reordering in AVC or B-frames in VC1), this index might be different to
* index_frame_decoded. By checking this index, HOST applications can easily figure
* out whether sequence decoding has been finished or not.
*
* -3(0xFFFD) or -2(0xFFFE) : when a display output cannot be given due to picture
* reordering or skip option
* -1(0xFFFF) : when there is no more output for display at the end of sequence
* decoding
*/
s32 index_frame_display;
/**
* This is the frame buffer index of the decoded picture among the frame buffers which were
* registered using vpu_dec_register_frame_buffer(). The currently decoded frame is stored
* into the frame buffer specified by this index.
*
* -2 : indicates that no decoded output is generated because decoder meets EOS
* (end of sequence) or skip
* -1 : indicates that the decoder fails to decode a picture because there is no available
* frame buffer
*/
s32 index_frame_decoded;
s32 index_frame_decoded_for_tiled;
u32 nal_type;
unsigned int pic_type;
struct vpu_rect rc_display;
unsigned int disp_pic_width;
unsigned int disp_pic_height;
struct vpu_rect rc_decoded;
u32 dec_pic_width;
u32 dec_pic_height;
s32 decoded_poc;
int temporal_id; /* temporal ID of the picture */
dma_addr_t rd_ptr; /* stream buffer read pointer for the current decoder instance */
dma_addr_t wr_ptr; /* stream buffer write pointer for the current decoder instance */
struct frame_buffer disp_frame;
u32 frame_display_flag; /* it reports a frame buffer flag to be displayed */
/**
* this variable reports that sequence has been changed while H.264/AVC stream decoding.
* if it is 1, HOST application can get the new sequence information by calling
* vpu_dec_get_initial_info() or wave5_vpu_dec_issue_seq_init().
*
* for H.265/HEVC decoder, each bit has a different meaning as follows.
*
* sequence_changed[5] : it indicates that the profile_idc has been changed
* sequence_changed[16] : it indicates that the resolution has been changed
* sequence_changed[19] : it indicates that the required number of frame buffer has
* been changed.
*/
unsigned int frame_cycle; /* reports the number of cycles for processing a frame */
u32 sequence_no;
u32 dec_host_cmd_tick; /* tick of DEC_PIC command for the picture */
u32 dec_decode_end_tick; /* end tick of decoding slices of the picture */
u32 sequence_changed;
};
struct queue_status_info {
u32 instance_queue_count;
u32 report_queue_count;
};
/*
* encode struct and definition
*/
#define MAX_NUM_TEMPORAL_LAYER 7
#define MAX_NUM_SPATIAL_LAYER 3
#define MAX_GOP_NUM 8
struct custom_gop_pic_param {
u32 pic_type; /* picture type of nth picture in the custom GOP */
u32 poc_offset; /* POC of nth picture in the custom GOP */
u32 pic_qp; /* quantization parameter of nth picture in the custom GOP */
u32 use_multi_ref_p; /* use multiref pic for P picture. valid only if PIC_TYPE is P */
u32 ref_poc_l0; /* POC of reference L0 of nth picture in the custom GOP */
u32 ref_poc_l1; /* POC of reference L1 of nth picture in the custom GOP */
s32 temporal_id; /* temporal ID of nth picture in the custom GOP */
};
struct enc_wave_param {
/*
* profile indicator (HEVC only)
*
* 0 : the firmware determines a profile according to the internal_bit_depth
* 1 : main profile
* 2 : main10 profile
* 3 : main still picture profile
* In the AVC encoder, a profile cannot be set by the host application.
* The firmware decides it based on internal_bit_depth.
* profile = HIGH (bitdepth 8) profile = HIGH10 (bitdepth 10)
*/
u32 profile;
u32 level; /* level indicator (level * 10) */
u32 internal_bit_depth: 4; /* 8/10 */
u32 gop_preset_idx: 4; /* 0 - 9 */
u32 decoding_refresh_type: 2; /* 0=non-IRAP, 1=CRA, 2=IDR */
u32 intra_qp; /* quantization parameter of intra picture */
u32 intra_period; /* period of intra picture in GOP size */
u32 conf_win_top; /* top offset of conformance window */
u32 conf_win_bot; /* bottom offset of conformance window */
u32 conf_win_left; /* left offset of conformance window */
u32 conf_win_right; /* right offset of conformance window */
u32 intra_refresh_mode: 3;
/*
* Argument for intra_ctu_refresh_mode.
*
* Depending on intra_refresh_mode, it can mean one of the following:
* - intra_ctu_refresh_mode (1) -> number of consecutive CTU rows
* - intra_ctu_refresh_mode (2) -> the number of consecutive CTU columns
* - intra_ctu_refresh_mode (3) -> step size in CTU
* - intra_ctu_refresh_mode (4) -> number of intra ct_us to be encoded in a picture
*/
u32 intra_refresh_arg;
/*
* 0 : custom setting
* 1 : recommended encoder parameters (slow encoding speed, highest picture quality)
* 2 : boost mode (normal encoding speed, moderate picture quality)
* 3 : fast mode (fast encoding speed, low picture quality)
*/
u32 depend_slice_mode : 2;
u32 depend_slice_mode_arg;
u32 independ_slice_mode : 1; /* 0=no-multi-slice, 1=slice-in-ctu-number*/
u32 independ_slice_mode_arg;
u32 max_num_merge: 2;
s32 beta_offset_div2: 4; /* sets beta_offset_div2 for deblocking filter */
s32 tc_offset_div2: 4; /* sets tc_offset_div3 for deblocking filter */
u32 hvs_qp_scale: 4; /* QP scaling factor for CU QP adjust if hvs_qp_scale_enable is 1 */
u32 hvs_max_delta_qp; /* maximum delta QP for HVS */
s32 chroma_cb_qp_offset; /* the value of chroma(cb) QP offset */
s32 chroma_cr_qp_offset; /* the value of chroma(cr) QP offset */
s32 initial_rc_qp;
u32 nr_intra_weight_y;
u32 nr_intra_weight_cb; /* weight to cb noise level for intra picture (0 ~ 31) */
u32 nr_intra_weight_cr; /* weight to cr noise level for intra picture (0 ~ 31) */
u32 nr_inter_weight_y;
u32 nr_inter_weight_cb; /* weight to cb noise level for inter picture (0 ~ 31) */
u32 nr_inter_weight_cr; /* weight to cr noise level for inter picture (0 ~ 31) */
u32 min_qp_i; /* minimum QP of I picture for rate control */
u32 max_qp_i; /* maximum QP of I picture for rate control */
u32 min_qp_p; /* minimum QP of P picture for rate control */
u32 max_qp_p; /* maximum QP of P picture for rate control */
u32 min_qp_b; /* minimum QP of B picture for rate control */
u32 max_qp_b; /* maximum QP of B picture for rate control */
u32 avc_idr_period; /* period of IDR picture (0 ~ 1024). 0 - implies an infinite period */
u32 avc_slice_arg; /* the number of MB for a slice when avc_slice_mode is set with 1 */
u32 intra_mb_refresh_mode: 2; /* 0=none, 1=row, 2=column, 3=step-size-in-mb */
/**
* Argument for intra_mb_refresh_mode.
*
* intra_mb_refresh_mode (1) -> number of consecutive MB rows
* intra_mb_refresh_mode (2) ->the number of consecutive MB columns
* intra_mb_refresh_mode (3) -> step size in MB
*/
u32 intra_mb_refresh_arg;
u32 rc_weight_param;
u32 rc_weight_buf;
/* flags */
u32 en_still_picture: 1; /* still picture profile */
u32 tier: 1; /* 0=main, 1=high */
u32 avc_slice_mode: 1; /* 0=none, 1=slice-in-mb-number */
u32 entropy_coding_mode: 1; /* 0=CAVLC, 1=CABAC */
u32 lossless_enable: 1; /* enable lossless encoding */
u32 const_intra_pred_flag: 1; /* enable constrained intra prediction */
u32 tmvp_enable: 1; /* enable temporal motion vector prediction */
u32 wpp_enable: 1;
u32 disable_deblk: 1; /* disable in-loop deblocking filtering */
u32 lf_cross_slice_boundary_enable: 1;
u32 skip_intra_trans: 1;
u32 sao_enable: 1; /* enable SAO (sample adaptive offset) */
u32 intra_nx_n_enable: 1; /* enables intra nx_n p_us */
u32 cu_level_rc_enable: 1; /* enable CU level rate control */
u32 hvs_qp_enable: 1; /* enable CU QP adjustment for subjective quality enhancement */
u32 strong_intra_smooth_enable: 1; /* enable strong intra smoothing */
u32 rdo_skip: 1; /* skip RDO (rate distortion optimization) */
u32 lambda_scaling_enable: 1; /* enable lambda scaling using custom GOP */
u32 transform8x8_enable: 1; /* enable 8x8 intra prediction and 8x8 transform */
u32 mb_level_rc_enable: 1; /* enable MB-level rate control */
u32 forced_idr_header_enable: 1; /* enable header encoding before IDR frame */
u32 constraint_set1_flag: 1; /* enable CBP */
u32 bg_detection: 1; /* enable background detection */
};
struct enc_open_param {
dma_addr_t bitstream_buffer;
unsigned int bitstream_buffer_size;
u32 pic_width; /* width of a picture to be encoded in unit of sample */
u32 pic_height; /* height of a picture to be encoded in unit of sample */
u32 frame_rate_info;/* desired fps */
u32 vbv_buffer_size;
u32 bit_rate; /* target bitrate in bps */
struct enc_wave_param wave_param;
enum packed_format_num packed_format; /* <<vpuapi_h_packed_format_num>> */
enum frame_buffer_format src_format;
bool line_buf_int_en;
u32 rc_enable : 1; /* rate control */
};
struct enc_initial_info {
u32 min_frame_buffer_count; /* minimum number of frame buffers */
u32 min_src_frame_count; /* minimum number of source buffers */
u32 seq_init_err_reason;
u32 warn_info;
u32 vlc_buf_size; /* size of task buffer */
u32 param_buf_size; /* size of task buffer */
};
/*
* Flags to encode NAL units explicitly
*/
struct enc_code_opt {
u32 implicit_header_encode: 1;
u32 encode_vcl: 1;
u32 encode_vps: 1;
u32 encode_sps: 1;
u32 encode_pps: 1;
u32 encode_aud: 1;
u32 encode_eos: 1;
u32 encode_eob: 1;
u32 encode_vui: 1;
};
struct enc_param {
struct frame_buffer *source_frame;
u32 pic_stream_buffer_addr;
u64 pic_stream_buffer_size;
u32 src_idx; /* source frame buffer index */
struct enc_code_opt code_option;
u64 pts; /* presentation timestamp (PTS) of the input source */
bool src_end_flag;
};
struct enc_output_info {
u32 bitstream_buffer;
u32 bitstream_size; /* byte size of encoded bitstream */
u32 pic_type: 2; /* <<vpuapi_h_pic_type>> */
s32 recon_frame_index;
dma_addr_t rd_ptr;
dma_addr_t wr_ptr;
u32 enc_pic_byte; /* number of encoded picture bytes */
s32 enc_src_idx; /* source buffer index of the currently encoded picture */
u32 enc_vcl_nut;
u32 error_reason; /* error reason of the currently encoded picture */
u32 warn_info; /* warning information on the currently encoded picture */
unsigned int frame_cycle; /* param for reporting the cycle number of encoding one frame*/
u64 pts;
u32 enc_host_cmd_tick; /* tick of ENC_PIC command for the picture */
u32 enc_encode_end_tick; /* end tick of encoding slices of the picture */
};
enum enc_pic_code_option {
CODEOPT_ENC_HEADER_IMPLICIT = BIT(0),
CODEOPT_ENC_VCL = BIT(1), /* flag to encode VCL nal unit explicitly */
};
enum gop_preset_idx {
PRESET_IDX_CUSTOM_GOP = 0, /* user defined GOP structure */
PRESET_IDX_ALL_I = 1, /* all intra, gopsize = 1 */
PRESET_IDX_IPP = 2, /* consecutive P, cyclic gopsize = 1 */
PRESET_IDX_IBBB = 3, /* consecutive B, cyclic gopsize = 1 */
PRESET_IDX_IBPBP = 4, /* gopsize = 2 */
PRESET_IDX_IBBBP = 5, /* gopsize = 4 */
PRESET_IDX_IPPPP = 6, /* consecutive P, cyclic gopsize = 4 */
PRESET_IDX_IBBBB = 7, /* consecutive B, cyclic gopsize = 4 */
PRESET_IDX_RA_IB = 8, /* random access, cyclic gopsize = 8 */
PRESET_IDX_IPP_SINGLE = 9, /* consecutive P, cyclic gopsize = 1, with single ref */
};
struct sec_axi_info {
u32 use_ip_enable;
u32 use_bit_enable;
u32 use_lf_row_enable: 1;
u32 use_enc_rdo_enable: 1;
u32 use_enc_lf_enable: 1;
};
struct dec_info {
struct dec_open_param open_param;
struct dec_initial_info initial_info;
struct dec_initial_info new_seq_info; /* temporal new sequence information */
u32 stream_wr_ptr;
u32 stream_rd_ptr;
u32 frame_display_flag;
dma_addr_t stream_buf_start_addr;
dma_addr_t stream_buf_end_addr;
u32 stream_buf_size;
struct vpu_buf vb_mv[MAX_REG_FRAME];
struct vpu_buf vb_fbc_y_tbl[MAX_REG_FRAME];
struct vpu_buf vb_fbc_c_tbl[MAX_REG_FRAME];
unsigned int num_of_decoding_fbs: 7;
unsigned int num_of_display_fbs: 7;
unsigned int stride;
struct sec_axi_info sec_axi_info;
dma_addr_t user_data_buf_addr;
u32 user_data_enable;
u32 user_data_buf_size;
struct vpu_buf vb_work;
struct vpu_buf vb_task;
struct dec_output_info dec_out_info[WAVE5_MAX_FBS];
u32 seq_change_mask;
enum temporal_id_mode temp_id_select_mode;
u32 target_temp_id;
u32 target_spatial_id;
u32 instance_queue_count;
u32 report_queue_count;
u32 cycle_per_tick;
u32 product_code;
u32 vlc_buf_size;
u32 param_buf_size;
bool initial_info_obtained;
bool reorder_enable;
bool first_cycle_check;
u32 stream_endflag: 1;
};
struct enc_info {
struct enc_open_param open_param;
struct enc_initial_info initial_info;
u32 stream_rd_ptr;
u32 stream_wr_ptr;
dma_addr_t stream_buf_start_addr;
dma_addr_t stream_buf_end_addr;
u32 stream_buf_size;
unsigned int num_frame_buffers;
unsigned int stride;
bool rotation_enable;
bool mirror_enable;
enum mirror_direction mirror_direction;
unsigned int rotation_angle;
bool initial_info_obtained;
struct sec_axi_info sec_axi_info;
bool line_buf_int_en;
struct vpu_buf vb_work;
struct vpu_buf vb_mv; /* col_mv buffer */
struct vpu_buf vb_fbc_y_tbl; /* FBC luma table buffer */
struct vpu_buf vb_fbc_c_tbl; /* FBC chroma table buffer */
struct vpu_buf vb_sub_sam_buf; /* sub-sampled buffer for ME */
struct vpu_buf vb_task;
u64 cur_pts; /* current timestamp in 90_k_hz */
u64 pts_map[32]; /* PTS mapped with source frame index */
u32 instance_queue_count;
u32 report_queue_count;
bool first_cycle_check;
u32 cycle_per_tick;
u32 product_code;
u32 vlc_buf_size;
u32 param_buf_size;
};
struct vpu_device {
struct device *dev;
struct v4l2_device v4l2_dev;
struct v4l2_m2m_dev *v4l2_m2m_dec_dev;
struct v4l2_m2m_dev *v4l2_m2m_enc_dev;
struct list_head instances;
struct video_device *video_dev_dec;
struct video_device *video_dev_enc;
struct mutex dev_lock; /* lock for the src, dst v4l2 queues */
struct mutex hw_lock; /* lock hw configurations */
struct mutex irq_lock;
int irq;
enum product_id product;
struct vpu_attr attr;
struct vpu_buf common_mem;
u32 last_performance_cycles;
u32 sram_size;
struct gen_pool *sram_pool;
struct vpu_buf sram_buf;
void __iomem *vdb_register;
u32 product_code;
struct ida inst_ida;
struct clk_bulk_data *clks;
struct hrtimer hrtimer;
struct kthread_work work;
struct kthread_worker *worker;
int vpu_poll_interval;
int num_clks;
struct task_struct *irq_thread;
struct semaphore irq_sem; /* signal to irq_thread when interrupt happens*/
struct reset_control *resets;
spinlock_t irq_spinlock; /* protect instances list */
};
struct vpu_instance;
struct vpu_instance_ops {
void (*finish_process)(struct vpu_instance *inst);
};
struct vpu_instance {
struct list_head list;
struct v4l2_fh v4l2_fh;
struct v4l2_m2m_dev *v4l2_m2m_dev;
struct v4l2_ctrl_handler v4l2_ctrl_hdl;
struct vpu_device *dev;
struct completion irq_done;
struct v4l2_pix_format_mplane src_fmt;
struct v4l2_pix_format_mplane dst_fmt;
enum v4l2_colorspace colorspace;
enum v4l2_xfer_func xfer_func;
enum v4l2_ycbcr_encoding ycbcr_enc;
enum v4l2_quantization quantization;
struct kfifo irq_status;
enum vpu_instance_state state;
enum vpu_instance_type type;
const struct vpu_instance_ops *ops;
spinlock_t state_spinlock; /* This protects the instance state */
enum wave_std std;
s32 id;
union {
struct enc_info enc_info;
struct dec_info dec_info;
} *codec_info;
struct frame_buffer frame_buf[MAX_REG_FRAME];
struct vpu_buf frame_vbuf[MAX_REG_FRAME];
u32 fbc_buf_count;
u32 queued_src_buf_num;
u32 queued_dst_buf_num;
struct list_head avail_src_bufs;
struct list_head avail_dst_bufs;
struct v4l2_rect conf_win;
u64 timestamp;
enum frame_buffer_format output_format;
bool cbcr_interleave;
bool nv21;
bool eos;
bool sent_eos; /* check if EOS is sent to application */
bool retry; /* retry to feed bitstream if failure reason is WAVE5_SYSERR_QUEUEING_FAIL*/
int queuing_num; /* count of bitstream queued */
struct mutex feed_lock; /* lock for feeding bitstream buffers */
bool queuing_fail; /* if there is the queuing failure */
bool empty_queue;
struct vpu_buf bitstream_vbuf;
dma_addr_t last_rd_ptr;
size_t remaining_consumed_bytes;
bool needs_reallocation;
unsigned int min_src_buf_count;
unsigned int rot_angle;
unsigned int mirror_direction;
unsigned int bit_depth;
unsigned int frame_rate;
unsigned int vbv_buf_size;
unsigned int rc_mode;
unsigned int rc_enable;
unsigned int bit_rate;
unsigned int encode_aud;
struct enc_wave_param enc_param;
};
void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data);
u32 wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr);
int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count,
size_t size);
int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset,
u8 *data, size_t len);
int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev);
void wave5_vdi_free_sram(struct vpu_device *vpu_dev);
int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size);
int wave5_vpu_flush_instance(struct vpu_instance *inst);
int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id);
int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param);
int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res);
int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst);
int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info);
int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs,
int num_of_display_fbs, int stride, int height);
int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, u32 *res_fail);
int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info);
int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr);
dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst);
int wave5_vpu_dec_reset_framebuffer(struct vpu_instance *inst, unsigned int index);
int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter);
int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr,
dma_addr_t *pwr_ptr, size_t *size);
int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size);
int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index);
int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index);
int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param);
int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res);
int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst);
int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info);
int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num,
unsigned int stride, int height,
enum tiled_map_type map_type);
int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param,
u32 *fail_res);
int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info);
int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter);
#endif
@@ -0,0 +1,103 @@
/* 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 WAVE515_CODE 0x5150
#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) || (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
#define W5_DEF_DEC_PIC_WIDTH 720U
#define W5_DEF_DEC_PIC_HEIGHT 480U
#define W5_MIN_DEC_PIC_8_WIDTH 8U
#define W5_MIN_DEC_PIC_8_HEIGHT 8U
#define W5_MIN_DEC_PIC_32_WIDTH 32U
#define W5_MIN_DEC_PIC_32_HEIGHT 32U
#define W5_MAX_DEC_PIC_WIDTH 8192U
#define W5_MAX_DEC_PIC_HEIGHT 4320U
#define W5_DEC_CODEC_STEP_WIDTH 1U
#define W5_DEC_CODEC_STEP_HEIGHT 1U
#define W5_DEC_RAW_STEP_WIDTH 32U
#define W5_DEC_RAW_STEP_HEIGHT 16U
#define W5_DEF_ENC_PIC_WIDTH 416U
#define W5_DEF_ENC_PIC_HEIGHT 240U
#define W5_MIN_ENC_PIC_WIDTH 256U
#define W5_MIN_ENC_PIC_HEIGHT 128U
#define W5_MAX_ENC_PIC_WIDTH 8192U
#define W5_MAX_ENC_PIC_HEIGHT 8192U
#define W5_ENC_CODEC_STEP_WIDTH 8U
#define W5_ENC_CODEC_STEP_HEIGHT 8U
#define W5_ENC_RAW_STEP_WIDTH 32U
#define W5_ENC_RAW_STEP_HEIGHT 16U
// application specific configuration
#define VPU_ENC_TIMEOUT 60000
#define VPU_DEC_TIMEOUT 60000
#define VPU_DEC_STOP_TIMEOUT 10
// 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 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 WAVE521_MAX_CODE_BUF_SIZE (2 * 1024 * 1024)
#define WAVE515_MAX_CODE_BUF_SIZE (1024 * 1024)
#define WAVE5_TEMPBUF_SIZE (1024 * 1024)
#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 ======================//
#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_ */
@@ -0,0 +1,292 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Wave5 series multi-standard codec IP - error values
*
* Copyright (C) 2021-2023 CHIPS&MEDIA INC
*/
#ifndef ERROR_CODE_H_INCLUDED
#define ERROR_CODE_H_INCLUDED
/*
* WAVE5
*/
/************************************************************************/
/* WAVE5 COMMON SYSTEM ERROR (FAIL_REASON) */
/************************************************************************/
#define WAVE5_SYSERR_QUEUEING_FAIL 0x00000001
#define WAVE5_SYSERR_ACCESS_VIOLATION_HW 0x00000040
#define WAVE5_SYSERR_BUS_ERROR 0x00000200
#define WAVE5_SYSERR_DOUBLE_FAULT 0x00000400
#define WAVE5_SYSERR_RESULT_NOT_READY 0x00000800
#define WAVE5_SYSERR_VPU_STILL_RUNNING 0x00001000
#define WAVE5_SYSERR_UNKNOWN_CMD 0x00002000
#define WAVE5_SYSERR_UNKNOWN_CODEC_STD 0x00004000
#define WAVE5_SYSERR_UNKNOWN_QUERY_OPTION 0x00008000
#define WAVE5_SYSERR_VLC_BUF_FULL 0x00010000
#define WAVE5_SYSERR_WATCHDOG_TIMEOUT 0x00020000
#define WAVE5_SYSERR_VCPU_TIMEOUT 0x00080000
#define WAVE5_SYSERR_TEMP_SEC_BUF_OVERFLOW 0x00200000
#define WAVE5_SYSERR_NEED_MORE_TASK_BUF 0x00400000
#define WAVE5_SYSERR_PRESCAN_ERR 0x00800000
#define WAVE5_SYSERR_ENC_GBIN_OVERCONSUME 0x01000000
#define WAVE5_SYSERR_ENC_MAX_ZERO_DETECT 0x02000000
#define WAVE5_SYSERR_ENC_LVL_FIRST_ERROR 0x04000000
#define WAVE5_SYSERR_ENC_EG_RANGE_OVER 0x08000000
#define WAVE5_SYSERR_ENC_IRB_FRAME_DROP 0x10000000
#define WAVE5_SYSERR_INPLACE_V 0x20000000
#define WAVE5_SYSERR_FATAL_VPU_HANGUP 0xf0000000
/************************************************************************/
/* WAVE5 COMMAND QUEUE ERROR (FAIL_REASON) */
/************************************************************************/
#define WAVE5_CMDQ_ERR_NOT_QUEABLE_CMD 0x00000001
#define WAVE5_CMDQ_ERR_SKIP_MODE_ENABLE 0x00000002
#define WAVE5_CMDQ_ERR_INST_FLUSHING 0x00000003
#define WAVE5_CMDQ_ERR_INST_INACTIVE 0x00000004
#define WAVE5_CMDQ_ERR_QUEUE_FAIL 0x00000005
#define WAVE5_CMDQ_ERR_CMD_BUF_FULL 0x00000006
/************************************************************************/
/* WAVE5 ERROR ON DECODER (ERR_INFO) */
/************************************************************************/
// HEVC
#define HEVC_SPSERR_SEQ_PARAMETER_SET_ID 0x00001000
#define HEVC_SPSERR_CHROMA_FORMAT_IDC 0x00001001
#define HEVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES 0x00001002
#define HEVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES 0x00001003
#define HEVC_SPSERR_CONF_WIN_LEFT_OFFSET 0x00001004
#define HEVC_SPSERR_CONF_WIN_RIGHT_OFFSET 0x00001005
#define HEVC_SPSERR_CONF_WIN_TOP_OFFSET 0x00001006
#define HEVC_SPSERR_CONF_WIN_BOTTOM_OFFSET 0x00001007
#define HEVC_SPSERR_BIT_DEPTH_LUMA_MINUS8 0x00001008
#define HEVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8 0x00001009
#define HEVC_SPSERR_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4 0x0000100A
#define HEVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING 0x0000100B
#define HEVC_SPSERR_SPS_MAX_NUM_REORDER_PICS 0x0000100C
#define HEVC_SPSERR_SPS_MAX_LATENCY_INCREASE 0x0000100D
#define HEVC_SPSERR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3 0x0000100E
#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE 0x0000100F
#define HEVC_SPSERR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2 0x00001010
#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE 0x00001011
#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER 0x00001012
#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA 0x00001013
#define HEVC_SPSERR_SCALING_LIST 0x00001014
#define HEVC_SPSERR_LOG2_DIFF_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3 0x00001015
#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE 0x00001016
#define HEVC_SPSERR_NUM_SHORT_TERM_REF_PIC_SETS 0x00001017
#define HEVC_SPSERR_NUM_LONG_TERM_REF_PICS_SPS 0x00001018
#define HEVC_SPSERR_GBU_PARSING_ERROR 0x00001019
#define HEVC_SPSERR_EXTENSION_FLAG 0x0000101A
#define HEVC_SPSERR_VUI_ERROR 0x0000101B
#define HEVC_SPSERR_ACTIVATE_SPS 0x0000101C
#define HEVC_SPSERR_PROFILE_SPACE 0x0000101D
#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID 0x00002000
#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID 0x00002001
#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1 0x00002002
#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1 0x00002003
#define HEVC_PPSERR_INIT_QP_MINUS26 0x00002004
#define HEVC_PPSERR_DIFF_CU_QP_DELTA_DEPTH 0x00002005
#define HEVC_PPSERR_PPS_CB_QP_OFFSET 0x00002006
#define HEVC_PPSERR_PPS_CR_QP_OFFSET 0x00002007
#define HEVC_PPSERR_NUM_TILE_COLUMNS_MINUS1 0x00002008
#define HEVC_PPSERR_NUM_TILE_ROWS_MINUS1 0x00002009
#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1 0x0000200A
#define HEVC_PPSERR_ROW_HEIGHT_MINUS1 0x0000200B
#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2 0x0000200C
#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2 0x0000200D
#define HEVC_PPSERR_SCALING_LIST 0x0000200E
#define HEVC_PPSERR_LOG2_PARALLEL_MERGE_LEVEL_MINUS2 0x0000200F
#define HEVC_PPSERR_NUM_TILE_COLUMNS_RANGE_OUT 0x00002010
#define HEVC_PPSERR_NUM_TILE_ROWS_RANGE_OUT 0x00002011
#define HEVC_PPSERR_MORE_RBSP_DATA_ERROR 0x00002012
#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT 0x00002013
#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT 0x00002014
#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002015
#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002016
#define HEVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT 0x00002017
#define HEVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT 0x00002018
#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1_RANGE_OUT 0x00002019
#define HEVC_PPSERR_ROW_HEIGHT_MINUS1_RANGE_OUT 0x00002020
#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2_RANGE_OUT 0x00002021
#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2_RANGE_OUT 0x00002022
#define HEVC_SHERR_SLICE_PIC_PARAMETER_SET_ID 0x00003000
#define HEVC_SHERR_ACTIVATE_PPS 0x00003001
#define HEVC_SHERR_ACTIVATE_SPS 0x00003002
#define HEVC_SHERR_SLICE_TYPE 0x00003003
#define HEVC_SHERR_FIRST_SLICE_IS_DEPENDENT_SLICE 0x00003004
#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_SPS_FLAG 0x00003005
#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET 0x00003006
#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_IDX 0x00003007
#define HEVC_SHERR_NUM_LONG_TERM_SPS 0x00003008
#define HEVC_SHERR_NUM_LONG_TERM_PICS 0x00003009
#define HEVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE 0x0000300A
#define HEVC_SHERR_DELTA_POC_MSB_CYCLE_LT 0x0000300B
#define HEVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1 0x0000300C
#define HEVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1 0x0000300D
#define HEVC_SHERR_COLLOCATED_REF_IDX 0x0000300E
#define HEVC_SHERR_PRED_WEIGHT_TABLE 0x0000300F
#define HEVC_SHERR_FIVE_MINUS_MAX_NUM_MERGE_CAND 0x00003010
#define HEVC_SHERR_SLICE_QP_DELTA 0x00003011
#define HEVC_SHERR_SLICE_QP_DELTA_IS_OUT_OF_RANGE 0x00003012
#define HEVC_SHERR_SLICE_CB_QP_OFFSET 0x00003013
#define HEVC_SHERR_SLICE_CR_QP_OFFSET 0x00003014
#define HEVC_SHERR_SLICE_BETA_OFFSET_DIV2 0x00003015
#define HEVC_SHERR_SLICE_TC_OFFSET_DIV2 0x00003016
#define HEVC_SHERR_NUM_ENTRY_POINT_OFFSETS 0x00003017
#define HEVC_SHERR_OFFSET_LEN_MINUS1 0x00003018
#define HEVC_SHERR_SLICE_SEGMENT_HEADER_EXTENSION_LENGTH 0x00003019
#define HEVC_SHERR_WRONG_POC_IN_STILL_PICTURE_PROFILE 0x0000301A
#define HEVC_SHERR_SLICE_TYPE_ERROR_IN_STILL_PICTURE_PROFILE 0x0000301B
#define HEVC_SHERR_PPS_ID_NOT_EQUAL_PREV_VALUE 0x0000301C
#define HEVC_SPECERR_OVER_PICTURE_WIDTH_SIZE 0x00004000
#define HEVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE 0x00004001
#define HEVC_SPECERR_OVER_CHROMA_FORMAT 0x00004002
#define HEVC_SPECERR_OVER_BIT_DEPTH 0x00004003
#define HEVC_SPECERR_OVER_BUFFER_OVER_FLOW 0x00004004
#define HEVC_SPECERR_OVER_WRONG_BUFFER_ACCESS 0x00004005
#define HEVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND 0x00005000
#define HEVC_ETCERR_DEC_PIC_VCL_NOT_FOUND 0x00005001
#define HEVC_ETCERR_NO_VALID_SLICE_IN_AU 0x00005002
#define HEVC_ETCERR_INPLACE_V 0x0000500F
// AVC
#define AVC_SPSERR_SEQ_PARAMETER_SET_ID 0x00001000
#define AVC_SPSERR_CHROMA_FORMAT_IDC 0x00001001
#define AVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES 0x00001002
#define AVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES 0x00001003
#define AVC_SPSERR_CONF_WIN_LEFT_OFFSET 0x00001004
#define AVC_SPSERR_CONF_WIN_RIGHT_OFFSET 0x00001005
#define AVC_SPSERR_CONF_WIN_TOP_OFFSET 0x00001006
#define AVC_SPSERR_CONF_WIN_BOTTOM_OFFSET 0x00001007
#define AVC_SPSERR_BIT_DEPTH_LUMA_MINUS8 0x00001008
#define AVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8 0x00001009
#define AVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING 0x0000100B
#define AVC_SPSERR_SPS_MAX_NUM_REORDER_PICS 0x0000100C
#define AVC_SPSERR_SCALING_LIST 0x00001014
#define AVC_SPSERR_GBU_PARSING_ERROR 0x00001019
#define AVC_SPSERR_VUI_ERROR 0x0000101B
#define AVC_SPSERR_ACTIVATE_SPS 0x0000101C
#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID 0x00002000
#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID 0x00002001
#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1 0x00002002
#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1 0x00002003
#define AVC_PPSERR_INIT_QP_MINUS26 0x00002004
#define AVC_PPSERR_PPS_CB_QP_OFFSET 0x00002006
#define AVC_PPSERR_PPS_CR_QP_OFFSET 0x00002007
#define AVC_PPSERR_SCALING_LIST 0x0000200E
#define AVC_PPSERR_MORE_RBSP_DATA_ERROR 0x00002012
#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT 0x00002013
#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT 0x00002014
#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002015
#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002016
#define AVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT 0x00002017
#define AVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT 0x00002018
#define AVC_SHERR_SLICE_PIC_PARAMETER_SET_ID 0x00003000
#define AVC_SHERR_ACTIVATE_PPS 0x00003001
#define AVC_SHERR_ACTIVATE_SPS 0x00003002
#define AVC_SHERR_SLICE_TYPE 0x00003003
#define AVC_SHERR_FIRST_MB_IN_SLICE 0x00003004
#define AVC_SHERR_RPLM 0x00003006
#define AVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE 0x0000300A
#define AVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1 0x0000300C
#define AVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1 0x0000300D
#define AVC_SHERR_PRED_WEIGHT_TABLE 0x0000300F
#define AVC_SHERR_SLICE_QP_DELTA 0x00003011
#define AVC_SHERR_SLICE_BETA_OFFSET_DIV2 0x00003015
#define AVC_SHERR_SLICE_TC_OFFSET_DIV2 0x00003016
#define AVC_SHERR_DISABLE_DEBLOCK_FILTER_IDC 0x00003017
#define AVC_SPECERR_OVER_PICTURE_WIDTH_SIZE 0x00004000
#define AVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE 0x00004001
#define AVC_SPECERR_OVER_CHROMA_FORMAT 0x00004002
#define AVC_SPECERR_OVER_BIT_DEPTH 0x00004003
#define AVC_SPECERR_OVER_BUFFER_OVER_FLOW 0x00004004
#define AVC_SPECERR_OVER_WRONG_BUFFER_ACCESS 0x00004005
#define AVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND 0x00005000
#define AVC_ETCERR_DEC_PIC_VCL_NOT_FOUND 0x00005001
#define AVC_ETCERR_NO_VALID_SLICE_IN_AU 0x00005002
#define AVC_ETCERR_ASO 0x00005004
#define AVC_ETCERR_FMO 0x00005005
#define AVC_ETCERR_INPLACE_V 0x0000500F
/************************************************************************/
/* WAVE5 WARNING ON DECODER (WARN_INFO) */
/************************************************************************/
// HEVC
#define HEVC_SPSWARN_MAX_SUB_LAYERS_MINUS1 0x00000001
#define HEVC_SPSWARN_GENERAL_RESERVED_ZERO_44BITS 0x00000002
#define HEVC_SPSWARN_RESERVED_ZERO_2BITS 0x00000004
#define HEVC_SPSWARN_SUB_LAYER_RESERVED_ZERO_44BITS 0x00000008
#define HEVC_SPSWARN_GENERAL_LEVEL_IDC 0x00000010
#define HEVC_SPSWARN_SPS_MAX_DEC_PIC_BUFFERING_VALUE_OVER 0x00000020
#define HEVC_SPSWARN_RBSP_TRAILING_BITS 0x00000040
#define HEVC_SPSWARN_ST_RPS_UE_ERROR 0x00000080
#define HEVC_SPSWARN_EXTENSION_FLAG 0x01000000
#define HEVC_SPSWARN_REPLACED_WITH_PREV_SPS 0x02000000
#define HEVC_PPSWARN_RBSP_TRAILING_BITS 0x00000100
#define HEVC_PPSWARN_REPLACED_WITH_PREV_PPS 0x00000200
#define HEVC_SHWARN_FIRST_SLICE_SEGMENT_IN_PIC_FLAG 0x00001000
#define HEVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG 0x00002000
#define HEVC_SHWARN_PIC_OUTPUT_FLAG 0x00004000
#define HEVC_SHWARN_DUPLICATED_SLICE_SEGMENT 0x00008000
#define HEVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND 0x00010000
#define HEVC_ETCWARN_MISSING_REFERENCE_PICTURE 0x00020000
#define HEVC_ETCWARN_WRONG_TEMPORAL_ID 0x00040000
#define HEVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED 0x00080000
#define HEVC_SPECWARN_OVER_PROFILE 0x00100000
#define HEVC_SPECWARN_OVER_LEVEL 0x00200000
#define HEVC_PRESWARN_PARSING_ERR 0x04000000
#define HEVC_PRESWARN_MVD_OUT_OF_RANGE 0x08000000
#define HEVC_PRESWARN_CU_QP_DELTA_VAL_OUT_OF_RANGE 0x09000000
#define HEVC_PRESWARN_COEFF_LEVEL_REMAINING_OUT_OF_RANGE 0x0A000000
#define HEVC_PRESWARN_PCM_ERR 0x0B000000
#define HEVC_PRESWARN_OVERCONSUME 0x0C000000
#define HEVC_PRESWARN_END_OF_SUBSET_ONE_BIT_ERR 0x10000000
#define HEVC_PRESWARN_END_OF_SLICE_SEGMENT_FLAG 0x20000000
// AVC
#define AVC_SPSWARN_RESERVED_ZERO_2BITS 0x00000004
#define AVC_SPSWARN_GENERAL_LEVEL_IDC 0x00000010
#define AVC_SPSWARN_RBSP_TRAILING_BITS 0x00000040
#define AVC_PPSWARN_RBSP_TRAILING_BITS 0x00000100
#define AVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG 0x00002000
#define AVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND 0x00010000
#define AVC_ETCWARN_MISSING_REFERENCE_PICTURE 0x00020000
#define AVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED 0x00080000
#define AVC_SPECWARN_OVER_PROFILE 0x00100000
#define AVC_SPECWARN_OVER_LEVEL 0x00200000
#define AVC_PRESWARN_MVD_RANGE_OUT 0x00400000
#define AVC_PRESWARN_MB_QPD_RANGE_OUT 0x00500000
#define AVC_PRESWARN_COEFF_RANGE_OUT 0x00600000
#define AVC_PRESWARN_MV_RANGE_OUT 0x00700000
#define AVC_PRESWARN_MB_SKIP_RUN_RANGE_OUT 0x00800000
#define AVC_PRESWARN_MB_TYPE_RANGE_OUT 0x00900000
#define AVC_PRESWARN_SUB_MB_TYPE_RANGE_OUT 0x00A00000
#define AVC_PRESWARN_CBP_RANGE_OUT 0x00B00000
#define AVC_PRESWARN_INTRA_CHROMA_PRED_MODE_RANGE_OUT 0x00C00000
#define AVC_PRESWARN_REF_IDX_RANGE_OUT 0x00D00000
#define AVC_PRESWARN_COEFF_TOKEN_RANGE_OUT 0x00E00000
#define AVC_PRESWARN_TOTAL_ZERO_RANGE_OUT 0x00F00000
#define AVC_PRESWARN_RUN_BEFORE_RANGE_OUT 0x01000000
#define AVC_PRESWARN_OVERCONSUME 0x01100000
#define AVC_PRESWARN_MISSING_SLICE 0x01200000
/************************************************************************/
/* WAVE5 ERROR ON ENCODER (ERR_INFO) */
/************************************************************************/
/************************************************************************/
/* WAVE5 WARNING ON ENCODER (WARN_INFO) */
/************************************************************************/
#define WAVE5_ETCWARN_FORCED_SPLIT_BY_CU8X8 0x000000001
/************************************************************************/
/* WAVE5 debug info (PRI_REASON) */
/************************************************************************/
#define WAVE5_DEC_VCORE_VCE_HANGUP 0x0001
#define WAVE5_DEC_VCORE_UNDETECTED_SYNTAX_ERR 0x0002
#define WAVE5_DEC_VCORE_MIB_BUSY 0x0003
#define WAVE5_DEC_VCORE_VLC_BUSY 0x0004
#endif /* ERROR_CODE_H_INCLUDED */
@@ -0,0 +1,123 @@
/* 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)
/*
* 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
* 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_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
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__ */