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,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>