1
0
Fork 0

Add Malone decoder and windsor encoder for QXP/QM

Add vpu driver:
drivers/mxc/vpu_malone
drivers/mxc/vpu_windsor

Signed-off-by: Zhou Peng <eagle.zhou@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Zhou Peng 2019-01-24 11:15:00 +08:00 committed by Dong Aisheng
parent c5b08a52fe
commit 95b1763c0a
25 changed files with 15073 additions and 0 deletions

View File

@ -0,0 +1,20 @@
#
# Codec configuration
#
menu "MXC VPU(Video Processing Unit) MALONE support"
config MXC_VPU_MALONE
tristate "Support for MXC VPU(Video Processing Unit) DECODER"
default y
---help---
The VPU codec device provides codec function for H.265 H.264 MPEG2 MPEG4 etc.
config MXC_VPU_MALONE_DEBUG
bool "MXC VPU DECODER debugging"
depends on MXC_VPU_MALONE != n
help
This is an option for the developers; most people should
say N here. This enables MXC VPU driver debugging.
endmenu

View File

@ -0,0 +1,16 @@
##
## Makefile for the VPU and M0 driver
##
DEFINES += -D REBOOT=1 \
-D BOOT_ARCH=1
EXTRA_CFLAGS += $(DEFINES)
obj-y = vpu-malone.o
vpu-malone-objs = vpu_b0.o \
vpu_rpc.o \
insert_startcode.o \
vpu_debug_log.o
clean:
rm -rf $(vpu-malone-objs)

View File

@ -0,0 +1,546 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file insert_startcode.c
*
* copyright here may be changed later
*
*
*/
#include "insert_startcode.h"
// Global VC1 ID and version
u_int32 uVC1CodecID = 0x10; // Simple = 0x10, Main = 0x11
u_int32 uVC1VersionID = 1;
static int insert_RCV_seqhdr(unsigned char *pHeader, u_int32 *pHeaderLen, unsigned char *src,
u_int32 nFrameSize, u_int32 nWidth, u_int32 nHeight, int *pNoError)
{
int nHeaderLen;
unsigned int nValue;
unsigned int HdrExtDataLen;
int i = 0;
int profile;
nHeaderLen = RCV_HEADER_LEN;
//Number of Frames, Header Extension Bit, Codec Version
nValue = RCV_NUM_FRAMES | RCV_SET_HDR_EXT | RCV_CODEC_VERSION;
pHeader[i++] = (unsigned char)nValue;
pHeader[i++] = (unsigned char)(nValue >> 8);
pHeader[i++] = (unsigned char)(nValue >> 16);
#if 0 //1 ???
pHeader[i++] = 0xC5;
#else
pHeader[i++] = (unsigned char)(nValue >> 24);
#endif
//Header Extension Size
//ASF Parser gives 5 bytes whereas the VPU expects only 4 bytes, so limiting it
HdrExtDataLen = 4;
pHeader[i++] = (unsigned char)HdrExtDataLen;
pHeader[i++] = (unsigned char)(HdrExtDataLen >> 8);
pHeader[i++] = (unsigned char)(HdrExtDataLen >> 16);
pHeader[i++] = (unsigned char)(HdrExtDataLen >> 24);
profile = (*src)>>4;
if ((profile != 0) && (profile != 4) && (profile != 12)) {
//it is reasonable to return error immediately since only one sequence header inserted in whole rcv clip
*pNoError = 0;
}
memcpy(pHeader+i, src, HdrExtDataLen);
i += HdrExtDataLen;
//Height
pHeader[i++] = (unsigned char)nHeight;
pHeader[i++] = (unsigned char)(((nHeight >> 8) & 0xff));
pHeader[i++] = (unsigned char)(((nHeight >> 16) & 0xff));
pHeader[i++] = (unsigned char)(((nHeight >> 24) & 0xff));
//Width
pHeader[i++] = (unsigned char)nWidth;
pHeader[i++] = (unsigned char)(((nWidth >> 8) & 0xff));
pHeader[i++] = (unsigned char)(((nWidth >> 16) & 0xff));
pHeader[i++] = (unsigned char)(((nWidth >> 24) & 0xff));
//Frame Size
pHeader[i++] = (unsigned char)nFrameSize;
pHeader[i++] = (unsigned char)(nFrameSize >> 8);
pHeader[i++] = (unsigned char)(nFrameSize >> 16);
#if 0 //1 ???
pHeader[i++] = (unsigned char)((nFrameSize >> 24));
#else
pHeader[i++] = (unsigned char)((nFrameSize >> 24) | 0x80);
#endif
*pHeaderLen = nHeaderLen;
return 1;
}
static int insert_RCV_pichdr(unsigned char *pHeader, int *pHeaderLen, unsigned int nInSize)
{
pHeader[0] = (unsigned char)nInSize;
pHeader[1] = (unsigned char)(nInSize >> 8);
pHeader[2] = (unsigned char)(nInSize >> 16);
pHeader[3] = (unsigned char)(nInSize >> 24);
*pHeaderLen = 4;
return 1;
}
/*
* Byte 0-3: Startcode
* Byte 4: Payload length bits[23:16]
* Byte 5: Payload length bits[15:8]
* Byte 6: 0x4e
* Byte 7: Payload length bits[7:0]
* Byte 8: Codec ID Non-zero
* Byte 9: Codec Version ID Non-zero
* Byte 10: Picture Width bits[15:8]
* Byte 11: Picture Width bits[7:0]
* Byte 12: 0x58
* Byte 13: Picture Height bits[15:8]
* Byte 14: Picture Height bits[7:0]
* Byte 15: 0x50
*/
static void insert_payload_header_vc1(u_int8 *dst, u_int32 uScodeType, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
{
// Startcode
dst[0] = 0x00;
dst[1] = 0x00;
dst[2] = 0x01;
dst[3] = uScodeType;
// Length
dst[4] = ((uPayloadSize>>16)&0xff);
dst[5] = ((uPayloadSize>>8)&0xff);
dst[6] = 0x4e;
dst[7] = ((uPayloadSize>>0)&0xff);
// Codec ID and Version
dst[8] = uVC1CodecID;
dst[9] = uVC1VersionID;
// Width
dst[10] = ((uWidth>>8)&0xff);
dst[11] = ((uWidth>>0)&0xff);
dst[12] = 0x58;
// Height
dst[13] = ((uHeight>>8)&0xff);
dst[14] = ((uHeight>>0)&0xff);
dst[15] = 0x50;
}
static int VC1CreateNALSeqHeader(unsigned char *pHeader, int *pHeaderLen,
unsigned char *pCodecPri, int nCodecSize, unsigned int *pData, int nMaxHeader)
{
int nHeaderLen;
unsigned char temp[4] = {0x00, 0x00, 0x01, 0x0D};
nHeaderLen = nCodecSize - 1;
if ((4+nHeaderLen) > nMaxHeader) {
nHeaderLen = nMaxHeader - 4;
vpu_dbg(LVL_ERR, "error: header length %d overrun !!! \r\n", nCodecSize);
}
memcpy(pHeader, pCodecPri+1, nHeaderLen);
if (VC1_IS_NOT_NAL(pData[0])) {
//insert 0x0000010D at the end of header
memcpy(pHeader+nHeaderLen, temp, 4);
nHeaderLen += 4;
}
*pHeaderLen = nHeaderLen;
return 1;
}
static int VC1CreateNalFrameHeader(unsigned char *pHeader, int *pHeaderLen, unsigned int *pInData)
{
unsigned int VC1Id;
VC1Id = *pInData;
if (VC1_IS_NOT_NAL(VC1Id)) {
//need insert header : special ID
pHeader[0] = 0x0;
pHeader[1] = 0x0;
pHeader[2] = 0x01;
pHeader[3] = 0x0D;
*pHeaderLen = 4;
} else {
//need not insert header
//do nothing
*pHeaderLen = 0;
}
return 1;
}
void vp6_scd_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
{
int Length = 0;
buffer[0] = 0x00;
buffer[1] = 0x00;
buffer[2] = 0x01;
buffer[3] = 0x31;
buffer[4] = (Length+12)>>16;
buffer[5] = (Length+12)>>8;
buffer[6] = 0x4e;
buffer[7] = (Length+12);
buffer[8] = 0x36;
buffer[9] = 0x1;
buffer[10] = pic_width>>8;
buffer[11] = pic_width;
buffer[12] = 0x58;
buffer[13] = pic_height>>8;
buffer[14] = pic_height;
buffer[15] = 0x50;
}
void vp6_scd_frame_header(unsigned char *buffer, int pic_width, int pic_height, int Length)
{
buffer[0] = 0x00;
buffer[1] = 0x00;
buffer[2] = 0x01;
buffer[3] = 0x32;
buffer[4] = (Length+12)>>16;
buffer[5] = (Length+12)>>8;
buffer[6] = 0x4e;
buffer[7] = (Length+12);
buffer[8] = 0x36;
buffer[9] = 0x1;
buffer[10] = pic_width>>8;
buffer[11] = pic_width;
buffer[12] = 0x58;
buffer[13] = pic_height>>8;
buffer[14] = pic_height;
buffer[15] = 0x50;
}
void vp8_ivf_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
{
int Length = 32;
buffer[0] = 0x44;
buffer[1] = 0x4b;
buffer[2] = 0x49;
buffer[3] = 0x46; //0-3byte signature "DKIF"
buffer[4] = 0x00;
buffer[5] = 0x00; //4-5byte version 0
buffer[6] = Length;
buffer[7] = Length >> 8; //length of Header
buffer[8] = 0x56;
buffer[9] = 0x50;
buffer[10] = 0x38;
buffer[11] = 0x30; //VP8 fourcc
buffer[12] = pic_width;
buffer[13] = pic_width >> 8;
buffer[14] = pic_height;
buffer[15] = pic_height >> 8;
buffer[16] = 0xe8;
buffer[17] = 0x03;
buffer[18] = 0x00;
buffer[19] = 0x00; //16-19 frame rate
buffer[20] = 0x01;
buffer[21] = 0x00;
buffer[22] = 0x00;
buffer[23] = 0x00; //20-23 time scale
buffer[24] = 0xdf;
buffer[25] = 0xf9;
buffer[26] = 0x09;
buffer[27] = 0x00; //24-27 number frames
//28-31 unused
}
void vp8_ivf_frame_header(unsigned char *buffer, u_int32 FrameSize)
{
buffer[0] = FrameSize;
buffer[1] = FrameSize >> 8;
buffer[2] = FrameSize >> 16;
buffer[3] = FrameSize >> 24;
//4-11 timestamp
}
void vp8_scd_sequence_header(unsigned char *buffer, int pic_width, int pic_height)
{
int Length = 32;
buffer[0] = 0x00;
buffer[1] = 0x00;
buffer[2] = 0x01;
buffer[3] = 0x31;
buffer[4] = (Length+12)>>16;
buffer[5] = (Length+12)>>8;
buffer[6] = 0x4e;
buffer[7] = (Length+12);
buffer[8] = 0x36;
buffer[9] = 0x1;
buffer[10] = pic_width>>8;
buffer[11] = pic_width;
buffer[12] = 0x58;
buffer[13] = pic_height>>8;
buffer[14] = pic_height;
buffer[15] = 0x50;
}
void vp8_scd_frame_header(unsigned char *buffer, int pic_width, int pic_height, int Length)
{
buffer[0] = 0x00;
buffer[1] = 0x00;
buffer[2] = 0x01;
buffer[3] = 0x32;
buffer[4] = (Length+12)>>16;
buffer[5] = (Length+12)>>8;
buffer[6] = 0x4e;
buffer[7] = (Length+12);
buffer[8] = 0x36;
buffer[9] = 0x1;
buffer[10] = pic_width>>8;
buffer[11] = pic_width;
buffer[12] = 0x58;
buffer[13] = pic_height>>8;
buffer[14] = pic_height;
buffer[15] = 0x50;
}
static void insert_payload_header_divx(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
{
// Startcode
dst[0] = 0x00;
dst[1] = 0x00;
dst[2] = 0x01;
dst[3] = 0x32;
// Length
dst[4] = ((uPayloadSize>>16)&0xff);
dst[5] = ((uPayloadSize>>8)&0xff);
dst[6] = 0x4e;
dst[7] = ((uPayloadSize>>0)&0xff);
// Codec ID and Version
dst[8] = 0x38;
dst[9] = 0x01;
// Width
dst[10] = ((uWidth>>8)&0xff);
dst[11] = ((uWidth>>0)&0xff);
dst[12] = 0x58;
// Height
dst[13] = ((uHeight>>8)&0xff);
dst[14] = ((uHeight>>0)&0xff);
dst[15] = 0x50;
}
static void insert_seq_header_spk(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
{
// Startcode
dst[0] = 0x00;
dst[1] = 0x00;
dst[2] = 0x01;
dst[3] = 0x31;
// Length
dst[4] = ((uPayloadSize>>16)&0xff);
dst[5] = ((uPayloadSize>>8)&0xff);
dst[6] = 0x4e;
dst[7] = ((uPayloadSize>>0)&0xff);
// Codec ID and Version
dst[8] = 0x39;
dst[9] = 0x01;
// Width
dst[10] = ((uWidth>>8)&0xff);
dst[11] = ((uWidth>>0)&0xff);
dst[12] = 0x58;
// Height
dst[13] = ((uHeight>>8)&0xff);
dst[14] = ((uHeight>>0)&0xff);
dst[15] = 0x50;
}
static void insert_frame_header_spk(u_int8 *dst, u_int32 uPayloadSize, u_int32 uWidth, u_int32 uHeight)
{
uPayloadSize = 0;
// Startcode
dst[0] = 0x00;
dst[1] = 0x00;
dst[2] = 0x01;
dst[3] = 0x32;
// Length
dst[4] = ((uPayloadSize>>16)&0xff);
dst[5] = ((uPayloadSize>>8)&0xff);
dst[6] = 0x4e;
dst[7] = ((uPayloadSize>>0)&0xff);
// Codec ID and Version
dst[8] = 0x39;
dst[9] = 0x01;
// Width
dst[10] = ((uWidth>>8)&0xff);
dst[11] = ((uWidth>>0)&0xff);
dst[12] = 0x58;
// Height
dst[13] = ((uHeight>>8)&0xff);
dst[14] = ((uHeight>>0)&0xff);
dst[15] = 0x50;
}
u_int32 insert_scode_4_seq(struct vpu_ctx *ctx, u_int8 *src, u_int8 *dst, u_int32 vdec_std, u_int32 uPayloadSize)
{
struct queue_data *q_data = &ctx->q_data[V4L2_SRC];
u_int32 length = 0;
switch (vdec_std) {
case VPU_VIDEO_VC1: {
if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) {
u_int8 Header[VC1_MAX_SEQ_HEADER_SIZE];
u_int32 uWidth = q_data->width;
u_int32 uHeight = q_data->height; //Width & Height in the generic payload header are ignored
u_int32 FrameSize = 0x60;
u_int32 HeaderLen, NoError = 1;
//insert startcode for vc1
insert_payload_header_vc1(dst, VC1_SCODE_NEW_SEQUENCE, 20, uWidth, uHeight);
length = 16;
//insert RCV sequence header for vc1 v1, length=20
insert_RCV_seqhdr(Header, &HeaderLen, src, FrameSize, uWidth, uHeight, &NoError);
HeaderLen = RCV_HEADER_LEN - 4;
memcpy(dst + 16, Header, HeaderLen);
length += HeaderLen;
} else {
u_int8 Header[VC1_MAX_SEQ_HEADER_SIZE];
u_int32 HeaderLen;
VC1CreateNALSeqHeader(Header, &HeaderLen, src, uPayloadSize,
(unsigned int *)src, VC1_MAX_SEQ_HEADER_SIZE);
if (VC1_IS_NOT_NAL(((unsigned int *)src)[0]))
HeaderLen -= 4;
memcpy(dst, Header, HeaderLen);
length += HeaderLen;
}
}
break;
case VPU_VIDEO_VP6: {
vp6_scd_sequence_header(dst, q_data->width, q_data->height);
length = 16;
}
break;
case VPU_VIDEO_VP8: {
u_int8 seq_header[32] = {0};
u_int8 frame_header[8] = {0};
vp8_scd_sequence_header(dst, q_data->width, q_data->height);
length = 16;
vp8_ivf_sequence_header(seq_header, q_data->width, q_data->height);
memcpy(dst+length, seq_header, 32);
length += 32;
vp8_scd_frame_header(dst + length, q_data->width, q_data->height, uPayloadSize + 8);
length += 16;
vp8_ivf_frame_header(frame_header, uPayloadSize);
memcpy(dst+length, frame_header, 8);
length += 8;
memcpy(dst+length, src, uPayloadSize);
length += uPayloadSize;
}
break;
case VPU_VIDEO_ASP: {
if (q_data->fourcc == VPU_PIX_FMT_DIVX) {
insert_payload_header_divx(dst, uPayloadSize, q_data->width, q_data->height);
length = 16;
memcpy(dst+length, src, uPayloadSize);
length += uPayloadSize;
}
}
break;
case VPU_VIDEO_SPK: {
insert_seq_header_spk(dst, uPayloadSize, q_data->width, q_data->height);
length = 16;
}
break;
default:
break;
}
return length;
}
u_int32 insert_scode_4_pic(struct vpu_ctx *ctx, u_int8 *dst, u_int8 *src, u_int32 vdec_std, u_int32 uPayloadSize)
{
struct queue_data *q_data = &ctx->q_data[V4L2_SRC];
u_int32 length = 0;
switch (vdec_std) {
case VPU_VIDEO_VC1: {
if (q_data->fourcc == V4L2_PIX_FMT_VC1_ANNEX_G) {
u_int8 Header[VC1_MAX_FRM_HEADER_SIZE];
u_int32 HeaderLen;
u_int32 uWidth = q_data->width;
u_int32 uHeight = q_data->height; //Width & Height in the generic payload header are ignored
insert_payload_header_vc1(dst, VC1_SCODE_NEW_PICTURE, uPayloadSize + 4, uWidth, uHeight);
insert_RCV_pichdr(Header, &HeaderLen, uPayloadSize);
memcpy(dst+16, Header, 4);
length = 16 + 4;
} else {
u_int8 Header[VC1_MAX_FRM_HEADER_SIZE];
u_int32 HeaderLen;
VC1CreateNalFrameHeader(Header, (int *)(&HeaderLen), (unsigned int *)(src));
memcpy(dst, Header, HeaderLen);
length = HeaderLen;
}
}
break;
case VPU_VIDEO_VP6: {
vp6_scd_frame_header(dst, q_data->width, q_data->height, uPayloadSize);
length = 16;
}
break;
case VPU_VIDEO_VP8: {
u_int8 frame_header[8];
vp8_scd_frame_header(dst, q_data->width, q_data->height, uPayloadSize + 8);
length = 16;
vp8_ivf_frame_header(frame_header, uPayloadSize);
memcpy(dst+length, frame_header, 8);
length += 8;
}
break;
case VPU_VIDEO_ASP: {
if (q_data->fourcc == VPU_PIX_FMT_DIVX) {
insert_payload_header_divx(dst, uPayloadSize, q_data->width, q_data->height);
length = 16;
}
}
break;
case VPU_VIDEO_SPK: {
insert_frame_header_spk(dst, uPayloadSize, q_data->width, q_data->height);
length = 16;
}
break;
default:
break;
}
return length;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file insert_startcode.h
*
*/
#ifndef __INSERT_STARTCODE_H__
#define __INSERT_STARTCODE_H__
#include "vpu_b0.h"
#include "mediasys_types.h"
// Startcode insertion types for VC1
#define VC1_SCODE_NEW_SEQUENCE 0x31
#define VC1_SCODE_NEW_PICTURE 0x32
#define VC1_SCODE_NEW_SLICE 0x33
#define RCV_V2_FRAMESIZE_FLAGS (0xFF000000)
#define RCV_HEADER_LEN 24
#define RCV_CODEC_VERSION (0x5 << 24) //FOURCC_WMV3_WMV
#define RCV_NUM_FRAMES 0xFF
#define RCV_SET_HDR_EXT 0x80000000
#define VC1_IS_NOT_NAL(id) ((id & 0x00FFFFFF) != 0x00010000)
#define VC1_MAX_FRM_HEADER_SIZE 32
#define VC1_MAX_SEQ_HEADER_SIZE 256
u_int32 insert_scode_4_pic(struct vpu_ctx *ctx, u_int8 *dst, u_int8 *src, u_int32 vdec_std, u_int32 uPayloadSize);
u_int32 insert_scode_4_seq(struct vpu_ctx *ctx, u_int8 *src, u_int8 *dst, u_int32 vdec_std, u_int32 uPayloadSize);
#endif

View File

@ -0,0 +1,790 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MEDIASYS_TYPES_H_
#define _MEDIASYS_TYPES_H_
typedef unsigned int u_int32;
typedef unsigned char u_int8;
typedef unsigned long u_int64;
typedef unsigned int BOOL;
#define FALSE 0
#define TRUE 1
#define VPU_MAX_NUM_STREAMS 8
#define VID_API_NUM_STREAMS 8
#define VID_API_MAX_BUF_PER_STR 3
#define VID_API_MAX_NUM_MVC_VIEWS 4
#define MEDIAIP_MAX_NUM_MALONES 2
#define MEDIAIP_MAX_NUM_MALONE_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_WINDSORS 1
#define MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_CMD_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_MSG_IRQ_PINS 1
#define MEDIAIP_MAX_NUM_TIMER_IRQ_PINS 4
#define MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS 4
#define VID_API_COMMAND_LIMIT 64
#define VID_API_MESSAGE_LIMIT 256
#define MSG_WORD_LENGTH 3
#define API_CMD_AVAILABLE 0x0
#define API_CMD_INCOMPLETE 0x1
#define API_CMD_BUFFER_ERROR 0x2
#define API_CMD_UNAVAILABLE 0x3
#define API_MSG_AVAILABLE 0x0
#define API_MSG_INCOMPLETE 0x1
#define API_MSG_BUFFER_ERROR 0x2
#define API_MSG_UNAVAILABLE 0x3
typedef enum {
FRAME_ALLOC = 0,
FRAME_FREE,
FRAME_DECODED,
FRAME_READY,
FRAME_RELEASE,
} FRAME_BUFFER_STAT;
typedef enum {
VPU_APP,
VPU_DRIVER,
VPU_DECODER,
} FRAME_BUFFER_OWNER;
typedef enum {
INVALID_MODE = 0,
FRAME_LVL,
NON_FRAME_LVL,
} STREAM_INPUT_MODE;
typedef enum {
MEDIAIP_FRAME_REQ = 0,
MEDIAIP_MBI_REQ,
MEDIAIP_DCP_REQ,
MEDIAIP_REQ_LAST = MEDIAIP_DCP_REQ
} MEDIAIP_MEM_REQ;
typedef struct {
u_int32 uNum;
MEDIAIP_MEM_REQ eType;
} MEDIA_PLAYER_FSREQ;
typedef struct {
u_int32 uFSIdx;
MEDIAIP_MEM_REQ eType;
BOOL bNotDisplayed;
} MEDIA_PLAYER_FSREL;
typedef enum {
/* Non-Stream Specific messages */
MEDIA_PLAYER_API_MODE_INVALID = 0x00,
MEDIA_PLAYER_API_MODE_PARSE_STEP = 0x01,
MEDIA_PLAYER_API_MODE_DECODE_STEP = 0x02,
MEDIA_PLAYER_API_MODE_CONTINUOUS = 0x03
} MEDIA_PLAYER_API_MODE;
typedef enum {
/* Non-Stream Specific messages */
MEDIA_PLAYER_FS_CTRL_MODE_INTERNAL = 0x00,
MEDIA_PLAYER_FS_CTRL_MODE_EXTERNAL = 0x01
} MEDIA_PLAYER_FS_CTRL_MODE;
typedef enum {
/* Non-Stream Specific messages */
VID_API_CMD_NULL = 0x00,
VID_API_CMD_PARSE_NEXT_SEQ = 0x01,
VID_API_CMD_PARSE_NEXT_I = 0x02,
VID_API_CMD_PARSE_NEXT_IP = 0x03,
VID_API_CMD_PARSE_NEXT_ANY = 0x04,
VID_API_CMD_DEC_PIC = 0x05,
VID_API_CMD_UPDATE_ES_WR_PTR = 0x06,
VID_API_CMD_UPDATE_ES_RD_PTR = 0x07,
VID_API_CMD_UPDATE_UDATA = 0x08,
VID_API_CMD_GET_FSINFO = 0x09,
VID_API_CMD_SKIP_PIC = 0x0a,
VID_API_CMD_DEC_CHUNK = 0x0b,
VID_API_CMD_START = 0x10,
VID_API_CMD_STOP = 0x11,
VID_API_CMD_ABORT = 0x12,
VID_API_CMD_RST_BUF = 0x13,
VID_API_CMD_FS_RELEASE = 0x15,
VID_API_CMD_MEM_REGION_ATTACH = 0x16,
VID_API_CMD_MEM_REGION_DETACH = 0x17,
VID_API_CMD_MVC_VIEW_SELECT = 0x18,
VID_API_CMD_FS_ALLOC = 0x19,
VID_API_CMD_DBG_GET_STATUS = 0x1C,
VID_API_CMD_DBG_START_LOG = 0x1D,
VID_API_CMD_DBG_STOP_LOG = 0x1E,
VID_API_CMD_DBG_DUMP_LOG = 0x1F,
/* Begin Encode CMDs */
VID_API_CMD_YUV_READY = 0x20,
VID_API_CMD_FIRM_RESET = 0x40,
#if BOOT_ARCH == REBOOT
VID_API_CMD_SNAPSHOT = 0xAA,
VID_API_CMD_ROLL_SNAPSHOT = 0xAB,
VID_API_CMD_LOCK_SCHEDULER = 0xAC,
VID_API_CMD_UNLOCK_SCHEDULER = 0xAD,
#endif
VID_API_CMD_CQ_FIFO_DUMP = 0xAE,
VID_API_CMD_DBG_FIFO_DUMP = 0xAF,
VID_API_CMD_SVC_ILP = 0xBB,
VID_API_CMD_INVALID = 0xFF
} TB_API_DEC_CMD;
typedef enum {
/* Non-Stream Specific messages */
VID_API_EVENT_NULL = 0x00,
VID_API_EVENT_RESET_DONE = 0x01,
VID_API_EVENT_SEQ_HDR_FOUND = 0x02,
VID_API_EVENT_PIC_HDR_FOUND = 0x03,
VID_API_EVENT_PIC_DECODED = 0x04,
VID_API_EVENT_FIFO_LOW = 0x05,
VID_API_EVENT_FIFO_HIGH = 0x06,
VID_API_EVENT_FIFO_EMPTY = 0x07,
VID_API_EVENT_FIFO_FULL = 0x08,
VID_API_EVENT_BS_ERROR = 0x09,
VID_API_EVENT_UDATA_FIFO_UPTD = 0x0A,
VID_API_EVENT_RES_CHANGE = 0x0B,
VID_API_EVENT_FIFO_OVF = 0x0C,
VID_API_EVENT_CHUNK_DECODED = 0x0D,
VID_API_EVENT_REQ_FRAME_BUFF = 0x10,
VID_API_EVENT_FRAME_BUFF_RDY = 0x11,
VID_API_EVENT_REL_FRAME_BUFF = 0x12,
VID_API_EVENT_STR_BUF_RST = 0x13,
VID_API_EVENT_RET_PING = 0x14, /* Temp here - rationalise debug events at bottom */
VID_API_EVENT_QMETER = 0x15,
VID_API_EVENT_STR_FMT_CHANGE = 0x16,
VID_API_EVENT_FIRMWARE_XCPT = 0x17,
VID_API_EVENT_START_DONE = 0x18,
VID_API_EVENT_STOPPED = 0x19,
VID_API_EVENT_ABORT_DONE = 0x1A,
VID_API_EVENT_FINISHED = 0x1B,
VID_API_EVENT_DBG_STAT_UPDATE = 0x1C,
VID_API_EVENT_DBG_LOG_STARTED = 0x1D,
VID_API_EVENT_DBG_LOG_STOPPED = 0x1E,
VID_API_EVENT_DBG_LOG_UPDATED = 0x1F,
VID_API_EVENT_DBG_MSG_DEC = 0x20,
VID_API_EVENT_DEC_SC_ERR = 0x21,
VID_API_EVENT_CQ_FIFO_DUMP = 0x22,
VID_API_EVENT_DBG_FIFO_DUMP = 0x23,
VID_API_EVENT_DEC_CHECK_RES = 0x24,
VID_API_EVENT_DEC_CFG_INFO = 0x25,
VID_API_EVENT_SNAPSHOT_DONE = 0x40,
VID_API_EVENT_INVALID = 0xFF
} TB_API_DEC_EVENT;
typedef enum {
MEDIAIP_PLAYMODE_CONNECTIVITY = 0,
MEDIAIP_PLAYMODE_BROADCAST,
MEDIAIP_PLAYMODE_BROADCAST_DSS,
MEDIAIP_PLAYMODE_LAST = MEDIAIP_PLAYMODE_BROADCAST_DSS
} MEDIA_IP_PLAYMODE;
typedef enum {
MEDIA_IP_FMT_NULL = 0x0,
MEDIA_IP_FMT_AVC = 0x1,
MEDIA_IP_FMT_VC1 = 0x2,
MEDIA_IP_FMT_MP2 = 0x3,
MEDIA_IP_FMT_AVS = 0x4,
MEDIA_IP_FMT_ASP = 0x5,
MEDIA_IP_FMT_JPG = 0x6,
MEDIA_IP_FMT_RV = 0x7,
MEDIA_IP_FMT_VP6 = 0x8,
MEDIA_IP_FMT_SPK = 0x9,
MEDIA_IP_FMT_VP8 = 0xA,
MEDIA_IP_FMT_MVC = 0xB,
MEDIA_IP_FMT_VP3 = 0xC,
MEDIA_IP_FMT_HEVC = 0xD,
MEDIA_IP_FMT_AUTO_DETECT = 0xAD00,
MEDIA_IP_FMT_ALL = (int)0xAAAAAAAA,
MEDIA_IP_FMT_UNSUPPORTED = (int)0xFFFFFFFF,
MEDIA_IP_FMT_LAST = MEDIA_IP_FMT_UNSUPPORTED
} MEDIA_IP_FORMAT;
typedef enum {
VSys_FrmtNull = 0x0,
VSys_AvcFrmt = 0x1,
VSys_Mp2Frmt = 0x2,
VSys_Vc1Frmt = 0x3,
VSys_AvsFrmt = 0x4,
VSys_AspFrmt = 0x5,
VSys_JpgFrmt = 0x6,
VSys_RvFrmt = 0x7,
VSys_Vp6Frmt = 0x8,
VSys_SpkFrmt = 0x9,
VSys_Vp8Frmt = 0xA,
VSys_HevcFrmt = 0xB,
VSys_LastFrmt = VSys_HevcFrmt
} TB_API_DEC_FMT;
typedef struct {
u_int32 bTopFldFirst;
u_int32 bRptFstField;
u_int32 uDispVerRes;
u_int32 uDispHorRes;
u_int32 uCentreVerOffset;
u_int32 uCentreHorOffset;
u_int32 uCropLeftRightOffset;
u_int32 uCropTopBotOffset;
} MediaIPFW_Video_PicDispInfo;
typedef struct MediaIPFW_PicPerfInfo {
u_int32 uMemCRC;
u_int32 uBSCRC;
u_int32 uSlcActiveCnt;
u_int32 uIBEmptyCnt;
u_int32 uBaseMemCRC;
u_int32 uBaseCRCSkip;
u_int32 uBaseCRCDrop;
BOOL bBaseCRCValid;
u_int32 uCRC0;
u_int32 uCRC1;
u_int32 uCRC2;
u_int32 uCRC3;
u_int32 uCRC4;
u_int32 uCRC5;
u_int32 uFrameActCount;
u_int32 uRbspBytesCount;
u_int32 uDpbReadCount;
u_int32 uMprWaitCount;
u_int32 uAccQP;
u_int32 uCacheStat;
u_int32 mbq_full;
u_int32 mbq_empty;
u_int32 slice_cnt;
u_int32 mb_count;
u_int32 uTotalTime_us;
u_int32 uTotalFwTime_us;
u_int32 uProcIaccTotRdCnt;
u_int32 uProcDaccTotRdCnt;
u_int32 uProcDaccTotWrCnt;
u_int32 uProcDaccRegRdCnt;
u_int32 uProcDaccRegWrCnt;
u_int32 uProcDaccRngRdCnt;
u_int32 uProcDaccRngWrCnt;
} MediaIPFW_Video_PicPerfInfo;
typedef struct {
u_int32 mb_count;
u_int32 slice_cnt;
/* Front End Metrics */
u_int32 uDFEBinsUsed;
u_int32 uDFECycleCount;
u_int32 uDFESliceCycleCount;
u_int32 uDFEIBWaitCount;
u_int32 uDFENumBytes;
u_int32 uProcIaccTotRdCnt;
u_int32 uProcDaccTotRdCnt;
u_int32 uProcDaccTotWrCnt;
u_int32 uProcDaccRegRdCnt;
u_int32 uProcDaccRegWrCnt;
u_int32 uProcDaccRngRdCnt;
u_int32 uProcDaccRngWrCnt;
/* Back End metrics */
u_int32 uNumBEUsed;
u_int32 uTotalTime_us;
u_int32 uTotalFwTime_us;
u_int32 uDBECycleCount[0x2];
u_int32 uDBESliceCycleCount[0x2];
u_int32 uDBEMprWaitCount[0x2];
u_int32 uDBEWaitCount[0x2];
u_int32 uDBECRC[0x2];
u_int32 uDBETotalTime_us[0x2];
u_int32 uDBEMPRPRXWaitCount[0x2];
u_int32 uDBEPXDPRXWaitCount[0x2];
u_int32 uDBEFCHPLQWaitCount[0x2];
u_int32 uDBEPXDPLQWaitCount[0x2];
u_int32 uDBEFchWordsCount[0x2];
u_int32 uDBEDpbCRC[0x2];
u_int32 uDBEDpbReadCount[0x2];
u_int32 uDBECacheStats[0x2];
} MediaIPFW_Video_PicPerfDcpInfo, *pMediaIPFW_Video_PicPerfDcpInfo;
typedef struct {
u_int32 uPicType;
u_int32 uPicStruct;
u_int32 bLastPicNPF;
u_int32 uPicStAddr;
u_int32 uFrameStoreID;
MediaIPFW_Video_PicDispInfo DispInfo;
MediaIPFW_Video_PicPerfInfo PerfInfo;
MediaIPFW_Video_PicPerfDcpInfo PerfDcpInfo;
u_int32 bUserDataAvail;
u_int32 uPercentInErr;
u_int32 uBbdHorActive;
u_int32 uBbdVerActive;
u_int32 uBbdLogoActive;
u_int32 uBbdBotPrev;
u_int32 uBbdMinColPrj;
u_int32 uBbdMinRowPrj;
u_int32 uFSBaseAddr;
/* Only for RealVideo RPR */
u_int32 uRprPicWidth;
u_int32 uRprPicHeight;
/*only for divx3*/
u_int32 uFrameRate;
} MediaIPFW_Video_PicInfo;
typedef struct {
u_int32 bClosedGop;
u_int32 bBrokenLink;
} MediaIPFW_Video_GopInfo;
typedef struct {
u_int32 uIQuant;
u_int32 uIQuantAvail;
u_int32 uGopBitRate;
u_int32 uGopBitRateAvail;
} MediaIPFW_Video_QMeterInfo;
typedef struct {
u_int32 pPicInfoArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_PicInfoBuffTabDesc;
typedef struct {
u_int32 pGopInfoArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_GopInfoBuffTabDesc;
typedef struct {
u_int32 pQMeterInfoArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_QMeterInfoTabDesc;
typedef struct {
u_int32 uMemChunkBase;
u_int32 uMemChunkSize;
} MediaIPFW_Video_FrameBuffer;
typedef struct {
u_int32 uUDataBase;
u_int32 uUDataTotalSize;
u_int32 uUDataSlotSize;
} MediaIPFW_Video_UData;
typedef struct {
u_int32 uDecStatusLogBase;
u_int32 uDecStatusLogSize;
u_int32 uDTVLogBase[VID_API_NUM_STREAMS];
u_int32 uDTVLogSize[VID_API_NUM_STREAMS];
} MediaIPFW_Video_DbgLogDesc;
typedef struct {
u_int32 uDTVLogBase[VID_API_NUM_STREAMS];
u_int32 uDTVLogSize[VID_API_NUM_STREAMS];
} MediaIPFW_Video_EngAccessLogDesc;
typedef struct MediaIPFW_FrameStore {
u_int32 uFrameStoreLumaBase;
u_int32 uFrameStoreChromaBase;
} MediaIPFW_Video_FrameStore;
typedef struct {
u_int32 uAddrFirstDescriptor;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_StreamBuffTabDesc;
typedef struct {
u_int32 uAddrFirstDescriptor;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_UserDataBuffTabDesc;
typedef struct {
u_int32 uNumRefFrms;
u_int32 uNumDPBFrms;
u_int32 uNumDFEAreas;
u_int32 uColorDesc;
u_int32 uProgressive;
u_int32 uVerRes;
u_int32 uHorRes;
u_int32 uParWidth;
u_int32 uParHeight;
u_int32 FrameRate;
u_int32 UDispAspRatio;
u_int32 uLevelIDC;
u_int32 uVerDecodeRes;
u_int32 uHorDecodeRes;
u_int32 uOverScan;
u_int32 uChromaFmt;
u_int32 uPAFF;
u_int32 uMBAFF;
u_int32 uBitDepthLuma;
u_int32 uBitDepthChroma;
u_int32 uMVCNumViews;
u_int32 uMVCViewList[VID_API_MAX_NUM_MVC_VIEWS];
u_int32 uFBCInUse;
u_int32 uFrameCropValid;
u_int32 uFrameCropLeftOffset;
u_int32 uFrameCropRightOffset;
u_int32 uFrameCropTopOffset;
u_int32 uFrameCropBottomOffset;
} MediaIPFW_Video_SeqInfo;
typedef struct {
u_int32 pSeqInfoArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_SeqInfoBuffTabDesc;
typedef struct {
u_int32 wptr;
u_int32 rptr;
u_int32 start;
u_int32 end;
} BUFFER_DESCRIPTOR_TYPE, *pBUFFER_DESCRIPTOR_TYPE;
typedef struct {
u_int32 stream_input_mode;
u_int32 stream_pic_input_count;
u_int32 stream_pic_parsed_count;
} BUFFER_INFO_TYPE, *pBUFFER_INFO_TYPE;
typedef struct {
volatile u_int32 wptr;
volatile u_int32 rptr;
volatile u_int32 start;
volatile u_int32 end;
volatile u_int32 LWM;
} STREAM_BUFFER_DESCRIPTOR_TYPE, *pSTREAM_BUFFER_DESCRIPTOR_TYPE;
typedef struct {
u_int32 uRotationAngle;
u_int32 uHorizScaleFactor;
u_int32 uVertScaleFactor;
u_int32 uRotationMode;
u_int32 uRGBMode;
u_int32 uChunkMode; /* 0 ~ 1 */
u_int32 uLastChunk; /* 0 ~ 1 */
u_int32 uChunkRows; /* 0 ~ 255 */
u_int32 uNumBytes;
u_int32 uJpgCropXStart;
u_int32 uJpgCropYStart;
u_int32 uJpgCropWidth;
u_int32 uJpgCropHeight;
u_int32 uJpgMjpegMode;
u_int32 uJpgMjpegInterlaced;
} MediaIPFW_Video_JpegParams;
typedef struct {
u_int32 pJpegParamArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_JpegParamTabDesc;
typedef struct {
u_int32 uDispImm;
u_int32 uFourCC;
u_int32 uCodecVersion;
u_int32 uFrameRate;
u_int32 uEnableDbgLog;
u_int32 bbd_lum_thr;
u_int32 bbd_coring;
u_int32 bbd_s_thr_row;
u_int32 bbd_p_thr_row;
u_int32 bbd_s_thr_logo_row;
u_int32 bbd_p_thr_logo_row;
u_int32 bbd_s_thr_col;
u_int32 bbd_p_thr_col;
u_int32 bbd_chr_thr_row;
u_int32 bbd_chr_thr_col;
u_int32 bbd_uv_mid_level;
u_int32 bbd_excl_win_mb_left;
u_int32 bbd_excl_win_mb_right;
} MediaIPFW_Video_CodecParams;
typedef struct {
u_int32 uFramePitch;
} MediaIPFW_Video_PitchInfo;
typedef struct {
u_int32 uWrPtr;
u_int32 uRdPtr;
u_int32 uStart;
u_int32 uEnd;
u_int32 uLo;
u_int32 uHi;
} MediaIPFW_Video_BufDesc;
typedef struct {
u_int32 pCodecParamArrayBase;
u_int32 uNumSizeDescriptors;
} MediaIPFW_Video_CodecParamTabDesc;
typedef struct {
u_int32 uRC4Key[0x8];
u_int32 uMemObfuscVal;
} MediaIPFW_Video_Encrypt_Info, *pMediaIPFW_Video_Encrypt_Info;
typedef struct {
u_int32 uCfgCookie;
u_int32 uNumMalones;
u_int32 uMaloneBaseAddress[MEDIAIP_MAX_NUM_MALONES];
u_int32 uHifOffset[MEDIAIP_MAX_NUM_MALONES];
u_int32 uMaloneIrqPin[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS];
u_int32 uMaloneIrqTarget[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS];
u_int32 uNumWindsors;
u_int32 uWindsorBaseAddress[MEDIAIP_MAX_NUM_WINDSORS];
u_int32 uWindsorIrqPin[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS];
u_int32 uWindsorIrqTarget[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS];
u_int32 uCmdIrqPin[MEDIAIP_MAX_NUM_CMD_IRQ_PINS];
u_int32 uCmdIrqTarget[MEDIAIP_MAX_NUM_CMD_IRQ_PINS];
u_int32 uMsgIrqPin[MEDIAIP_MAX_NUM_MSG_IRQ_PINS];
u_int32 uMsgIrqTarget[MEDIAIP_MAX_NUM_MSG_IRQ_PINS];
u_int32 uSysClkFreq;
u_int32 uNumTimers;
u_int32 uTimerBaseAddr;
u_int32 uTimerIrqPin[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS];
u_int32 uTimerIrqTarget[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS];
u_int32 uTimerSlots[MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS];
u_int32 uGICBaseAddr;
u_int32 uUartBaseAddr;
u_int32 uDPVBaseAddr;
u_int32 uDPVIrqPin;
u_int32 uDPVIrqTarget;
u_int32 uPixIfBaseAddr;
u_int32 pal_trace_level;
u_int32 pal_trace_destination;
u_int32 pal_trace_level1;
u_int32 pal_trace_destination1;
u_int32 uHeapBase;
u_int32 uHeapSize;
u_int32 uFSLCacheBaseAddr[2];
} MEDIAIP_FW_SYSTEM_CONFIG, *pMEDIAIP_FW_SYSTEM_CONFIG;
typedef struct {
u_int32 FwExecBaseAddr;
u_int32 FwExecAreaSize;
MediaIPFW_Video_BufDesc StreamCmdBufferDesc;
MediaIPFW_Video_BufDesc StreamMsgBufferDesc;
u_int32 StreamCmdIntEnable[VID_API_NUM_STREAMS];
MediaIPFW_Video_PitchInfo StreamPitchInfo[VID_API_NUM_STREAMS];
u_int32 StreamConfig[VID_API_NUM_STREAMS];
MediaIPFW_Video_CodecParamTabDesc CodecParamTabDesc; /* TODO-KMC should we just go ahead and remove the concept of tabdesc? It is basicaly a bad coding style used for pinkys anyway */
MediaIPFW_Video_JpegParamTabDesc JpegParamTabDesc;
#ifdef COREPLAY_API
pBUFFER_DESCRIPTOR_TYPE pStreamBuffDesc[VID_API_NUM_STREAMS][VID_API_MAX_BUF_PER_STR];
#else
u_int32 pStreamBuffDesc[VID_API_NUM_STREAMS][VID_API_MAX_BUF_PER_STR];
#endif
MediaIPFW_Video_SeqInfoBuffTabDesc SeqInfoTabDesc;
MediaIPFW_Video_PicInfoBuffTabDesc PicInfoTabDesc;
MediaIPFW_Video_GopInfoBuffTabDesc GopInfoTabDesc;
MediaIPFW_Video_QMeterInfoTabDesc QMeterInfoTabDesc;
u_int32 StreamError[VID_API_NUM_STREAMS];
u_int32 FWVersion;
u_int32 uMVDMipsOffset;
u_int32 uMaxDecoderStreams;
MediaIPFW_Video_DbgLogDesc DbgLogDesc;
MediaIPFW_Video_FrameBuffer StreamFrameBuffer[VID_API_NUM_STREAMS];
MediaIPFW_Video_FrameBuffer StreamDCPBuffer[VID_API_NUM_STREAMS];
MediaIPFW_Video_UData UDataBuffer[VID_API_NUM_STREAMS];
MediaIPFW_Video_BufDesc DebugBufferDesc;
MediaIPFW_Video_BufDesc EngAccessBufferDesc[VID_API_NUM_STREAMS];
u_int32 ptEncryptInfo[VID_API_NUM_STREAMS];
MEDIAIP_FW_SYSTEM_CONFIG sSystemCfg;
u_int32 uApiVersion;
BUFFER_INFO_TYPE StreamBuffInfo[VID_API_NUM_STREAMS];
} DEC_RPC_HOST_IFACE, *pDEC_RPC_HOST_IFACE;
//x means source data , y means destination data
#define VID_STREAM_CONFIG_FORMAT_MASK 0x0000000F
#define VID_STREAM_CONFIG_FORMAT_POS 0
#define VID_STREAM_CONFIG_FORMAT_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_FORMAT_POS)&VID_STREAM_CONFIG_FORMAT_MASK)))
#define VID_STREAM_CONFIG_STRBUFIDX_MASK 0x00000300
#define VID_STREAM_CONFIG_STRBUFIDX_POS 8
#define VID_STREAM_CONFIG_STRBUFIDX_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_STRBUFIDX_POS)&VID_STREAM_CONFIG_STRBUFIDX_MASK)))
#define VID_STREAM_CONFIG_NOSEQ_MASK 0x00000400
#define VID_STREAM_CONFIG_NOSEQ_POS 10
#define VID_STREAM_CONFIG_NOSEQ_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_NOSEQ_POS)&VID_STREAM_CONFIG_NOSEQ_MASK)))
#define VID_STREAM_CONFIG_DEBLOCK_MASK 0x00000800
#define VID_STREAM_CONFIG_DEBLOCK_POS 11
#define VID_STREAM_CONFIG_DEBLOCK_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_DEBLOCK_POS)&VID_STREAM_CONFIG_DEBLOCK_MASK)))
#define VID_STREAM_CONFIG_DERING_MASK 0x00001000
#define VID_STREAM_CONFIG_DERING_POS 12
#define VID_STREAM_CONFIG_DERING_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_DERING_POS)&VID_STREAM_CONFIG_DERING_MASK)))
#define VID_STREAM_CONFIG_IBWAIT_MASK 0x00002000
#define VID_STREAM_CONFIG_IBWAIT_POS 13
#define VID_STREAM_CONFIG_IBWAIT_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_IBWAIT_POS)&VID_STREAM_CONFIG_IBWAIT_MASK)))
#define VID_STREAM_CONFIG_FBC_MASK 0x00004000
#define VID_STREAM_CONFIG_FBC_POS 14
#define VID_STREAM_CONFIG_FBC_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_FBC_POS)&VID_STREAM_CONFIG_FBC_MASK)))
#define VID_STREAM_CONFIG_PLAY_MODE_MASK 0x00030000
#define VID_STREAM_CONFIG_PLAY_MODE_POS 16
#define VID_STREAM_CONFIG_PLAY_MODE_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_PLAY_MODE_POS)&VID_STREAM_CONFIG_PLAY_MODE_MASK)))
#define VID_STREAM_CONFIG_ENABLE_DCP_MASK 0x00100000
#define VID_STREAM_CONFIG_ENABLE_DCP_POS 20
#define VID_STREAM_CONFIG_ENABLE_DCP_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_ENABLE_DCP_POS)&VID_STREAM_CONFIG_ENABLE_DCP_MASK)))
#define VID_STREAM_CONFIG_NUM_STR_BUF_MASK 0x00600000
#define VID_STREAM_CONFIG_NUM_STR_BUF_POS 21
#define VID_STREAM_CONFIG_NUM_STR_BUF_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_NUM_STR_BUF_POS)&VID_STREAM_CONFIG_NUM_STR_BUF_MASK)))
#define VID_STREAM_CONFIG_MALONE_USAGE_MASK 0x01800000
#define VID_STREAM_CONFIG_MALONE_USAGE_POS 23
#define VID_STREAM_CONFIG_MALONE_USAGE_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_MALONE_USAGE_POS)&VID_STREAM_CONFIG_MALONE_USAGE_MASK)))
#define VID_STREAM_CONFIG_MULTI_VID_MASK 0x02000000
#define VID_STREAM_CONFIG_MULTI_VID_POS 25
#define VID_STREAM_CONFIG_MULTI_VID_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_MULTI_VID_POS)&VID_STREAM_CONFIG_MULTI_VID_MASK)))
#define VID_STREAM_CONFIG_OBFUSC_EN_MASK 0x04000000
#define VID_STREAM_CONFIG_OBFUSC_EN_POS 26
#define VID_STREAM_CONFIG_OBFUSC_EN_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_OBFUSC_EN_POS)&VID_STREAM_CONFIG_OBFUSC_EN_MASK)))
#define VID_STREAM_CONFIG_RC4_EN_MASK 0x08000000
#define VID_STREAM_CONFIG_RC4_EN_POS 27
#define VID_STREAM_CONFIG_RC4_EN_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_RC4_EN_POS)&VID_STREAM_CONFIG_RC4_EN_MASK)))
#define VID_STREAM_CONFIG_MCX_MASK 0x10000000
#define VID_STREAM_CONFIG_MCX_POS 28
#define VID_STREAM_CONFIG_MCX_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_MCX_POS)&VID_STREAM_CONFIG_MCX_MASK)))
#define VID_STREAM_CONFIG_PES_MASK 0x20000000
#define VID_STREAM_CONFIG_PES_POS 29
#define VID_STREAM_CONFIG_PES_SET(x, y) ((*y = (*y | ((x << VID_STREAM_CONFIG_PES_POS)&VID_STREAM_CONFIG_PES_MASK))))
#define VID_STREAM_CONFIG_NUM_DBE_MASK 0x40000000
#define VID_STREAM_CONFIG_NUM_DBE_POS 30
#define VID_STREAM_CONFIG_NUM_DBE_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_NUM_DBE_POS)&VID_STREAM_CONFIG_NUM_DBE_MASK)))
#define VID_STREAM_CONFIG_FS_CTRL_MODE_MASK 0x80000000
#define VID_STREAM_CONFIG_FS_CTRL_MODE_POS 31
#define VID_STREAM_CONFIG_FS_CTRL_MODE_SET(x, y) (*y = (*y | ((x << VID_STREAM_CONFIG_FS_CTRL_MODE_POS)&VID_STREAM_CONFIG_FS_CTRL_MODE_MASK)))
#define SCB_XREG_SLV_BASE 0x00000000
#define SCB_SCB_BLK_CTRL 0x00070000
#define SCB_BLK_CTRL_XMEM_RESET_SET 0x00000090
#define SCB_BLK_CTRL_CACHE_RESET_SET 0x000000A0
#define SCB_BLK_CTRL_CACHE_RESET_CLR 0x000000A4
#define SCB_BLK_CTRL_SCB_CLK_ENABLE_SET 0x00000100
#define XMEM_CONTROL 0x00041000
#define DEC_MFD_XREG_SLV_BASE 0x00180000
#define MFD_HIF 0x0001C000
#define MFD_HIF_MSD_REG_INTERRUPT_STATUS 0x00000018
#define MFD_SIF 0x0001D000
#define MFD_SIF_CTRL_STATUS 0x000000F0
#define MFD_SIF_INTR_STATUS 0x000000F4
#define MFD_MCX 0x00020800
#define MFD_MCX_OFF 0x00000020
#define MFD_BLK_CTRL 0x00030000
#define MFD_BLK_CTRL_MFD_SYS_RESET_SET 0x00000000
#define MFD_BLK_CTRL_MFD_SYS_RESET_CLR 0x00000004
#define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_SET 0x00000100
#define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_CLR 0x00000104
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,320 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU Lesser General
* Public License. You may obtain a copy of the GNU Lesser General
* Public License Version 2.1 or later at the following locations:
*
* http://www.opensource.org/licenses/lgpl-license.html
* http://www.gnu.org/copyleft/lgpl.html
*/
/*!
* @file vpu_b0.h
*
* @brief VPU B0 definition
*
*/
#ifndef __VPU_B0_H
#define __VPU_B0_H
#include <linux/irqreturn.h>
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/videobuf2-v4l2.h>
//#include <soc/imx8/sc/svc/irq/api.h>
//#include <soc/imx8/sc/ipc.h>
//#include <soc/imx8/sc/sci.h>
#include <linux/mx8_mu.h>
#include <media/v4l2-event.h>
#include <linux/kfifo.h>
#include "vpu_rpc.h"
extern unsigned int vpu_dbg_level_decoder;
#define v4l2_fh_to_ctx(__fh) \
container_of(__fh, struct vpu_ctx, fh)
#define v4l2_ctrl_to_ctx(__ctrl) \
container_of((__ctrl)->handler, struct vpu_ctx, ctrl_handler)
#define MIN_SPACE (SCODE_SIZE + 64)
#define SCODE_SIZE (4096)
#define VPU_MAX_BUFFER 32
#define M0FW_FILENAME "vpu/vpu_fw_imx8_dec.bin"
#define MMAP_BUF_TYPE_SHIFT 28
#define MMAP_BUF_TYPE_MASK 0xF0000000
#define DCP_SIZE 0x3000000
#define MAX_BUFFER_SIZE 0xc00000
#define UDATA_BUFFER_SIZE 0x1000
#define MAX_DCP_NUM 2
#define MAX_MBI_NUM 18 // same with MEDIA_PLAYER_MAX_MBI_UNIT defined in firmware
#define MAX_TIMEOUT_COUNT 10
#define VPU_REG_BASE 0x40000000
#define V4L2_MAX_CTRLS 12
#define V4L2_PIX_FMT_NV12_10BIT v4l2_fourcc('N', 'T', '1', '2') /* Y/CbCr 4:2:0 for 10bit */
#define INVALID_FRAME_DEPTH -1
#define DECODER_NODE_NUMBER 12 // use /dev/video12 as vpu decoder
#define DEFAULT_LOG_DEPTH 20
#define V4L2_EVENT_SKIP 8
struct vpu_v4l2_control {
uint32_t id;
enum v4l2_ctrl_type type;
uint32_t minimum;
uint32_t maximum;
uint32_t step;
uint32_t default_value;
uint32_t menu_skip_mask;
bool is_volatile;
};
typedef enum{
INIT_DONE = 1,
RPC_BUF_OFFSET,
BOOT_ADDRESS,
COMMAND,
EVENT
} MSG_Type;
enum PLAT_TYPE {
IMX8QXP = 0,
IMX8QM = 1,
};
enum QUEUE_TYPE {
V4L2_SRC = 0,
V4L2_DST = 1,
};
enum vpu_video_standard {
VPU_VIDEO_UNDEFINED = 0,
VPU_VIDEO_AVC = 1,
VPU_VIDEO_VC1 = 2,
VPU_VIDEO_MPEG2 = 3,
VPU_VIDEO_AVS = 4,
VPU_VIDEO_ASP = 5,
VPU_VIDEO_JPEG = 6,
VPU_VIDEO_RV = 7,
VPU_VIDEO_VP6 = 8,
VPU_VIDEO_SPK = 9,
VPU_VIDEO_VP8 = 10,
VPU_VIDEO_AVC_MVC = 11,
VPU_VIDEO_HEVC = 12,
};
typedef enum{
EOS_PADDING_TYPE = 1,
BUFFLUSH_PADDING_TYPE = 2,
BUFABORT_PADDING_TYPE = 3,
} VPU_PADDING_SCODE_TYPE;
#define VPU_PIX_FMT_AVS v4l2_fourcc('A', 'V', 'S', '0')
#define VPU_PIX_FMT_ASP v4l2_fourcc('A', 'S', 'P', '0')
#define VPU_PIX_FMT_RV v4l2_fourcc('R', 'V', '0', '0')
#define VPU_PIX_FMT_VP6 v4l2_fourcc('V', 'P', '6', '0')
#define VPU_PIX_FMT_SPK v4l2_fourcc('S', 'P', 'K', '0')
#define VPU_PIX_FMT_DIVX v4l2_fourcc('D', 'I', 'V', 'X')
#define VPU_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
#define VPU_PIX_FMT_LOGO v4l2_fourcc('L', 'O', 'G', 'O')
#define VPU_PIX_FMT_TILED_8 v4l2_fourcc('Z', 'T', '0', '8')
#define VPU_PIX_FMT_TILED_10 v4l2_fourcc('Z', 'T', '1', '0')
#define V4L2_CID_USER_RAW_BASE (V4L2_CID_USER_BASE + 0x1100)
enum vpu_pixel_format {
VPU_HAS_COLOCATED = 0x00000001,
VPU_HAS_SPLIT_FLD = 0x00000002,
VPU_PF_MASK = ~(VPU_HAS_COLOCATED | VPU_HAS_SPLIT_FLD),
VPU_IS_TILED = 0x000000100,
VPU_HAS_10BPP = 0x00000200,
VPU_IS_PLANAR = 0x00001000,
VPU_IS_SEMIPLANAR = 0x00002000,
VPU_IS_PACKED = 0x00004000,
// Merged definitions using above flags:
VPU_PF_UNDEFINED = 0,
VPU_PF_YUV420_SEMIPLANAR = 0x00010000 | VPU_IS_SEMIPLANAR,
VPU_PF_YUV420_PLANAR = 0x00020000 | VPU_IS_PLANAR,
VPU_PF_UYVY = 0x00040000 | VPU_IS_PACKED,
VPU_PF_TILED_8BPP = 0x00080000 | VPU_IS_TILED | VPU_IS_SEMIPLANAR,
VPU_PF_TILED_10BPP = 0x00100000 | VPU_IS_TILED | VPU_IS_SEMIPLANAR | VPU_HAS_10BPP,
};
struct vpu_v4l2_fmt {
char *name;
unsigned int fourcc;
unsigned int num_planes;
unsigned int vdec_std;
unsigned int disable;
};
struct vb2_data_req {
struct list_head list;
struct vb2_buffer *vb2_buf;
int id;
u_int32 status;
bool bfield;
u_int32 phy_addr[2]; //0 for luma, 1 for chroma
u_int32 data_offset[2]; //0 for luma, 1 for chroma
};
struct queue_data {
unsigned int width;
unsigned int height;
unsigned int stride;
unsigned int bytesperline;
unsigned int num_planes;
unsigned int sizeimage[2];
unsigned int fourcc;
unsigned int vdec_std;
struct v4l2_rect rect;
int buf_type; // v4l2_buf_type
bool vb2_q_inited;
struct vb2_queue vb2_q; // vb2 queue
struct list_head drv_q; // driver queue
struct semaphore drv_q_lock;
struct vb2_data_req vb2_reqs[VPU_MAX_BUFFER];
enum QUEUE_TYPE type;
};
struct vpu_ctx;
struct vpu_dev {
struct device *generic_dev;
struct v4l2_device v4l2_dev;
struct video_device *pvpu_decoder_dev;
struct platform_device *plat_dev;
struct firmware *m0_pfw;
void *m0_p_fw_space_vir;
u_int32 m0_p_fw_space_phy;
u_int32 m0_boot_size;
void *m0_rpc_virt;
u_int32 m0_rpc_phy;
u_int32 m0_rpc_size;
struct mutex dev_mutex;
struct mutex cmd_mutex;
bool fw_is_ready;
bool firmware_started;
struct completion start_cmp;
struct completion snap_done_cmp;
struct workqueue_struct *workqueue;
struct work_struct msg_work;
unsigned long instance_mask;
unsigned long hang_mask; //this is used to deal with hang issue to reset firmware
//sc_ipc_t mu_ipcHandle;
struct clk *vpu_clk;
void __iomem *mu_base_virtaddr;
unsigned int vpu_mu_id;
int vpu_mu_init;
u_int32 plat_type;
struct clk *clk_m0;
void __iomem *regs_base;
void __iomem *csr_base;
u_int32 cm_offset;
struct shared_addr shared_mem;
struct vpu_ctx *ctx[VPU_MAX_NUM_STREAMS];
struct dentry *debugfs_root;
struct device *pd_vpu;
struct device *pd_dec;
struct device *pd_mu;
};
struct vpu_statistic {
unsigned long cmd[VID_API_CMD_YUV_READY + 2];
unsigned long event[VID_API_EVENT_DEC_CFG_INFO + 2];
unsigned long current_cmd;
unsigned long current_event;
struct timespec ts_cmd;
struct timespec ts_event;
atomic64_t total_dma_size;
atomic64_t total_alloc_size;
};
struct dma_buffer {
dma_addr_t dma_phy;
void *dma_virt;
u_int32 dma_size;
};
struct vpu_ctx {
struct vpu_dev *dev;
struct v4l2_fh fh;
struct vpu_statistic statistic;
atomic64_t total_alloc_size;
struct device_attribute dev_attr_instance_command;
char command_name[64];
struct device_attribute dev_attr_instance_event;
char event_name[64];
struct device_attribute dev_attr_instance_buffer;
char buffer_name[64];
struct device_attribute dev_attr_instance_flow;
char flow_name[64];
struct dentry *dbglog_dir;
char dbglog_name[64];
struct v4l2_ctrl *ctrls[V4L2_MAX_CTRLS];
struct v4l2_ctrl_handler ctrl_handler;
bool ctrl_inited;
struct list_head log_q;
int str_index;
struct queue_data q_data[2];
struct kfifo msg_fifo;
struct mutex instance_mutex;
struct work_struct instance_work;
struct workqueue_struct *instance_wq;
struct completion completion;
struct completion stop_cmp;
struct completion eos_cmp;
MediaIPFW_Video_SeqInfo *pSeqinfo;
bool b_dis_reorder;
bool b_firstseq;
bool start_flag;
bool wait_abort_done;
bool wait_rst_done;
bool buffer_null;
bool firmware_stopped;
bool firmware_finished;
bool eos_stop_received;
bool eos_stop_added;
bool ctx_released;
bool start_code_bypass;
bool hang_status;
wait_queue_head_t buffer_wq;
u_int32 mbi_count;
u_int32 mbi_num;
u_int32 dcp_count;
struct dma_buffer dpb_buffer;
struct dma_buffer dcp_buffer[MAX_DCP_NUM];
struct dma_buffer mbi_buffer[MAX_MBI_NUM];
struct dma_buffer stream_buffer;
struct dma_buffer udata_buffer;
int frm_dis_delay;
int frm_dec_delay;
int frm_total_num;
};
#define LVL_INFO 3
#define LVL_EVENT 2
#define LVL_WARN 1
#define LVL_ERR 0
#define vpu_dbg(level, fmt, arg...) \
do { \
if (vpu_dbg_level_decoder >= (level)) \
printk("[VPU Decoder]\t " fmt, ## arg); \
} while (0)
#endif

View File

@ -0,0 +1,137 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file vpu-debug_log.c
*
* copyright here may be changed later
*
*
*/
#include "vpu_debug_log.h"
int init_log_info_queue(struct vpu_ctx *ctx)
{
if (!ctx)
return -EINVAL;
mutex_lock(&ctx->instance_mutex);
INIT_LIST_HEAD(&ctx->log_q);
mutex_unlock(&ctx->instance_mutex);
return 0;
}
int create_log_info_queue(struct vpu_ctx *ctx, u_int32 vpu_log_depth)
{
struct vpu_log_info *vpu_info = NULL;
u_int32 i;
if (!ctx)
return -EINVAL;
for (i = 0; i < vpu_log_depth; i++) {
vpu_info = kzalloc(sizeof(*vpu_info), GFP_KERNEL);
if (!vpu_info)
continue;
atomic64_add(sizeof(*vpu_info), &ctx->statistic.total_alloc_size);
list_add_tail(&vpu_info->list, &ctx->log_q);
}
return 0;
}
int destroy_log_info_queue(struct vpu_ctx *ctx)
{
struct vpu_log_info *vpu_info, *temp_info;
u_int32 ret = 0;
if (!ctx)
return -EINVAL;
mutex_lock(&ctx->instance_mutex);
if (list_empty(&ctx->log_q)) {
ret = -EINVAL;
goto exit;
}
list_for_each_entry_safe(vpu_info, temp_info, &ctx->log_q, list)
if (vpu_info) {
list_del_init(&vpu_info->list);
kfree(vpu_info);
atomic64_sub(sizeof(*vpu_info), &ctx->statistic.total_alloc_size);
}
exit:
mutex_unlock(&ctx->instance_mutex);
return ret;
}
int put_log_info(struct vpu_ctx *ctx, struct vpu_log_info *vpu_info)
{
if (!ctx || !vpu_info)
return -EINVAL;
mutex_lock(&ctx->instance_mutex);
list_add_tail(&vpu_info->list, &ctx->log_q);
mutex_unlock(&ctx->instance_mutex);
return 0;
}
struct vpu_log_info *pop_log_info(struct vpu_ctx *ctx)
{
struct vpu_log_info *vpu_info = NULL;
if (!ctx)
return NULL;
mutex_lock(&ctx->instance_mutex);
if (list_empty(&ctx->log_q))
vpu_info = NULL;
vpu_info = list_first_entry(&ctx->log_q, struct vpu_log_info, list);
if (vpu_info)
list_del_init(&vpu_info->list);
mutex_unlock(&ctx->instance_mutex);
return vpu_info;
}
int set_log_info(struct vpu_log_info *vpu_info, enum ACTION_TYPE type, u_int32 info, u_int32 info_data)
{
if (!vpu_info)
return -EINVAL;
if (type >= LOG_RESERVED)
return -EINVAL;
vpu_info->type = type;
vpu_info->log_info[type] = info;
vpu_info->data = info_data;
return 0;
}
int record_log_info(struct vpu_ctx *ctx, enum ACTION_TYPE type, u_int32 info, u_int32 info_data)
{
struct vpu_log_info *vpu_info = NULL;
if (!ctx)
return -EINVAL;
vpu_info = pop_log_info(ctx);
if (!vpu_info)
return -EINVAL;
set_log_info(vpu_info, type, info, info_data);
put_log_info(ctx, vpu_info);
return 0;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU Lesser General
* Public License. You may obtain a copy of the GNU Lesser General
* Public License Version 2.1 or later at the following locations:
*
* http://www.opensource.org/licenses/lgpl-license.html
* http://www.gnu.org/copyleft/lgpl.html
*/
/*!
* @file vpu_debug_log.h
*
* @brief VPU debug definition
*
*/
#ifndef _VPU_DEBUG_LOG_H_
#define _VPU_DEBUG_LOG_H_
#include "vpu_b0.h"
enum ACTION_TYPE {
LOG_NULL = 0,
LOG_EVENT,
LOG_COMMAND,
LOG_PADDING,
LOG_EOS,
LOG_UPDATE_STREAM,
LOG_RESERVED,
};
struct vpu_log_info {
struct list_head list;
enum ACTION_TYPE type;
u_int32 log_info[LOG_RESERVED];
u_int32 data;
};
int init_log_info_queue(struct vpu_ctx *ctx);
int create_log_info_queue(struct vpu_ctx *ctx, u_int32 vpu_log_depth);
int destroy_log_info_queue(struct vpu_ctx *ctx);
int put_log_info(struct vpu_ctx *ctx, struct vpu_log_info *vpu_info);
struct vpu_log_info *pop_log_info(struct vpu_ctx *ctx);
int set_log_info(struct vpu_log_info *vpu_info, enum ACTION_TYPE type, u_int32 info, u_int32 info_data);
int record_log_info(struct vpu_ctx *ctx, enum ACTION_TYPE type, u_int32 info, u_int32 info_data);
#endif

View File

@ -0,0 +1,364 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/uaccess.h>
#include <linux/fs.h>
#include "vpu_rpc.h"
void rpc_init_shared_memory(struct shared_addr *This,
unsigned long long base_phy_addr,
void *base_virt_addr,
u_int32 total_size)
{
pDEC_RPC_HOST_IFACE pSharedInterface;
unsigned int phy_addr;
unsigned int i;
MediaIPFW_Video_BufDesc *pSharedCmdBufDescPtr;
MediaIPFW_Video_BufDesc *pSharedMsgBufDescPtr;
MediaIPFW_Video_BufDesc *pDebugBufferDesc;
MediaIPFW_Video_BufDesc *pEngAccessBufferDesc;
This->shared_mem_phy = base_phy_addr;
This->shared_mem_vir = base_virt_addr;
pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
This->pSharedInterface = pSharedInterface;
pSharedInterface->FwExecBaseAddr = base_phy_addr;
pSharedInterface->FwExecAreaSize = total_size;
pSharedCmdBufDescPtr = (MediaIPFW_Video_BufDesc *)&pSharedInterface->StreamCmdBufferDesc;
pSharedMsgBufDescPtr = (MediaIPFW_Video_BufDesc *)&pSharedInterface->StreamMsgBufferDesc;
phy_addr = base_phy_addr + sizeof(DEC_RPC_HOST_IFACE);
This->cmd_mem_phy = phy_addr;
This->cmd_mem_vir = This->shared_mem_vir + sizeof(DEC_RPC_HOST_IFACE);
pSharedCmdBufDescPtr->uWrPtr = phy_addr;
pSharedCmdBufDescPtr->uRdPtr = pSharedCmdBufDescPtr->uWrPtr;
pSharedCmdBufDescPtr->uStart = pSharedCmdBufDescPtr->uWrPtr;
pSharedCmdBufDescPtr->uEnd = pSharedCmdBufDescPtr->uStart + CMD_SIZE;
phy_addr += CMD_SIZE;
This->msg_mem_phy = phy_addr;
This->msg_mem_vir = This->cmd_mem_vir + CMD_SIZE;
pSharedMsgBufDescPtr->uWrPtr = phy_addr;
pSharedMsgBufDescPtr->uRdPtr = pSharedMsgBufDescPtr->uWrPtr;
pSharedMsgBufDescPtr->uStart = pSharedMsgBufDescPtr->uWrPtr;
pSharedMsgBufDescPtr->uEnd = pSharedMsgBufDescPtr->uStart + MSG_SIZE;
phy_addr += MSG_SIZE;
This->codec_mem_phy = phy_addr;
This->codec_mem_vir = This->msg_mem_vir + MSG_SIZE;
pSharedInterface->CodecParamTabDesc.pCodecParamArrayBase = This->codec_mem_phy;
phy_addr += CODEC_SIZE;
This->jpeg_mem_phy = phy_addr;
This->jpeg_mem_vir = This->codec_mem_vir + CODEC_SIZE;
pSharedInterface->JpegParamTabDesc.pJpegParamArrayBase = This->jpeg_mem_phy;
phy_addr += JPEG_SIZE;
This->seq_mem_phy = phy_addr;
This->seq_mem_vir = This->jpeg_mem_vir + JPEG_SIZE;
pSharedInterface->SeqInfoTabDesc.pSeqInfoArrayBase = This->seq_mem_phy;
phy_addr += SEQ_SIZE;
This->pic_mem_phy = phy_addr;
This->pic_mem_vir = This->seq_mem_vir + SEQ_SIZE;
pSharedInterface->PicInfoTabDesc.pPicInfoArrayBase = This->pic_mem_phy;
phy_addr += PIC_SIZE;
This->gop_mem_phy = phy_addr;
This->gop_mem_vir = This->pic_mem_vir + PIC_SIZE;
pSharedInterface->GopInfoTabDesc.pGopInfoArrayBase = This->gop_mem_phy;
phy_addr += GOP_SIZE;
This->qmeter_mem_phy = phy_addr;
This->qmeter_mem_vir = This->gop_mem_vir + GOP_SIZE;
pSharedInterface->QMeterInfoTabDesc.pQMeterInfoArrayBase = This->qmeter_mem_phy;
phy_addr += QMETER_SIZE;
pDebugBufferDesc = &pSharedInterface->DebugBufferDesc;
pDebugBufferDesc->uWrPtr = base_phy_addr + M0_PRINT_OFFSET;
pDebugBufferDesc->uRdPtr = pDebugBufferDesc->uWrPtr;
pDebugBufferDesc->uStart = pDebugBufferDesc->uWrPtr;
pDebugBufferDesc->uEnd = pDebugBufferDesc->uStart + DEBUG_SIZE;
This->dbglog_mem_phy = phy_addr;
This->dbglog_mem_vir = This->qmeter_mem_vir + QMETER_SIZE;
pSharedInterface->DbgLogDesc.uDecStatusLogBase = This->dbglog_mem_phy;
pSharedInterface->DbgLogDesc.uDecStatusLogSize = DBGLOG_SIZE;
phy_addr += DBGLOG_SIZE;
// phy_addr += sizeof(MediaIPFW_Video_BufDesc);
for (i = 0; i < VPU_MAX_NUM_STREAMS; i++) {
pEngAccessBufferDesc = &pSharedInterface->EngAccessBufferDesc[i];
pEngAccessBufferDesc->uWrPtr = phy_addr;
pEngAccessBufferDesc->uRdPtr = pEngAccessBufferDesc->uWrPtr;
pEngAccessBufferDesc->uStart = pEngAccessBufferDesc->uWrPtr;
pEngAccessBufferDesc->uEnd = pEngAccessBufferDesc->uStart + ENG_SIZE;
phy_addr += ENG_SIZE;
}
for (i = 0; i < VPU_MAX_NUM_STREAMS; i++) {
pSharedInterface->ptEncryptInfo[i] = phy_addr;
phy_addr += sizeof(MediaIPFW_Video_Encrypt_Info);
}
}
void rpc_set_stream_cfg_value(void *Interface, u_int32 str_idx, u_int32 vpu_dbe_num)
{
pDEC_RPC_HOST_IFACE pSharedInterface;
u_int32 *CurrStrfg;
pSharedInterface = (pDEC_RPC_HOST_IFACE)Interface;
CurrStrfg = &pSharedInterface->StreamConfig[str_idx];
*CurrStrfg = 0;
//the value should be passed from application
VID_STREAM_CONFIG_STRBUFIDX_SET(0, CurrStrfg);
VID_STREAM_CONFIG_NOSEQ_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_DEBLOCK_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_DERING_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_PLAY_MODE_SET(MEDIA_PLAYER_API_MODE_CONTINUOUS, CurrStrfg);
VID_STREAM_CONFIG_FS_CTRL_MODE_SET(MEDIA_PLAYER_FS_CTRL_MODE_EXTERNAL, CurrStrfg);
VID_STREAM_CONFIG_ENABLE_DCP_SET(TRUE, CurrStrfg);
VID_STREAM_CONFIG_NUM_STR_BUF_SET(1, CurrStrfg);
VID_STREAM_CONFIG_MALONE_USAGE_SET(1, CurrStrfg);
VID_STREAM_CONFIG_MULTI_VID_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_OBFUSC_EN_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_RC4_EN_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_MCX_SET(TRUE, CurrStrfg);
VID_STREAM_CONFIG_PES_SET(FALSE, CurrStrfg);
VID_STREAM_CONFIG_NUM_DBE_SET(vpu_dbe_num, CurrStrfg);
}
void rpc_set_system_cfg_value(void *Interface, u_int32 regs_base)
{
pDEC_RPC_HOST_IFACE pSharedInterface;
MEDIAIP_FW_SYSTEM_CONFIG *pSystemCfg;
pSharedInterface = (pDEC_RPC_HOST_IFACE)Interface;
pSystemCfg = &pSharedInterface->sSystemCfg;
pSystemCfg->uNumMalones = 1;
pSystemCfg->uMaloneBaseAddress[0] = (unsigned int)(regs_base + 0x180000);
pSystemCfg->uMaloneBaseAddress[0x1] = 0x0;
pSystemCfg->uHifOffset[0x0] = 0x1C000;
pSystemCfg->uHifOffset[0x1] = 0x0;
pSystemCfg->uDPVBaseAddr = 0x0;
pSystemCfg->uDPVIrqPin = 0x0;
pSystemCfg->uPixIfBaseAddr = (unsigned int)(regs_base + 0x180000 + 0x20000);
pSystemCfg->uFSLCacheBaseAddr[0] = (unsigned int)(regs_base + 0x60000);
pSystemCfg->uFSLCacheBaseAddr[1] = (unsigned int)(regs_base + 0x68000);
}
u_int32 rpc_MediaIPFW_Video_buffer_space_check(MediaIPFW_Video_BufDesc *pBufDesc,
BOOL bFull,
u_int32 uSize,
u_int32 *puUpdateAddress)
{
u_int32 uPtr1;
u_int32 uPtr2;
u_int32 uStart;
u_int32 uEnd;
u_int32 uTemp;
/* bFull is FALSE when send message, write data */
/* bFull is TRUE when process commands, read data */
uPtr1 = (bFull) ? pBufDesc->uRdPtr : pBufDesc->uWrPtr;
uPtr2 = (bFull) ? pBufDesc->uWrPtr : pBufDesc->uRdPtr;
if (uPtr1 == uPtr2) {
if (bFull)
/* No data at all to read */
return 0;
else {
/* wrt pointer equal to read pointer thus the */
/* buffer is completely empty for further writes */
uStart = pBufDesc->uStart;
uEnd = pBufDesc->uEnd;
/* The address to be returned in this case is for */
/* the updated write pointer. */
uTemp = uPtr1 + uSize;
if (uTemp >= uEnd)
uTemp += (uStart - uEnd);
*puUpdateAddress = uTemp;
return (uEnd - uStart);
}
} else if (uPtr1 < uPtr2) {
/* return updated rd pointer address */
/* In this case if size was too big - we expect the */
/* external ftn to compare the size against the */
/* space returned.
*/
*puUpdateAddress = uPtr1 + uSize;
return (uPtr2 - uPtr1);
}
/* We know the system has looped!! */
uStart = pBufDesc->uStart;
uEnd = pBufDesc->uEnd;
uTemp = uPtr1 + uSize;
if (uTemp >= uEnd)
uTemp += (uStart - uEnd);
*puUpdateAddress = uTemp;
return ((uEnd - uPtr1) + (uPtr2 - uStart));
}
static void rpc_update_cmd_buffer_ptr(MediaIPFW_Video_BufDesc *pCmdDesc)
{
u_int32 uWritePtr;
mb();
uWritePtr = pCmdDesc->uWrPtr + 4;
if (uWritePtr >= pCmdDesc->uEnd)
uWritePtr = pCmdDesc->uStart;
pCmdDesc->uWrPtr = uWritePtr;
}
void rpc_send_cmd_buf(struct shared_addr *This,
u_int32 idx,
u_int32 cmdid,
u_int32 cmdnum,
u_int32 *local_cmddata)
{
pDEC_RPC_HOST_IFACE pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
MediaIPFW_Video_BufDesc *pCmdDesc = &pSharedInterface->StreamCmdBufferDesc;
u_int32 *cmddata;
u_int32 i;
u_int32 *cmdword = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->uWrPtr - pCmdDesc->uStart);
*cmdword = 0;
*cmdword |= ((idx & 0x000000ff) << 24);
*cmdword |= ((cmdnum & 0x000000ff) << 16);
*cmdword |= ((cmdid & 0x00003fff) << 0);
rpc_update_cmd_buffer_ptr(pCmdDesc);
for (i = 0; i < cmdnum; i++) {
cmddata = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->uWrPtr - pCmdDesc->uStart);
*cmddata = local_cmddata[i];
rpc_update_cmd_buffer_ptr(pCmdDesc);
}
}
u_int32 rpc_MediaIPFW_Video_message_check(struct shared_addr *This)
{
u_int32 uSpace;
u_int32 uIgnore;
pDEC_RPC_HOST_IFACE pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
MediaIPFW_Video_BufDesc *pMsgDesc = &pSharedInterface->StreamMsgBufferDesc;
u_int32 msgword;
u_int32 msgnum;
uSpace = rpc_MediaIPFW_Video_buffer_space_check(pMsgDesc, TRUE, 0, &uIgnore);
uSpace = (uSpace >> 2);
if (uSpace) {
/* get current msgword word */
msgword = *((u_int32 *)(This->msg_mem_vir+pMsgDesc->uRdPtr - pMsgDesc->uStart));
/* Find the number of additional words */
msgnum = ((msgword & 0x00ff0000) >> 16);
/*
* * Check the number of message words against
* * 1) a limit - some sort of maximum or at least
* * the size of the SW buffer the message is read into
* * 2) The space reported (where space is write ptr - read ptr in 32bit words)
* * It must be less than space (as opposed to <=) because
* * the message itself is not included in msgword
*/
if (msgnum < VID_API_MESSAGE_LIMIT) {
if (msgnum < uSpace)
return API_MSG_AVAILABLE;
else
return API_MSG_INCOMPLETE;
} else
return API_MSG_BUFFER_ERROR;
}
return API_MSG_UNAVAILABLE;
}
static void rpc_update_msg_buffer_ptr(MediaIPFW_Video_BufDesc *pMsgDesc)
{
u_int32 uReadPtr;
mb();
uReadPtr = pMsgDesc->uRdPtr + 4;
if (uReadPtr >= pMsgDesc->uEnd)
uReadPtr = pMsgDesc->uStart;
pMsgDesc->uRdPtr = uReadPtr;
}
void rpc_receive_msg_buf(struct shared_addr *This, struct event_msg *msg)
{
unsigned int i;
pDEC_RPC_HOST_IFACE pSharedInterface = (pDEC_RPC_HOST_IFACE)This->shared_mem_vir;
MediaIPFW_Video_BufDesc *pMsgDesc = &pSharedInterface->StreamMsgBufferDesc;
u_int32 msgword = *((u_int32 *)(This->msg_mem_vir+pMsgDesc->uRdPtr - pMsgDesc->uStart));
msg->idx = ((msgword & 0xff000000) >> 24);
msg->msgnum = ((msgword & 0x00ff0000) >> 16);
msg->msgid = ((msgword & 0x00003fff) >> 0);
rpc_update_msg_buffer_ptr(pMsgDesc);
for (i = 0; i < msg->msgnum; i++) {
msg->msgdata[i] = *((u_int32 *)(This->msg_mem_vir+pMsgDesc->uRdPtr - pMsgDesc->uStart));
rpc_update_msg_buffer_ptr(pMsgDesc);
}
}

View File

@ -0,0 +1,118 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __VPU_IPC_H
#define __VPU_IPC_H
#include "mediasys_types.h"
#define CMD_SIZE 25600
#define MSG_SIZE 25600
#define CODEC_SIZE 0x1000
#define JPEG_SIZE 0x1000
#define SEQ_SIZE 0x1000
#define GOP_SIZE 0x1000
#define PIC_SIZE 0x1000
#define QMETER_SIZE 0x1000
#define DBGLOG_SIZE 0x10000
#define DEBUG_SIZE 0x80000
#define ENG_SIZE 0x1000
#define LOCAL_MSG_NUM VID_API_MESSAGE_LIMIT
#define M0_PRINT_OFFSET 0x180000
struct shared_addr {
pDEC_RPC_HOST_IFACE pSharedInterface;
unsigned long long shared_mem_phy;
void *shared_mem_vir;
unsigned long long cmd_mem_phy;
void *cmd_mem_vir;
unsigned long long msg_mem_phy;
void *msg_mem_vir;
unsigned long long codec_mem_phy;
void *codec_mem_vir;
unsigned long long jpeg_mem_phy;
void *jpeg_mem_vir;
unsigned long long seq_mem_phy;
void *seq_mem_vir;
unsigned long long pic_mem_phy;
void *pic_mem_vir;
unsigned long long gop_mem_phy;
void *gop_mem_vir;
unsigned long long qmeter_mem_phy;
void *qmeter_mem_vir;
unsigned long long dbglog_mem_phy;
void *dbglog_mem_vir;
};
struct event_msg {
u_int32 idx;
u_int32 msgnum;
u_int32 msgid;
u_int32 msgdata[LOCAL_MSG_NUM];
};
void rpc_init_shared_memory(struct shared_addr *This,
unsigned long long base_phy_addr,
void *base_virt_addr,
u_int32 total_size);
void rpc_set_system_cfg_value(void *Interface, u_int32 regs_base);
void rpc_set_stream_cfg_value(void *Interface, u_int32 str_idx, u_int32 vpu_dbe_num);
void rpc_send_cmd_buf(struct shared_addr *This,
u_int32 idx,
u_int32 cmdid,
u_int32 cmdnum,
u_int32 *local_cmddata);
void rpc_receive_msg_buf(struct shared_addr *This, struct event_msg *msg);
#endif

View File

@ -0,0 +1,25 @@
#
# Codec configuration
#
menu "MXC VPU(Video Processing Unit) WINDSOR support"
config MXC_VPU_WINDSOR
tristate "Support for MXC VPU(Video Processing Unit) ENCODER"
select MEDIA_SUPPORT
select VIDEO_DEV
select VIDEO_V4L2
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
default y
---help---
The VPU codec device provides codec function for H.264 etc.
config MXC_VPU_WINDSOR_DEBUG
bool "MXC VPU ENCODER debugging"
depends on MXC_VPU_WINDSOR != n
help
This is an option for the developers; most people should
say N here. This enables MXC VPU driver debugging.
endmenu

View File

@ -0,0 +1,15 @@
##
## Makefile for the VPU and M0 driver
##
EXTRA_CFLAGS += $(DEFINES)
obj-$(CONFIG_MXC_VPU_WINDSOR) = vpu-windsor.o
vpu-windsor-objs = vpu_encoder_b0.o \
vpu_encoder_ctrl.o \
vpu_event_msg.o \
vpu_encoder_mem.o \
vpu_encoder_rpc.o
clean:
rm -rf $(vpu-windsor-objs)

View File

@ -0,0 +1,705 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MEDIASYS_TYPES_H_
#define _MEDIASYS_TYPES_H_
typedef unsigned int u_int32;
typedef unsigned char u_int8;
typedef unsigned long u_int64;
typedef unsigned int BOOL;
typedef int int32;
#define FALSE 0
#define TRUE 1
#define VID_API_NUM_STREAMS 8
#define VID_API_MAX_BUF_PER_STR 3
#define VID_API_MAX_NUM_MVC_VIEWS 4
#define MEDIAIP_MAX_NUM_MALONES 2
#define MEDIAIP_MAX_NUM_MALONE_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_WINDSORS 1
#define MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_CMD_IRQ_PINS 2
#define MEDIAIP_MAX_NUM_MSG_IRQ_PINS 1
#define MEDIAIP_MAX_NUM_TIMER_IRQ_PINS 4
#define MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS 4
#define VID_API_COMMAND_LIMIT 64
#define VID_API_MESSAGE_LIMIT 256
#define API_CMD_AVAILABLE 0x0
#define API_CMD_INCOMPLETE 0x1
#define API_CMD_BUFFER_ERROR 0x2
#define API_CMD_UNAVAILABLE 0x3
#define API_MSG_AVAILABLE 0x0
#define API_MSG_INCOMPLETE 0x1
#define API_MSG_BUFFER_ERROR 0x2
#define API_MSG_UNAVAILABLE 0x3
#define MEDIAIP_ENC_USER_DATA_WORDS 16
#define MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES 0x6
#define MEDIAIP_MAX_NUM_WINDSOR_REF_FRAMES 0x3
typedef enum {
GTB_ENC_CMD_NOOP = 0x0,
GTB_ENC_CMD_STREAM_START,
GTB_ENC_CMD_FRAME_ENCODE,
GTB_ENC_CMD_FRAME_SKIP,
GTB_ENC_CMD_STREAM_STOP,
GTB_ENC_CMD_PARAMETER_UPD,
GTB_ENC_CMD_TERMINATE,
GTB_ENC_CMD_SNAPSHOT,
GTB_ENC_CMD_ROLL_SNAPSHOT,
GTB_ENC_CMD_LOCK_SCHEDULER,
GTB_ENC_CMD_UNLOCK_SCHEDULER,
GTB_ENC_CMD_CONFIGURE_CODEC,
GTB_ENC_CMD_DEAD_MARK,
GTB_ENC_CMD_FIRM_RESET,
GTB_ENC_CMD_RESERVED
} GTB_ENC_CMD;
typedef enum {
VID_API_EVENT_UNDEFINED = 0x0,
VID_API_ENC_EVENT_RESET_DONE = 0x1,
VID_API_ENC_EVENT_START_DONE,
VID_API_ENC_EVENT_STOP_DONE,
VID_API_ENC_EVENT_TERMINATE_DONE,
VID_API_ENC_EVENT_FRAME_INPUT_DONE,
VID_API_ENC_EVENT_FRAME_DONE,
VID_API_ENC_EVENT_FRAME_RELEASE,
VID_API_ENC_EVENT_PARA_UPD_DONE,
VID_API_ENC_EVENT_MEM_REQUEST,
VID_API_ENC_EVENT_FIRMWARE_XCPT,
VID_API_ENC_EVENT_RESERVED
} ENC_TB_API_ENC_EVENT;
typedef enum {
MEDIAIP_ENC_PIC_TYPE_B_FRAME = 0,
MEDIAIP_ENC_PIC_TYPE_P_FRAME,
MEDIAIP_ENC_PIC_TYPE_I_FRAME,
MEDIAIP_ENC_PIC_TYPE_IDR_FRAME,
MEDIAIP_ENC_PIC_TYPE_BI_FRAME
} MEDIAIP_ENC_PIC_TYPE, *pMEDIAIP_ENC_PIC_TYPE;
typedef struct {
u_int32 uMemPhysAddr;
u_int32 uMemVirtAddr;
u_int32 uMemSize;
} MEDIAIP_ENC_MEM_RESOURCE, *pMEDIAIP_ENC_MEM_RESOURCE;
typedef struct {
u_int32 uEncFrmSize;
u_int32 uEncFrmNum;
u_int32 uRefFrmSize;
u_int32 uRefFrmNum;
u_int32 uActBufSize;
} MEDIAIP_ENC_MEM_REQ_DATA, *pMEDIAIP_ENC_MEM_REQ_DATA;
typedef struct {
MEDIAIP_ENC_MEM_RESOURCE tEncFrameBuffers[MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES];
MEDIAIP_ENC_MEM_RESOURCE tRefFrameBuffers[MEDIAIP_MAX_NUM_WINDSOR_REF_FRAMES];
MEDIAIP_ENC_MEM_RESOURCE tActFrameBufferArea;
} MEDIAIP_ENC_MEM_POOL, *pMEDIAIP_ENC_MEM_POOL;
///////////////////////////////////////////
// MEDIAIP_ENC_PIC_TYPE
typedef struct {
u_int32 uFrameID;
u_int32 uPicEncodDone;
MEDIAIP_ENC_PIC_TYPE ePicType;
u_int32 uSkippedFrame;
u_int32 uErrorFlag;
u_int32 uPSNR;
u_int32 uFlushDone;
u_int32 uMBy;
u_int32 uMBx;
u_int32 uFrameSize;
u_int32 uFrameEncTtlCycles;
u_int32 uFrameEncTtlFrmCycles;
u_int32 uFrameEncTtlSlcCycles;
u_int32 uFrameEncTtlEncCycles;
u_int32 uFrameEncTtlHmeCycles;
u_int32 uFrameEncTtlDsaCycles;
u_int32 uFrameEncFwCycles;
u_int32 uFrameCrc;
u_int32 uNumInterrupts_1;
u_int32 uNumInterrupts_2;
u_int32 uH264POC;
u_int32 uRefInfo;
u_int32 uPicNum;
u_int32 uPicActivity;
u_int32 uSceneChange;
u_int32 uMBStats;
u_int32 uEncCacheCount0;
u_int32 uEncCacheCount1;
u_int32 uMtlWrStrbCnt;
u_int32 uMtlRdStrbCnt;
u_int32 uStrBuffWrPtr;
u_int32 uDiagnosticEvents;
u_int32 uProcIaccTotRdCnt;
u_int32 uProcDaccTotRdCnt;
u_int32 uProcDaccTotWrCnt;
u_int32 uProcDaccRegRdCnt;
u_int32 uProcDaccRegWrCnt;
u_int32 uProcDaccRngRdCnt;
u_int32 uProcDaccRngWrCnt;
} MEDIAIP_ENC_PIC_INFO, *pMEDIAIP_ENC_PIC_INFO;
typedef enum {
MEDIAIP_PLAYMODE_CONNECTIVITY = 0,
MEDIAIP_PLAYMODE_BROADCAST,
MEDIAIP_PLAYMODE_BROADCAST_DSS,
MEDIAIP_PLAYMODE_LAST = MEDIAIP_PLAYMODE_BROADCAST_DSS
} MEDIA_IP_PLAYMODE;
typedef struct {
u_int32 wptr;
u_int32 rptr;
u_int32 start;
u_int32 end;
} BUFFER_DESCRIPTOR_TYPE, *pBUFFER_DESCRIPTOR_TYPE;
typedef struct {
u_int32 uWrPtr;
u_int32 uRdPtr;
u_int32 uStart;
u_int32 uEnd;
u_int32 uLo;
u_int32 uHi;
} MediaIPFW_Video_BufDesc;
typedef struct {
u_int32 uCfgCookie;
u_int32 uNumMalones;
u_int32 uMaloneBaseAddress[MEDIAIP_MAX_NUM_MALONES];
u_int32 uHifOffset[MEDIAIP_MAX_NUM_MALONES];
u_int32 uMaloneIrqPin[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS];
u_int32 uMaloneIrqTarget[MEDIAIP_MAX_NUM_MALONES][MEDIAIP_MAX_NUM_MALONE_IRQ_PINS];
u_int32 uNumWindsors;
u_int32 uWindsorBaseAddress[MEDIAIP_MAX_NUM_WINDSORS];
u_int32 uWindsorIrqPin[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS];
u_int32 uWindsorIrqTarget[MEDIAIP_MAX_NUM_WINDSORS][MEDIAIP_MAX_NUM_WINDSOR_IRQ_PINS];
u_int32 uCmdIrqPin[MEDIAIP_MAX_NUM_CMD_IRQ_PINS];
u_int32 uCmdIrqTarget[MEDIAIP_MAX_NUM_CMD_IRQ_PINS];
u_int32 uMsgIrqPin[MEDIAIP_MAX_NUM_MSG_IRQ_PINS];
u_int32 uMsgIrqTarget[MEDIAIP_MAX_NUM_MSG_IRQ_PINS];
u_int32 uSysClkFreq;
u_int32 uNumTimers;
u_int32 uTimerBaseAddr;
u_int32 uTimerIrqPin[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS];
u_int32 uTimerIrqTarget[MEDIAIP_MAX_NUM_TIMER_IRQ_PINS];
u_int32 uTimerSlots[MEDIAIP_MAX_NUM_TIMER_IRQ_SLOTS];
u_int32 uGICBaseAddr;
u_int32 uUartBaseAddr;
u_int32 uDPVBaseAddr;
u_int32 uDPVIrqPin;
u_int32 uDPVIrqTarget;
u_int32 uPixIfBaseAddr;
u_int32 pal_trace_level;
u_int32 pal_trace_destination;
u_int32 pal_trace_level1;
u_int32 pal_trace_destination1;
u_int32 uHeapBase;
u_int32 uHeapSize;
u_int32 uFSLCacheBaseAddr[2];
} MEDIAIP_FW_SYSTEM_CONFIG, *pMEDIAIP_FW_SYSTEM_CONFIG;
typedef struct {
u_int32 uFrameID;
u_int32 uLumaBase;
u_int32 uChromaBase;
u_int32 uParamIdx;
u_int32 uKeyFrame;
} MEDIAIP_ENC_YUV_BUFFER_DESC, *pMEDIAIP_ENC_YUV_BUFFER_DESC;
typedef struct {
u_int32 use_ame;
u_int32 cme_mvx_max;
u_int32 cme_mvy_max;
u_int32 ame_prefresh_y0;
u_int32 ame_prefresh_y1;
u_int32 fme_min_sad;
u_int32 cme_min_sad;
u_int32 fme_pred_int_weight;
u_int32 fme_pred_hp_weight;
u_int32 fme_pred_qp_weight;
u_int32 fme_cost_weight;
u_int32 fme_act_thold;
u_int32 fme_sad_thold;
u_int32 fme_zero_sad_thold;
u_int32 fme_lrg_mvx_lmt;
u_int32 fme_lrg_mvy_lmt;
u_int32 fme_force_mode;
u_int32 fme_force4mvcost;
u_int32 fme_force2mvcost;
u_int32 h264_inter_thrd;
u_int32 i16x16_mode_cost;
u_int32 i4x4_mode_lambda;
u_int32 i8x8_mode_lambda;
u_int32 inter_mod_mult;
u_int32 inter_sel_mult;
u_int32 inter_bid_cost;
u_int32 inter_bwd_cost;
u_int32 inter_4mv_cost;
int32 one_mv_i16_cost;
int32 one_mv_i4x4_cost;
int32 one_mv_i8x8_cost;
int32 two_mv_i16_cost;
int32 two_mv_i4x4_cost;
int32 two_mv_i8x8_cost;
int32 four_mv_i16_cost;
int32 four_mv_i4x4_cost;
int32 four_mv_i8x8_cost;
u_int32 intra_pred_enab;
u_int32 intra_chr_pred;
u_int32 intra16_pred;
u_int32 intra4x4_pred;
u_int32 intra8x8_pred;
u_int32 cb_base;
u_int32 cb_size;
u_int32 cb_head_room;
u_int32 mem_page_width;
u_int32 mem_page_height;
u_int32 mem_total_size;
u_int32 mem_chunk_phys_addr;
u_int32 mem_chunk_virt_addr;
u_int32 mem_chunk_size;
u_int32 mem_y_stride;
u_int32 mem_uv_stride;
u_int32 split_wr_enab;
u_int32 split_wr_req_size;
u_int32 split_rd_enab;
u_int32 split_rd_req_size;
} MEDIAIP_ENC_CALIB_PARAMS, *pMEDIAIP_ENC_CALIB_PARAMS;
typedef struct {
u_int32 ParamChange;
u_int32 start_frame; // These variables are for debugging purposes only
u_int32 end_frame;
u_int32 userdata_enable;
u_int32 userdata_id[4];
u_int32 userdata_message[MEDIAIP_ENC_USER_DATA_WORDS];
u_int32 userdata_length;
u_int32 h264_profile_idc;
u_int32 h264_level_idc;
u_int32 h264_au_delimiter; // Enable the use of Access Unit Delimiters
u_int32 h264_seq_end_code; // Enable the use of Sequence End Codes
u_int32 h264_recovery_points; // Enable the use of Recovery Points (must be with a fixed GOP structure)
u_int32 h264_vui_parameters; // Enable the use of VUI parameters (for rate control purposes)
u_int32 h264_aspect_ratio_present;
u_int32 h264_aspect_ratio_sar_width;
u_int32 h264_aspect_ratio_sar_height;
u_int32 h264_overscan_present;
u_int32 h264_video_type_present;
u_int32 h264_video_format;
u_int32 h264_video_full_range;
u_int32 h264_video_colour_descriptor;
u_int32 h264_video_colour_primaries;
u_int32 h264_video_transfer_char;
u_int32 h264_video_matrix_coeff;
u_int32 h264_chroma_loc_info_present;
u_int32 h264_chroma_loc_type_top;
u_int32 h264_chroma_loc_type_bot;
u_int32 h264_timing_info_present;
u_int32 h264_buffering_period_present;
u_int32 h264_low_delay_hrd_flag;
u_int32 aspect_ratio;
u_int32 test_mode; // Automated firmware test mode
u_int32 dsa_test_mode; // Automated test mode for the DSA.
u_int32 fme_test_mode; // Automated test mode for the fme
u_int32 cbr_row_mode; //0: FW mode; 1: HW mode
u_int32 windsor_mode; //0: normal mode; 1: intra only mode; 2: intra+0MV mode
u_int32 encode_mode; // H264, VC1, MPEG2, DIVX
u_int32 frame_width; // display width
u_int32 frame_height; // display height
u_int32 enc_frame_width; // encoding width, should be 16-pix align
u_int32 enc_frame_height; // encoding height, should be 16-pix aligned for progressive and 32-pix aligned for interlace
u_int32 frame_rate_num;
u_int32 frame_rate_den;
u_int32 vi_field_source; // vi input source is frame or field
u_int32 vi_frame_width;
u_int32 vi_frame_height;
u_int32 crop_frame_width;
u_int32 crop_frame_height;
u_int32 crop_x_start_posn;
u_int32 crop_y_start_posn;
u_int32 mode422;
u_int32 mode_yuy2;
u_int32 dsa_luma_en;
u_int32 dsa_chroma_en;
u_int32 dsa_ext_hfilt_en;
u_int32 dsa_di_en;
u_int32 dsa_di_top_ref;
u_int32 dsa_vertf_disable; // disable the vertical filter.
u_int32 dsa_disable_pwb;
u_int32 dsa_hor_phase;
u_int32 dsa_ver_phase;
u_int32 dsa_iac_enable; // IAC / DSA cannot operate independently in FW so this variable controls
u_int32 iac_sc_threshold;
u_int32 iac_vm_threshold;
u_int32 iac_skip_mode;
u_int32 iac_grp_width;
u_int32 iac_grp_height;
u_int32 rate_control_mode;
u_int32 rate_control_resolution;
u_int32 buffer_size;
u_int32 buffer_level_init;
u_int32 buffer_I_bit_budget;
u_int32 top_field_first;
u_int32 intra_lum_qoffset;
u_int32 intra_chr_qoffset;
u_int32 inter_lum_qoffset;
u_int32 inter_chr_qoffset;
u_int32 use_def_scaling_mtx;
u_int32 inter_8x8_enab;
u_int32 inter_4x4_enab;
u_int32 fme_enable_qpel;
u_int32 fme_enable_hpel;
u_int32 fme_nozeromv; // can force the FME not to do the (0,0) search.
u_int32 fme_predmv_en;
u_int32 fme_pred_2mv4mv;
u_int32 fme_smallsadthresh;
u_int32 ame_en_lmvc;
u_int32 ame_x_mult;
u_int32 cme_enable_4mv; // Enable the use of 4MV partitioning
u_int32 cme_enable_1mv;
u_int32 hme_enable_16x8mv;
u_int32 hme_enable_8x16mv;
u_int32 cme_mv_weight; // CME motion vector decisions are made by combining these
u_int32 cme_mv_cost; // cost and weight variables
u_int32 ame_mult_mv;
u_int32 ame_shift_mv;
u_int32 hme_forceto1mv_en;
u_int32 hme_2mv_cost; // the cost of choosing a 2MV mode over 1MV.
u_int32 hme_pred_mode;
u_int32 hme_sc_rnge;
u_int32 hme_sw_rnge;
// for windsor pes , add by fulin
u_int32 output_format; // 0: output ES; 1: output PES
u_int32 timestamp_enab; // 0: have timestamps in all frame; 1: have timestamps in I and P frame; 2: have timestamps only in I frame
u_int32 initial_PTS_enab; // if enabled , use following value,else compute by fw
u_int32 initial_PTS; // the initial value of PTS in the first frame (ms)
} MEDIAIP_ENC_CONFIG_PARAMS, *pMEDIAIP_ENC_CONFIG_PARAMS;
typedef struct {
u_int32 ParamChange;
u_int32 gop_length;
u_int32 rate_control_bitrate;
u_int32 rate_control_bitrate_min;
u_int32 rate_control_bitrate_max;
u_int32 rate_control_content_models;
u_int32 rate_control_iframe_maxsize; // Maximum size of I frame generated by BPM in comparison to ideal (/4)
u_int32 rate_control_qp_init;
u_int32 rate_control_islice_qp;
u_int32 rate_control_pslice_qp;
u_int32 rate_control_bslice_qp;
u_int32 adaptive_quantization; // Enable the use of activity measures from VIPP in QP assignment
u_int32 aq_variance;
u_int32 cost_optimization; // Enable picture/frame level adjustments of the cost parameters by FW.
u_int32 fdlp_mode; // Frequency-domain low-pass filter control, 0: off, 1-4: specific, 5: adaptive
u_int32 enable_isegbframes; // Enable the use of B frames in the first segment of a GOP
u_int32 enable_adaptive_keyratio; // Enable the use of an adaptive I to P/B ratio (aims to reduce distortion)
u_int32 keyratio_imin; // Clamps applied to picture size ratios
u_int32 keyratio_imax;
u_int32 keyratio_pmin;
u_int32 keyratio_pmax;
u_int32 keyratio_bmin;
u_int32 keyratio_bmax;
int32 keyratio_istep;
int32 keyratio_pstep;
int32 keyratio_bstep;
u_int32 enable_paff; // Enable Picture Adaptive Frame/Field
u_int32 enable_b_frame_ref; // Enable B frame as references
u_int32 enable_adaptive_gop; // Enable an adaptive GOP structure
u_int32 enable_closed_gop; // Enable a closed GOP structure
// i.e. if enabled, the first consecutive B frames following
// an I frame in each GOP will be intra or backwards only coded
// and do not rely on previous reference pictures.
u_int32 open_gop_refresh_freq; // Controls the insertion of closed GOP's (or IDR GOP's in H.264)
u_int32 enable_adaptive_sc; // Enable adaptive scene change GOP structure (0:off, 1:adaptive, 2:IDR)
u_int32 enable_fade_detection; // Enable fade detection and associated motion estimation restrictions
int32 fade_detection_threshold; // Threshold at which the activity slope indicates a possible fading event
u_int32 enable_repeat_b; // Enalbe the repeated B frame mode at CBR
u_int32 enable_low_delay_b; // Use low delay-b frames with an IPPPP style GOP
} MEDIAIP_ENC_STATIC_PARAMS, *pMEDIAIP_ENC_STATIC_PARAMS;
typedef struct {
u_int32 ParamChange;
u_int32 rows_per_slice;
u_int32 mbaff_enable; // Macroblock adaptive frame/field enable
u_int32 dbf_enable; // Enable the deblocking filter
u_int32 field_source; // progressive/interlaced control
u_int32 gop_b_length; // Number of B frames between anchor frames
// (only to be changed at a GOP segment boundary)
u_int32 mb_group_size; // Number of macroblocks normally assigned to a group
// (implications for performance, interrupts and rate control)
u_int32 cbr_rows_per_group;
u_int32 skip_enable; // Enable the use of skipped macroblocks
u_int32 pts_bits_0_to_31; // TO BE REMOVED...
u_int32 pts_bit_32;
u_int32 rm_expsv_cff;
u_int32 const_ipred;
int32 chr_qp_offset;
u_int32 intra_mb_qp_offset;
u_int32 h264_cabac_init_method;
u_int32 h264_cabac_init_idc;
u_int32 h264_cabac_enable; // Main and stream
int32 alpha_c0_offset_div2;
int32 beta_offset_div2;
u_int32 intra_prefresh_y0; // for setting intra limits for prog refresh.
u_int32 intra_prefresh_y1;
u_int32 dbg_dump_rec_src;
} MEDIAIP_ENC_DYN_PARAMS, *pMEDIAIP_ENC_DYN_PARAMS;
typedef struct {
MEDIAIP_ENC_CALIB_PARAMS Calib;
MEDIAIP_ENC_CONFIG_PARAMS Config;
MEDIAIP_ENC_STATIC_PARAMS Static;
MEDIAIP_ENC_DYN_PARAMS Dynamic;
} MEDIAIP_ENC_EXPERT_MODE_PARAM, *pMEDIAIP_ENC_EXPERT_MODE_PARAM;
typedef enum {
MEDIAIP_ENC_FMT_H264 = 0,
MEDIAIP_ENC_FMT_VC1,
MEDIAIP_ENC_FMT_MPEG2,
MEDIAIP_ENC_FMT_MPEG4SP,
MEDIAIP_ENC_FMT_H263,
MEDIAIP_ENC_FMT_MPEG1,
MEDIAIP_ENC_FMT_SHORT_HEADER,
MEDIAIP_ENC_FMT_NULL
} MEDIAIP_ENC_FMT;
typedef enum {
MEDIAIP_ENC_PROF_MPEG2_SP = 0,
MEDIAIP_ENC_PROF_MPEG2_MP,
MEDIAIP_ENC_PROF_MPEG2_HP,
MEDIAIP_ENC_PROF_H264_BP,
MEDIAIP_ENC_PROF_H264_MP,
MEDIAIP_ENC_PROF_H264_HP,
MEDIAIP_ENC_PROF_MPEG4_SP,
MEDIAIP_ENC_PROF_MPEG4_ASP,
MEDIAIP_ENC_PROF_VC1_SP,
MEDIAIP_ENC_PROF_VC1_MP,
MEDIAIP_ENC_PROF_VC1_AP
} MEDIAIP_ENC_PROFILE;
typedef enum {
MEDIAIP_ENC_BITRATECONTROLMODE_VBR = 0x00000001,
MEDIAIP_ENC_BITRATECONTROLMODE_CBR = 0x00000002,
MEDIAIP_ENC_BITRATECONTROLMODE_CONSTANT_QP = 0x00000004 /* Only in debug mode */
} MEDIAIP_ENC_BITRATE_MODE, *pMEDIAIP_ENC_BITRATE_MODE;
typedef struct {
MEDIAIP_ENC_FMT eCodecMode;
MEDIAIP_ENC_PROFILE eProfile;
u_int32 uLevel;
MEDIAIP_ENC_MEM_RESOURCE tEncMemDesc;
u_int32 uFrameRate;
u_int32 uSrcStride;
u_int32 uSrcWidth;
u_int32 uSrcHeight;
u_int32 uSrcOffset_x;
u_int32 uSrcOffset_y;
u_int32 uSrcCropWidth;
u_int32 uSrcCropHeight;
u_int32 uOutWidth;
u_int32 uOutHeight;
u_int32 uIFrameInterval;
u_int32 uGopBLength;
u_int32 uLowLatencyMode;
MEDIAIP_ENC_BITRATE_MODE eBitRateMode;
u_int32 uTargetBitrate;
u_int32 uMaxBitRate;
u_int32 uMinBitRate;
u_int32 uInitSliceQP;
} MEDIAIP_ENC_PARAM, *pMEDIAIP_ENC_PARAM;
typedef struct {
u_int32 uFrameID;
u_int32 uErrorFlag; //Error type
u_int32 uMBy;
u_int32 uMBx;
u_int32 uReserved[12];
} ENC_ENCODING_STATUS, *pENC_ENCODING_STATUS;
typedef struct {
u_int32 uFrameID;
u_int32 uDsaCyle;
u_int32 uMBy;
u_int32 uMBx;
u_int32 uReserved[4];
} ENC_DSA_STATUS_t, *pENC_DSA_STATUS_t;
typedef struct {
u_int32 pEncYUVBufferDesc;
u_int32 pEncStreamBufferDesc;
u_int32 pEncExpertModeParam;
u_int32 pEncParam;
u_int32 pEncMemPool;
/* Status information for master to read */
u_int32 pEncEncodingStatus;
u_int32 pEncDSAStatus;
} MEDIA_ENC_API_CONTROL_INTERFACE, *pMEDIA_ENC_API_CONTROL_INTERFACE;
typedef struct {
u_int32 FwExecBaseAddr;
u_int32 FwExecAreaSize;
BUFFER_DESCRIPTOR_TYPE StreamCmdBufferDesc;
BUFFER_DESCRIPTOR_TYPE StreamMsgBufferDesc;
u_int32 StreamCmdIntEnable[VID_API_NUM_STREAMS];
u_int32 FWVersion;
u_int32 uMVDFWOffset;
u_int32 uMaxEncoderStreams;
u_int32 pEncCtrlInterface[VID_API_NUM_STREAMS];
MEDIAIP_FW_SYSTEM_CONFIG sSystemCfg;
u_int32 uApiVersion;
BUFFER_DESCRIPTOR_TYPE DebugBufferDesc;
} ENC_RPC_HOST_IFACE, *pENC_RPC_HOST_IFACE;
#define SCB_XREG_SLV_BASE 0x00000000
#define SCB_SCB_BLK_CTRL 0x00070000
#define SCB_BLK_CTRL_XMEM_RESET_SET 0x00000090
#define SCB_BLK_CTRL_CACHE_RESET_SET 0x000000A0
#define SCB_BLK_CTRL_CACHE_RESET_CLR 0x000000A4
#define SCB_BLK_CTRL_SCB_CLK_ENABLE_SET 0x00000100
#define XMEM_CONTROL 0x00041000
#define DEC_MFD_XREG_SLV_BASE 0x00180000
#define MFD_HIF 0x0001C000
#define MFD_HIF_MSD_REG_INTERRUPT_STATUS 0x00000018
#define MFD_SIF 0x0001D000
#define MFD_SIF_CTRL_STATUS 0x000000F0
#define MFD_SIF_INTR_STATUS 0x000000F4
#define MFD_MCX 0x00020800
#define MFD_MCX_OFF 0x00000020
#define MFD_BLK_CTRL 0x00030000
#define MFD_BLK_CTRL_MFD_SYS_RESET_SET 0x00000000
#define MFD_BLK_CTRL_MFD_SYS_RESET_CLR 0x00000004
#define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_SET 0x00000100
#define MFD_BLK_CTRL_MFD_SYS_CLOCK_ENABLE_CLR 0x00000104
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,419 @@
/*
* Copyright 2018 NXP
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file vpu_encoder_b0.h
*
* @brief VPU ENCODER B0 definition
*
*/
#ifndef __VPU_ENCODER_B0_H__
#define __VPU_ENCODER_B0_H__
#include <linux/irqreturn.h>
#include <linux/mutex.h>
#include <linux/videodev2.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/videobuf2-v4l2.h>
//#include <soc/imx8/sc/svc/irq/api.h>
//#include <soc/imx8/sc/ipc.h>
//#include <soc/imx8/sc/sci.h>
#include <linux/mx8_mu.h>
#include <media/v4l2-event.h>
#include "vpu_encoder_rpc.h"
#include "vpu_encoder_config.h"
extern unsigned int vpu_dbg_level_encoder;
#define v4l2_fh_to_ctx(__fh) \
container_of(__fh, struct vpu_ctx, fh)
#define v4l2_ctrl_to_ctx(__ctrl) \
container_of((__ctrl)->handler, struct vpu_ctx, ctrl_handler)
#define VPU_ENC_MAX_CORE_NUM 2
#define VPU_MAX_BUFFER 32
#define M0FW_FILENAME "vpu/vpu_fw_imx8_enc.bin"
#define MMAP_BUF_TYPE_SHIFT 28
#define MMAP_BUF_TYPE_MASK 0xF0000000
#define M0_BOOT_SIZE_DEFAULT 0x1000000
#define M0_BOOT_SIZE_MIN 0x100000
#define RPC_SIZE_DEFAULT 0x80000
#define RPC_SIZE_MIN 0x20000
#define PRINT_SIZE_DEFAULT 0x80000
#define PRINT_SIZE_MIN 0x20000
#define STREAM_SIZE 0x300000
#define MU_B0_REG_CONTROL (0x10000 + 0x24)
#define MIN_BUFFER_COUNT 3
#define BITRATE_COEF 1024
#define BITRATE_LOW_THRESHOLD (16)
#define BITRATE_HIGH_THRESHOLD (240 * 1024)
#define BITRATE_DEFAULT_TARGET (2 * 1024)
#define BITRATE_DEFAULT_PEAK (8 * 1024)
#define GOP_H_THRESHOLD 300
#define GOP_L_THRESHOLD 1
#define GOP_DEFAULT 30
#define BFRAMES_H_THRESHOLD 4
#define BFRAMES_L_THRESHOLD 0
#define BFRAMES_DEFAULT 2
#define QP_MAX 51
#define QP_MIN 0
#define QP_DEFAULT 25
#define VPU_DISABLE_BITS 0x7
#define VPU_ENCODER_MASK 0x1
#define ENCODER_NODE_NUMBER 13 //use /dev/video13 as encoder node
struct vpu_v4l2_control {
uint32_t id;
enum v4l2_ctrl_type type;
uint32_t minimum;
uint32_t maximum;
uint32_t step;
uint32_t default_value;
uint32_t menu_skip_mask;
bool is_volatile;
};
typedef enum{
INIT_DONE = 1,
RPC_BUF_OFFSET,
BOOT_ADDRESS,
COMMAND,
EVENT
} MSG_Type;
enum PLAT_TYPE {
IMX8QXP = 0,
IMX8QM = 1,
IMX8DM,
IMX8DX,
PLAT_TYPE_RESERVED
};
enum QUEUE_TYPE {
V4L2_SRC = 0,
V4L2_DST = 1,
};
enum vpu_video_standard {
VPU_VIDEO_UNDEFINED = 0,
VPU_VIDEO_AVC = 1,
VPU_VIDEO_VC1 = 2,
VPU_VIDEO_MPEG2 = 3,
VPU_VIDEO_AVS = 4,
VPU_VIDEO_ASP = 5,
VPU_VIDEO_JPEG = 6,
VPU_VIDEO_RV8 = 7,
VPU_VIDEO_RV9 = 8,
VPU_VIDEO_VP6 = 9,
VPU_VIDEO_SPK = 10,
VPU_VIDEO_VP8 = 11,
VPU_VIDEO_AVC_MVC = 12,
VPU_VIDEO_HEVC = 13,
VPU_VIDEO_VP9 = 14,
};
#define VPU_PIX_FMT_AVS v4l2_fourcc('A', 'V', 'S', '0')
#define VPU_PIX_FMT_ASP v4l2_fourcc('A', 'S', 'P', '0')
#define VPU_PIX_FMT_RV8 v4l2_fourcc('R', 'V', '8', '0')
#define VPU_PIX_FMT_RV9 v4l2_fourcc('R', 'V', '9', '0')
#define VPU_PIX_FMT_VP6 v4l2_fourcc('V', 'P', '6', '0')
#define VPU_PIX_FMT_SPK v4l2_fourcc('S', 'P', 'K', '0')
#define VPU_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
#define VPU_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0')
#define VPU_PIX_FMT_LOGO v4l2_fourcc('L', 'O', 'G', 'O')
#define VPU_PIX_FMT_TILED_8 v4l2_fourcc('Z', 'T', '0', '8')
#define VPU_PIX_FMT_TILED_10 v4l2_fourcc('Z', 'T', '1', '0')
enum vpu_pixel_format {
VPU_HAS_COLOCATED = 0x00000001,
VPU_HAS_SPLIT_FLD = 0x00000002,
VPU_PF_MASK = ~(VPU_HAS_COLOCATED | VPU_HAS_SPLIT_FLD),
VPU_IS_TILED = 0x000000100,
VPU_HAS_10BPP = 0x00000200,
VPU_IS_PLANAR = 0x00001000,
VPU_IS_SEMIPLANAR = 0x00002000,
VPU_IS_PACKED = 0x00004000,
// Merged definitions using above flags:
VPU_PF_UNDEFINED = 0,
VPU_PF_YUV420_SEMIPLANAR = 0x00010000 | VPU_IS_SEMIPLANAR,
VPU_PF_YUV420_PLANAR = 0x00020000 | VPU_IS_PLANAR,
VPU_PF_UYVY = 0x00040000 | VPU_IS_PACKED,
VPU_PF_TILED_8BPP = 0x00080000 | VPU_IS_TILED | VPU_IS_SEMIPLANAR,
VPU_PF_TILED_10BPP = 0x00100000 | VPU_IS_TILED | VPU_IS_SEMIPLANAR | VPU_HAS_10BPP,
};
struct vpu_ctx;
struct core_device;
struct vpu_dev;
struct vpu_v4l2_fmt {
char *name;
unsigned int fourcc;
unsigned int num_planes;
unsigned int venc_std;
unsigned int is_yuv;
};
struct vb2_data_req {
struct list_head list;
struct vb2_buffer *vb2_buf;
int id;
u_int32 buffer_flags;
};
enum ENC_RW_FLAG {
VPU_ENC_FLAG_WRITEABLE,
VPU_ENC_FLAG_READABLE
};
struct queue_data {
unsigned int width;
unsigned int height;
unsigned int bytesperline;
unsigned int sizeimage[3];
unsigned int fourcc;
unsigned int vdec_std;
struct v4l2_rect rect;
int buf_type; // v4l2_buf_type
bool vb2_q_inited;
struct vb2_queue vb2_q; // vb2 queue
struct list_head drv_q; // driver queue
struct semaphore drv_q_lock;
struct vb2_data_req vb2_reqs[VPU_MAX_BUFFER];
enum QUEUE_TYPE type;
struct vpu_v4l2_fmt *supported_fmts;
unsigned int fmt_count;
struct vpu_v4l2_fmt *current_fmt;
unsigned long rw_flag;
struct list_head frame_q;
atomic64_t frame_count;
struct list_head frame_idle;
struct vpu_ctx *ctx;
};
struct vpu_strip_info {
unsigned long count;
unsigned long max;
unsigned long total;
};
struct vpu_fps_sts {
unsigned int thd;
unsigned int times;
unsigned long frame_number;
struct timespec ts;
unsigned long fps;
};
struct vpu_statistic {
unsigned long cmd[GTB_ENC_CMD_RESERVED + 1];
unsigned long event[VID_API_ENC_EVENT_RESERVED + 1];
unsigned long current_cmd;
unsigned long current_event;
struct timespec ts_cmd;
struct timespec ts_event;
unsigned long yuv_count;
unsigned long encoded_count;
unsigned long h264_count;
struct {
struct vpu_strip_info fw;
struct vpu_strip_info begin;
struct vpu_strip_info eos;
} strip_sts;
bool fps_sts_enable;
struct vpu_fps_sts fps[VPU_FPS_STS_CNT];
};
struct vpu_attr {
struct device_attribute dev_attr;
char name[64];
u32 index;
struct core_device *core;
pid_t pid;
pid_t tgid;
struct vpu_statistic statistic;
MEDIAIP_ENC_PARAM param;
unsigned long ts_start[2];
unsigned long msg_count;
atomic64_t total_dma_size;
bool created;
};
struct core_device {
void *m0_p_fw_space_vir;
u_int32 m0_p_fw_space_phy;
u32 fw_buf_size;
u32 fw_actual_size;
void *m0_rpc_virt;
u_int32 m0_rpc_phy;
u32 rpc_buf_size;
u32 print_buf_size;
u32 rpc_actual_size;
struct mutex cmd_mutex;
bool fw_is_ready;
bool firmware_started;
struct completion start_cmp;
struct completion snap_done_cmp;
struct workqueue_struct *workqueue;
struct work_struct msg_work;
void __iomem *mu_base_virtaddr;
unsigned int vpu_mu_id;
int vpu_mu_init;
u32 supported_instance_count;
struct vpu_ctx *ctx[VID_API_NUM_STREAMS];
struct vpu_attr attr[VID_API_NUM_STREAMS];
struct shared_addr shared_mem;
u32 id;
u32 reg_base;
u32 reg_size;
u32 reg_csr_base;
u32 reg_csr_size;
int irq;
struct device *generic_dev;
struct vpu_dev *vdev;
bool snapshot;
bool suspend;
bool hang;
struct device_attribute core_attr;
char name[64];
unsigned long reset_times;
};
struct vpu_dev {
struct device *generic_dev;
struct v4l2_device v4l2_dev;
struct video_device *pvpu_encoder_dev;
struct platform_device *plat_dev;
struct clk *clk_m0;
u32 reg_vpu_base;
u32 reg_vpu_size;
u32 reg_rpc_system;
void __iomem *regs_base;
struct mutex dev_mutex;
struct core_device core_dev[VPU_ENC_MAX_CORE_NUM];
u_int32 plat_type;
u_int32 core_num;
bool hw_enable;
struct delayed_work watchdog;
u8 heartbeat;
struct {
u32 min_width;
u32 max_width;
u32 step_width;
u32 min_height;
u32 max_height;
u32 step_height;
} supported_size;
struct {
u32 min;
u32 max;
u32 step;
} supported_fps;
struct device *pd_vpu;
struct device *pd_enc;
struct device *pd_mu;
};
struct buffer_addr {
void *virt_addr;
dma_addr_t phy_addr;
u_int32 size;
};
enum {
VPU_ENC_STATUS_INITIALIZED,
VPU_ENC_STATUS_SNAPSHOT = 20,
VPU_ENC_STATUS_FORCE_RELEASE = 21,
VPU_ENC_STATUS_EOS_SEND = 22,
VPU_ENC_STATUS_START_SEND = 23,
VPU_ENC_STATUS_START_DONE = 24,
VPU_ENC_STATUS_STOP_REQ = 25,
VPU_ENC_STATUS_STOP_SEND = 26,
VPU_ENC_STATUS_STOP_DONE = 27,
VPU_ENC_STATUS_CLOSED = 28,
VPU_ENC_STATUS_CONFIGURED = 29,
VPU_ENC_STATUS_HANG = 30,
VPU_ENC_STATUS_KEY_FRAME = 31
};
struct vpu_ctx {
struct vpu_dev *dev;
struct v4l2_fh fh;
struct v4l2_ctrl_handler ctrl_handler;
bool ctrl_inited;
int str_index;
unsigned long status;
struct queue_data q_data[2];
struct mutex instance_mutex;
struct work_struct instance_work;
struct workqueue_struct *instance_wq;
bool ctx_released;
struct buffer_addr encoder_stream;
struct buffer_addr encFrame[MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES];
struct buffer_addr refFrame[MEDIAIP_MAX_NUM_WINDSOR_REF_FRAMES];
struct buffer_addr actFrame;
struct buffer_addr enc_buffer;
MEDIAIP_ENC_MEM_REQ_DATA mem_req;
struct core_device *core_dev;
struct completion stop_cmp;
bool power_status;
struct list_head msg_q;
struct list_head idle_q;
struct vpu_statistic sts;
unsigned int frozen_count;
};
#define LVL_DEBUG 4
#define LVL_INFO 3
#define LVL_IRQ 2
#define LVL_ALL 1
#define LVL_WARN 1
#define LVL_ERR 0
#ifndef TAG
#define TAG "[VPU Encoder]\t "
#endif
#define vpu_dbg(level, fmt, arg...) \
do { \
if (vpu_dbg_level_encoder >= (level)) \
pr_info(TAG""fmt, ## arg); \
} while (0)
#define vpu_err(fmt, arg...) vpu_dbg(LVL_ERR, fmt, ##arg)
u32 cpu_phy_to_mu(struct core_device *dev, u32 addr);
struct vpu_attr *get_vpu_ctx_attr(struct vpu_ctx *ctx);
struct vpu_ctx *get_vpu_attr_ctx(struct vpu_attr *attr);
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_encoder_config.h
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#ifndef _VPU_ENCODER_CONFIG_H
#define _VPU_ENCODER_CONFIG_H
#define VPU_ENC_WIDTH_MAX 1920
#define VPU_ENC_HEIGHT_MAX 1080
#define VPU_ENC_WIDTH_MIN 64
#define VPU_ENC_HEIGHT_MIN 48
#define VPU_ENC_WIDTH_STEP 16
#define VPU_ENC_HEIGHT_STEP 2
#define VPU_ENC_FRAMERATE_MAX 120
#define VPU_ENC_FRAMERATE_MIN 1
#define VPU_ENC_FRAMERATE_STEP 1
#define VPU_ENC_WIDTH_DEFAULT 1920
#define VPU_ENC_HEIGHT_DEFAULT 1080
#define VPU_ENC_FRAMERATE_DEFAULT 30
#define VPU_MEM_PATTERN 0x5a5a5a5a
#define VPU_TAIL_SERACH_SIZE 16
#define VPU_STRM_END_PATTERN {0x0, 0x0, 0x1, 0xb}
#define VPU_STRM_BEGIN_PATTERN {0x0, 0x0, 0x1}
#define MSG_DATA_DEFAULT_SIZE 256
#define MSG_COUNT_THD 16
#define FRAME_COUNT_THD 16
#define VPU_WATCHDOG_INTERVAL_MS 1000
#define VPU_ENC_HANG_THD 15
#define VPU_FPS_STS_CNT 3
#define VPU_FPS_STS_THDS {1, 3, 0}
#define VPU_FPS_COEF 100
#define VPU_DETAIL_INDEX_DFT 0xffff
#endif

View File

@ -0,0 +1,589 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*
* @file vpu_encoder_ctrl.c
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#include <media/v4l2-ctrls.h>
#include "vpu_encoder_b0.h"
#include "vpu_encoder_ctrl.h"
// H264 level is maped like level 5.1 to uLevel 51, except level 1b to uLevel 14
const u_int32 h264_level[] = {
[V4L2_MPEG_VIDEO_H264_LEVEL_1_0] = 10,
[V4L2_MPEG_VIDEO_H264_LEVEL_1B] = 14,
[V4L2_MPEG_VIDEO_H264_LEVEL_1_1] = 11,
[V4L2_MPEG_VIDEO_H264_LEVEL_1_2] = 12,
[V4L2_MPEG_VIDEO_H264_LEVEL_1_3] = 13,
[V4L2_MPEG_VIDEO_H264_LEVEL_2_0] = 20,
[V4L2_MPEG_VIDEO_H264_LEVEL_2_1] = 21,
[V4L2_MPEG_VIDEO_H264_LEVEL_2_2] = 22,
[V4L2_MPEG_VIDEO_H264_LEVEL_3_0] = 30,
[V4L2_MPEG_VIDEO_H264_LEVEL_3_1] = 31,
[V4L2_MPEG_VIDEO_H264_LEVEL_3_2] = 32,
[V4L2_MPEG_VIDEO_H264_LEVEL_4_0] = 40,
[V4L2_MPEG_VIDEO_H264_LEVEL_4_1] = 41,
[V4L2_MPEG_VIDEO_H264_LEVEL_4_2] = 42,
[V4L2_MPEG_VIDEO_H264_LEVEL_5_0] = 50,
[V4L2_MPEG_VIDEO_H264_LEVEL_5_1] = 51
};
static int set_h264_profile(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
switch (ctrl->val) {
case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
param->eProfile = MEDIAIP_ENC_PROF_H264_BP;
break;
case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
param->eProfile = MEDIAIP_ENC_PROF_H264_MP;
break;
case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
param->eProfile = MEDIAIP_ENC_PROF_H264_HP;
break;
default:
vpu_dbg(LVL_ERR, "not support H264 profile %d, set to main\n",
ctrl->val);
param->eProfile = MEDIAIP_ENC_PROF_H264_MP;
break;
}
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_h264_level(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uLevel = h264_level[ctrl->val];
mutex_unlock(&ctx->instance_mutex);
vpu_dbg(LVL_DEBUG, "set h264 level to %d\n", ctrl->val);
return 0;
}
static int set_bitrate_mode(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
switch (ctrl->val) {
case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
param->eBitRateMode =
MEDIAIP_ENC_BITRATECONTROLMODE_CONSTANT_QP;
break;
case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
param->eBitRateMode = MEDIAIP_ENC_BITRATECONTROLMODE_CBR;
break;
default:
vpu_dbg(LVL_ERR, "not support bitrate mode %d, set to cbr\n",
ctrl->val);
param->eBitRateMode = MEDIAIP_ENC_BITRATECONTROLMODE_CBR;
break;
}
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_bitrate(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uTargetBitrate = ctrl->val / BITRATE_COEF;
if (param->uMaxBitRate < param->uTargetBitrate)
param->uMaxBitRate = param->uTargetBitrate;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_bitrate_peak(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uMaxBitRate = ctrl->val / BITRATE_COEF;
if (param->uTargetBitrate > param->uMaxBitRate)
param->uTargetBitrate = param->uMaxBitRate;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_gop_size(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uIFrameInterval = ctrl->val;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_i_period(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uIFrameInterval = ctrl->val;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int get_gop_size(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
ctrl->val = param->uIFrameInterval;
return 0;
}
static int set_b_frames(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uGopBLength = ctrl->val;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_qp(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
param->uInitSliceQP = ctrl->val;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int get_min_buffers_for_output(struct v4l2_ctrl *ctrl)
{
vpu_dbg(LVL_DEBUG, "get min buffers for output\n");
ctrl->val = MIN_BUFFER_COUNT;
return 0;
}
static int set_display_re_ordering(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
pMEDIAIP_ENC_PARAM param = &attr->param;
mutex_lock(&ctx->instance_mutex);
if (ctrl->val)
param->uLowLatencyMode = 1;
else
param->uLowLatencyMode = 0;
mutex_unlock(&ctx->instance_mutex);
return 0;
}
static int set_force_key_frame(struct v4l2_ctrl *ctrl)
{
struct vpu_ctx *ctx = v4l2_ctrl_to_ctx(ctrl);
set_bit(VPU_ENC_STATUS_KEY_FRAME, &ctx->status);
return 0;
}
static int add_ctrl_h264_profile(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_h264_profile_ops = {
.s_ctrl = set_h264_profile,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler,
&ctrl_h264_profile_ops,
V4L2_CID_MPEG_VIDEO_H264_PROFILE,
V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
0xa,
V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl h264 profile fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_h264_level(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_h264_level_ops = {
.s_ctrl = set_h264_level,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler,
&ctrl_h264_level_ops,
V4L2_CID_MPEG_VIDEO_H264_LEVEL,
V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
0x0,
V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl h264 level fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_bitrate_mode(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_bitrate_mode_ops = {
.s_ctrl = set_bitrate_mode,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler,
&ctrl_bitrate_mode_ops,
V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
0x0,
V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl bitrate mode fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_bitrate(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_bitrate_ops = {
.s_ctrl = set_bitrate,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_bitrate_ops,
V4L2_CID_MPEG_VIDEO_BITRATE,
BITRATE_LOW_THRESHOLD * BITRATE_COEF,
BITRATE_HIGH_THRESHOLD * BITRATE_COEF,
BITRATE_COEF,
BITRATE_DEFAULT_TARGET * BITRATE_COEF);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl bitrate fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_bitrate_peak(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_bitrate_ops = {
.s_ctrl = set_bitrate_peak,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_bitrate_ops,
V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
BITRATE_LOW_THRESHOLD * BITRATE_COEF,
BITRATE_HIGH_THRESHOLD * BITRATE_COEF,
BITRATE_COEF,
BITRATE_DEFAULT_PEAK * BITRATE_COEF);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl bitrate peak fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_gop_size(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_gop_ops = {
.s_ctrl = set_gop_size,
.g_volatile_ctrl = get_gop_size,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_gop_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE,
GOP_L_THRESHOLD,
GOP_H_THRESHOLD,
1,
GOP_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl gop size fail\n");
return -EINVAL;
}
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
return 0;
}
static int add_ctrl_i_period(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_i_period_ops = {
.s_ctrl = set_i_period,
.g_volatile_ctrl = get_gop_size,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_i_period_ops,
V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
GOP_L_THRESHOLD,
GOP_H_THRESHOLD,
1,
GOP_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl i period fail\n");
return -EINVAL;
}
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
return 0;
}
static int add_ctrl_b_frames(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_b_frames = {
.s_ctrl = set_b_frames,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_b_frames,
V4L2_CID_MPEG_VIDEO_B_FRAMES,
BFRAMES_L_THRESHOLD,
BFRAMES_H_THRESHOLD,
1,
BFRAMES_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl b frames fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_i_frame_qp(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_iframe_qp_ops = {
.s_ctrl = set_qp,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_iframe_qp_ops,
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
QP_MIN,
QP_MAX,
1,
QP_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl h264 I frame qp fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_p_frame_qp(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_pframe_qp_ops = {
.s_ctrl = set_qp,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_pframe_qp_ops,
V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
QP_MIN,
QP_MAX,
1,
QP_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl h264 P frame qp fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_b_frame_qp(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_bframe_qp_ops = {
.s_ctrl = set_qp,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_bframe_qp_ops,
V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
QP_MIN,
QP_MAX,
1,
QP_DEFAULT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl h264 B frame qp fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_min_buffers_for_output(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops ctrl_min_buffers_ops = {
.g_volatile_ctrl = get_min_buffers_for_output,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&ctrl_min_buffers_ops,
V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
1,
32,
1,
MIN_BUFFER_COUNT);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl min buffers for output fail\n");
return -EINVAL;
}
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
return 0;
}
static int add_ctrl_display_re_ordering(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops re_ordering_ops = {
.s_ctrl = set_display_re_ordering,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&re_ordering_ops,
V4L2_CID_MPEG_VIDEO_H264_ASO,
0, 1, 1, 1);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl display re ordering fail\n");
return -EINVAL;
}
return 0;
}
static int add_ctrl_force_key_frame(struct vpu_ctx *ctx)
{
static const struct v4l2_ctrl_ops force_key_frame_ops = {
.s_ctrl = set_force_key_frame,
};
struct v4l2_ctrl *ctrl;
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_handler,
&force_key_frame_ops,
V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
0, 0, 0, 0);
if (!ctrl) {
vpu_dbg(LVL_ERR, "add ctrl force key frame fail\n");
return -EINVAL;
}
return 0;
}
static int vpu_enc_register_ctrls(struct vpu_ctx *ctx)
{
add_ctrl_h264_profile(ctx);
add_ctrl_h264_level(ctx);
add_ctrl_bitrate_mode(ctx);
add_ctrl_bitrate(ctx);
add_ctrl_bitrate_peak(ctx);
add_ctrl_gop_size(ctx);
add_ctrl_i_period(ctx);
add_ctrl_b_frames(ctx);
add_ctrl_i_frame_qp(ctx);
add_ctrl_p_frame_qp(ctx);
add_ctrl_b_frame_qp(ctx);
add_ctrl_min_buffers_for_output(ctx);
add_ctrl_display_re_ordering(ctx);
add_ctrl_force_key_frame(ctx);
return 0;
}
int vpu_enc_setup_ctrls(struct vpu_ctx *ctx)
{
v4l2_ctrl_handler_init(&ctx->ctrl_handler, 11);
vpu_enc_register_ctrls(ctx);
if (ctx->ctrl_handler.error) {
vpu_dbg(LVL_ERR, "control initialization error (%d)\n",
ctx->ctrl_handler.error);
return -EINVAL;
}
ctx->ctrl_inited = true;
return v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
}
int vpu_enc_free_ctrls(struct vpu_ctx *ctx)
{
if (ctx->ctrl_inited) {
v4l2_ctrl_handler_free(&ctx->ctrl_handler);
ctx->ctrl_inited = false;
}
return 0;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_encoder_ctrl.h
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#ifndef _VPU_ENCODER_CTRL_H
#define _VPU_ENCODER_CTRL_H
#include "mediasys_types.h"
int vpu_enc_setup_ctrls(struct vpu_ctx *ctx);
int vpu_enc_free_ctrls(struct vpu_ctx *ctx);
#endif

View File

@ -0,0 +1,412 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_encoder_mem.c
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include "vpu_encoder_config.h"
#include "vpu_encoder_b0.h"
#include "vpu_encoder_mem.h"
void vpu_enc_add_dma_size(struct vpu_attr *attr, unsigned long size)
{
if (!attr)
return;
atomic64_add(size, &attr->total_dma_size);
}
void vpu_enc_sub_dma_size(struct vpu_attr *attr, unsigned long size)
{
if (!attr)
return;
atomic64_sub(size, &attr->total_dma_size);
}
int vpu_enc_alloc_dma_buffer(struct vpu_ctx *ctx, struct buffer_addr *buffer)
{
if (!ctx || !ctx->dev || !buffer || !buffer->size)
return -EINVAL;
buffer->virt_addr = dma_alloc_coherent(ctx->dev->generic_dev,
buffer->size,
(dma_addr_t *)&buffer->phy_addr,
GFP_KERNEL | GFP_DMA32);
if (!buffer->virt_addr) {
vpu_dbg(LVL_ERR, "encoder alloc coherent dma(%d) fail\n",
buffer->size);
return -ENOMEM;
}
memset_io(buffer->virt_addr, 0, buffer->size);
vpu_enc_add_dma_size(get_vpu_ctx_attr(ctx), buffer->size);
return 0;
}
void vpu_enc_init_dma_buffer(struct buffer_addr *buffer)
{
if (!buffer)
return;
buffer->virt_addr = NULL;
buffer->phy_addr = 0;
buffer->size = 0;
}
int vpu_enc_free_dma_buffer(struct vpu_ctx *ctx, struct buffer_addr *buffer)
{
if (!ctx || !ctx->dev || !buffer)
return -EINVAL;
if (!buffer->virt_addr)
return 0;
vpu_enc_sub_dma_size(get_vpu_ctx_attr(ctx), buffer->size);
dma_free_coherent(ctx->dev->generic_dev, buffer->size,
buffer->virt_addr, buffer->phy_addr);
vpu_enc_init_dma_buffer(buffer);
return 0;
}
static u32 get_enc_alloc_size(u32 size)
{
u32 esize = ALIGN(size, PAGE_SIZE);
if (esize < size + sizeof(u32))
esize += PAGE_SIZE;
return esize;
}
static int alloc_mem_res(struct vpu_ctx *ctx, struct buffer_addr *buffer,
MEDIAIP_ENC_MEM_RESOURCE *resource, u32 size)
{
int ret;
if (!ctx || !buffer || !resource)
return -EINVAL;
if (!size) {
vpu_err("invalid memory resource size : %d\n", size);
return -EINVAL;
}
buffer->size = get_enc_alloc_size(size);
ret = vpu_enc_alloc_dma_buffer(ctx, buffer);
if (ret)
return ret;
resource->uMemPhysAddr = buffer->phy_addr;
resource->uMemVirtAddr = cpu_phy_to_mu(ctx->core_dev, buffer->phy_addr);
resource->uMemSize = size;
return 0;
}
static int free_mem_res(struct vpu_ctx *ctx, struct buffer_addr *buffer,
MEDIAIP_ENC_MEM_RESOURCE *resource)
{
if (!ctx || !buffer || !resource)
return -EINVAL;
vpu_enc_free_dma_buffer(ctx, buffer);
resource->uMemPhysAddr = 0;
resource->uMemVirtAddr = 0;
resource->uMemSize = 0;
return 0;
}
static int free_enc_frames(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
int i;
for (i = 0; i < ctx->mem_req.uEncFrmNum; i++)
free_mem_res(ctx, &ctx->encFrame[i],
&pool->tEncFrameBuffers[i]);
return 0;
}
static int alloc_enc_frames(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
int i;
int ret;
for (i = 0; i < ctx->mem_req.uEncFrmNum; i++) {
ret = alloc_mem_res(ctx,
&ctx->encFrame[i],
&pool->tEncFrameBuffers[i],
ctx->mem_req.uEncFrmSize);
if (ret) {
vpu_err("alloc enc frame[%d] fail\n", i);
goto error;
}
vpu_dbg(LVL_INFO, "encFrame[%d]: 0x%llx,%d(%d)\n", i,
ctx->encFrame[i].phy_addr,
ctx->mem_req.uEncFrmSize,
ctx->encFrame[i].size);
}
return 0;
error:
free_enc_frames(ctx, pool);
return ret;
}
static int free_ref_frames(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
int i;
for (i = 0; i < ctx->mem_req.uRefFrmNum; i++)
free_mem_res(ctx, &ctx->refFrame[i],
&pool->tRefFrameBuffers[i]);
return 0;
}
static int alloc_ref_frames(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
int i;
int ret;
for (i = 0; i < ctx->mem_req.uRefFrmNum; i++) {
ret = alloc_mem_res(ctx,
&ctx->refFrame[i],
&pool->tRefFrameBuffers[i],
ctx->mem_req.uRefFrmSize);
if (ret) {
vpu_err("alloc ref frame[%d] fail\n", i);
goto error;
}
vpu_dbg(LVL_INFO, "refFrame[%d]: 0x%llx,%d(%d)\n", i,
ctx->refFrame[i].phy_addr,
ctx->mem_req.uRefFrmSize,
ctx->refFrame[i].size);
}
return 0;
error:
free_ref_frames(ctx, pool);
return ret;
}
static int free_act_frame(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
if (!ctx || !pool)
return -EINVAL;
free_mem_res(ctx, &ctx->actFrame, &pool->tActFrameBufferArea);
return 0;
}
static int alloc_act_frame(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
int ret = 0;
ret = alloc_mem_res(ctx,
&ctx->actFrame,
&pool->tActFrameBufferArea,
ctx->mem_req.uActBufSize);
if (ret) {
vpu_err("alloc act frame fail\n");
return ret;
}
vpu_dbg(LVL_INFO, "actFrame: 0x%llx, %d(%d)\n",
ctx->actFrame.phy_addr,
ctx->mem_req.uActBufSize,
ctx->actFrame.size);
return 0;
}
static void set_mem_pattern(u32 *ptr)
{
if (!ptr)
return;
*ptr = VPU_MEM_PATTERN;
}
static int check_mem_pattern(u32 *ptr)
{
if (!ptr)
return -EINVAL;
if (*ptr != VPU_MEM_PATTERN)
return -EINVAL;
return 0;
}
static void vpu_enc_set_mem_pattern(struct vpu_ctx *ctx)
{
int i;
if (!ctx)
return;
for (i = 0; i < MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES; i++) {
if (!ctx->encFrame[i].virt_addr)
continue;
set_mem_pattern(ctx->encFrame[i].virt_addr +
ctx->mem_req.uEncFrmSize);
}
for (i = 0; i < MEDIAIP_MAX_NUM_WINDSOR_REF_FRAMES; i++) {
if (!ctx->refFrame[i].virt_addr)
continue;
set_mem_pattern(ctx->refFrame[i].virt_addr +
ctx->mem_req.uRefFrmSize);
}
if (ctx->actFrame.virt_addr)
set_mem_pattern(ctx->actFrame.virt_addr +
ctx->mem_req.uActBufSize);
}
int vpu_enc_check_mem_overstep(struct vpu_ctx *ctx)
{
int i;
int ret;
int flag = 0;
if (!ctx)
return -EINVAL;
for (i = 0; i < MEDIAIP_MAX_NUM_WINDSOR_SRC_FRAMES; i++) {
if (!ctx->encFrame[i].virt_addr)
continue;
ret = check_mem_pattern(ctx->encFrame[i].virt_addr +
ctx->mem_req.uEncFrmSize);
if (ret) {
vpu_err("***error:[%d][%d]encFrame[%d] out of bounds\n",
ctx->core_dev->id, ctx->str_index, i);
flag = 1;
}
}
for (i = 0; i < MEDIAIP_MAX_NUM_WINDSOR_REF_FRAMES; i++) {
if (!ctx->refFrame[i].virt_addr)
continue;
ret = check_mem_pattern(ctx->refFrame[i].virt_addr +
ctx->mem_req.uRefFrmSize);
if (ret) {
vpu_err("***error:[%d][%d]refFrame[%d] out of bounds\n",
ctx->core_dev->id, ctx->str_index, i);
flag = 1;
}
}
if (ctx->actFrame.virt_addr) {
ret = check_mem_pattern(ctx->actFrame.virt_addr +
ctx->mem_req.uActBufSize);
if (ret) {
vpu_err("***error:[%d][%d]actFrame out of bounds\n",
ctx->core_dev->id, ctx->str_index);
flag = 1;
}
}
if (flag) {
vpu_err("Error:Memory out of bounds in [%d][%d]\n",
ctx->core_dev->id, ctx->str_index);
vpu_enc_set_mem_pattern(ctx);
}
return 0;
}
int vpu_enc_alloc_mem(struct vpu_ctx *ctx,
MEDIAIP_ENC_MEM_REQ_DATA *req_data,
pMEDIAIP_ENC_MEM_POOL pool)
{
int ret;
if (!ctx || !req_data || !pool)
return -EINVAL;
if (ctx->mem_req.uEncFrmSize < req_data->uEncFrmSize ||
ctx->mem_req.uEncFrmNum < req_data->uEncFrmNum) {
free_enc_frames(ctx, pool);
ctx->mem_req.uEncFrmSize = req_data->uEncFrmSize;
ctx->mem_req.uEncFrmNum = req_data->uEncFrmNum;
ret = alloc_enc_frames(ctx, pool);
if (ret)
return ret;
}
if (ctx->mem_req.uRefFrmSize < req_data->uRefFrmSize ||
ctx->mem_req.uRefFrmNum < req_data->uRefFrmNum) {
free_ref_frames(ctx, pool);
ctx->mem_req.uRefFrmSize = req_data->uRefFrmSize;
ctx->mem_req.uRefFrmNum = req_data->uRefFrmNum;
ret = alloc_ref_frames(ctx, pool);
if (ret)
goto error_alloc_refs;
}
if (ctx->mem_req.uActBufSize < req_data->uActBufSize) {
free_act_frame(ctx, pool);
ctx->mem_req.uActBufSize = req_data->uActBufSize;
ret = alloc_act_frame(ctx, pool);
if (ret)
goto error_alloc_act;
}
vpu_enc_set_mem_pattern(ctx);
return 0;
error_alloc_act:
free_ref_frames(ctx, pool);
error_alloc_refs:
free_enc_frames(ctx, pool);
return ret;
}
int vpu_enc_free_mem(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool)
{
if (!ctx || !pool)
return -EINVAL;
free_act_frame(ctx, pool);
free_ref_frames(ctx, pool);
free_enc_frames(ctx, pool);
return 0;
}
int vpu_enc_alloc_stream(struct vpu_ctx *ctx)
{
int ret;
if (ctx->encoder_stream.virt_addr)
return 0;
ctx->encoder_stream.size = STREAM_SIZE;
ret = vpu_enc_alloc_dma_buffer(ctx, &ctx->encoder_stream);
if (ret) {
vpu_dbg(LVL_ERR, "alloc encoder stream buffer fail\n");
return -ENOMEM;
}
vpu_dbg(LVL_INFO, "encoder_stream: 0x%llx, %d\n",
ctx->encoder_stream.phy_addr, ctx->encoder_stream.size);
return 0;
}
void vpu_enc_free_stream(struct vpu_ctx *ctx)
{
vpu_enc_free_dma_buffer(ctx, &ctx->encoder_stream);
}

View File

@ -0,0 +1,29 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_encoder_mem.h
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#ifndef _VPU_ENCODER_MEM_H
#define _VPU_ENCODER_MEM_H
#include "vpu_encoder_b0.h"
void vpu_enc_add_dma_size(struct vpu_attr *attr, unsigned long size);
void vpu_enc_sub_dma_size(struct vpu_attr *attr, unsigned long size);
int vpu_enc_alloc_dma_buffer(struct vpu_ctx *ctx, struct buffer_addr *buffer);
int vpu_enc_free_dma_buffer(struct vpu_ctx *ctx, struct buffer_addr *buffer);
void vpu_enc_init_dma_buffer(struct buffer_addr *buffer);
int vpu_enc_check_mem_overstep(struct vpu_ctx *ctx);
int vpu_enc_alloc_mem(struct vpu_ctx *ctx,
MEDIAIP_ENC_MEM_REQ_DATA *req_data,
pMEDIAIP_ENC_MEM_POOL pool);
int vpu_enc_free_mem(struct vpu_ctx *ctx, pMEDIAIP_ENC_MEM_POOL pool);
int vpu_enc_alloc_stream(struct vpu_ctx *ctx);
void vpu_enc_free_stream(struct vpu_ctx *ctx);
#endif

View File

@ -0,0 +1,448 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include "vpu_encoder_rpc.h"
void rpc_init_shared_memory_encoder(struct shared_addr *This,
unsigned long long base_phy_addr,
void *base_virt_addr,
u_int32 total_size,
u32 *actual_size)
{
pENC_RPC_HOST_IFACE pSharedInterface;
unsigned int phy_addr;
unsigned int i;
unsigned int temp_addr;
BUFFER_DESCRIPTOR_TYPE *pSharedCmdBufDescPtr;
BUFFER_DESCRIPTOR_TYPE *pSharedMsgBufDescPtr;
pMEDIA_ENC_API_CONTROL_INTERFACE pEncCtrlInterface;
This->shared_mem_phy = base_phy_addr;
This->shared_mem_vir = base_virt_addr;
This->base_offset = (unsigned long long)(base_virt_addr - base_phy_addr);
pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir;
This->pSharedInterface = pSharedInterface;
pSharedInterface->FwExecBaseAddr = base_phy_addr;
pSharedInterface->FwExecAreaSize = total_size;
pSharedCmdBufDescPtr = (BUFFER_DESCRIPTOR_TYPE *)&pSharedInterface->StreamCmdBufferDesc;
pSharedMsgBufDescPtr = (BUFFER_DESCRIPTOR_TYPE *)&pSharedInterface->StreamMsgBufferDesc;
phy_addr = base_phy_addr + sizeof(ENC_RPC_HOST_IFACE);
This->cmd_mem_phy = phy_addr;
This->cmd_mem_vir = This->shared_mem_vir + sizeof(ENC_RPC_HOST_IFACE);
pSharedCmdBufDescPtr->wptr = phy_addr;
pSharedCmdBufDescPtr->rptr = pSharedCmdBufDescPtr->wptr;
pSharedCmdBufDescPtr->start = pSharedCmdBufDescPtr->wptr;
pSharedCmdBufDescPtr->end = pSharedCmdBufDescPtr->start + CMD_SIZE;
phy_addr += CMD_SIZE;
This->msg_mem_phy = phy_addr;
This->msg_mem_vir = This->cmd_mem_vir + CMD_SIZE;
pSharedMsgBufDescPtr->wptr = phy_addr;
pSharedMsgBufDescPtr->rptr = pSharedMsgBufDescPtr->wptr;
pSharedMsgBufDescPtr->start = pSharedMsgBufDescPtr->wptr;
pSharedMsgBufDescPtr->end = pSharedMsgBufDescPtr->start + MSG_SIZE;
phy_addr += MSG_SIZE;
for (i = 0; i < VID_API_NUM_STREAMS; i++) {
pSharedInterface->pEncCtrlInterface[i] = phy_addr;
phy_addr += sizeof(MEDIA_ENC_API_CONTROL_INTERFACE);
}
for (i = 0; i < VID_API_NUM_STREAMS; i++) {
temp_addr = pSharedInterface->pEncCtrlInterface[i];
pEncCtrlInterface = (pMEDIA_ENC_API_CONTROL_INTERFACE)(temp_addr + This->base_offset);
pEncCtrlInterface->pEncYUVBufferDesc = phy_addr;
phy_addr += sizeof(MEDIAIP_ENC_YUV_BUFFER_DESC);
pEncCtrlInterface->pEncStreamBufferDesc = phy_addr;
phy_addr += sizeof(BUFFER_DESCRIPTOR_TYPE);
pEncCtrlInterface->pEncExpertModeParam = phy_addr;
phy_addr += sizeof(MEDIAIP_ENC_EXPERT_MODE_PARAM);
pEncCtrlInterface->pEncParam = phy_addr;
phy_addr += sizeof(MEDIAIP_ENC_PARAM);
pEncCtrlInterface->pEncMemPool = phy_addr;
phy_addr += sizeof(MEDIAIP_ENC_MEM_POOL);
pEncCtrlInterface->pEncEncodingStatus = phy_addr;
phy_addr += sizeof(ENC_ENCODING_STATUS);
pEncCtrlInterface->pEncDSAStatus = phy_addr;
phy_addr += sizeof(ENC_DSA_STATUS_t);
}
if (actual_size)
*actual_size = phy_addr - base_phy_addr;
}
void rpc_set_system_cfg_value_encoder(void *Interface, u_int32 regs_base, u_int32 core_id)
{
pENC_RPC_HOST_IFACE pSharedInterface;
MEDIAIP_FW_SYSTEM_CONFIG *pSystemCfg;
pSharedInterface = (pENC_RPC_HOST_IFACE)Interface;
pSystemCfg = &pSharedInterface->sSystemCfg;
pSystemCfg->uNumWindsors = 1;
pSystemCfg->uWindsorIrqPin[0x0][0x0] = 0x4; // PAL_IRQ_WINDSOR_LOW
pSystemCfg->uWindsorIrqPin[0x0][0x1] = 0x5; // PAL_IRQ_WINDSOR_HI
pSystemCfg->uMaloneBaseAddress[0] = (unsigned int)(regs_base + 0x180000);
if (core_id == 0)
pSystemCfg->uWindsorBaseAddress[0] = (unsigned int)(regs_base + 0x800000);
else
pSystemCfg->uWindsorBaseAddress[0] = (unsigned int)(regs_base + 0xa00000);
pSystemCfg->uMaloneBaseAddress[0x1] = 0x0;
pSystemCfg->uHifOffset[0x0] = 0x1C000;
pSystemCfg->uHifOffset[0x1] = 0x0;
pSystemCfg->uDPVBaseAddr = 0x0;
pSystemCfg->uDPVIrqPin = 0x0;
pSystemCfg->uPixIfBaseAddr = (unsigned int)(regs_base + 0x180000 + 0x20000);
pSystemCfg->uFSLCacheBaseAddr[0] = (unsigned int)(regs_base + 0x60000);
pSystemCfg->uFSLCacheBaseAddr[1] = (unsigned int)(regs_base + 0x68000);
}
u_int32 rpc_MediaIPFW_Video_buffer_space_check_encoder(BUFFER_DESCRIPTOR_TYPE *pBufDesc,
BOOL bFull,
u_int32 uSize,
u_int32 *puUpdateAddress)
{
u_int32 uPtr1;
u_int32 uPtr2;
u_int32 start;
u_int32 end;
u_int32 uTemp;
/* bFull is FALSE when send message, write data */
/* bFull is TRUE when process commands, read data */
uPtr1 = (bFull) ? pBufDesc->rptr : pBufDesc->wptr;
uPtr2 = (bFull) ? pBufDesc->wptr : pBufDesc->rptr;
if (uPtr1 == uPtr2) {
if (bFull)
/* No data at all to read */
return 0;
else {
/* wrt pointer equal to read pointer thus the */
/* buffer is completely empty for further writes */
start = pBufDesc->start;
end = pBufDesc->end;
/* The address to be returned in this case is for */
/* the updated write pointer. */
uTemp = uPtr1 + uSize;
if (uTemp >= end)
uTemp += (start - end);
*puUpdateAddress = uTemp;
return (end - start);
}
} else if (uPtr1 < uPtr2) {
/* return updated rd pointer address */
/* In this case if size was too big - we expect the */
/* external ftn to compare the size against the */
/* space returned.
*/
*puUpdateAddress = uPtr1 + uSize;
return (uPtr2 - uPtr1);
}
/* We know the system has looped!! */
start = pBufDesc->start;
end = pBufDesc->end;
uTemp = uPtr1 + uSize;
if (uTemp >= end)
uTemp += (start - end);
*puUpdateAddress = uTemp;
return ((end - uPtr1) + (uPtr2 - start));
}
static void rpc_update_cmd_buffer_ptr_encoder(BUFFER_DESCRIPTOR_TYPE *pCmdDesc)
{
u_int32 uWritePtr;
/*avoid sw reset fail*/
mb();
uWritePtr = pCmdDesc->wptr + 4;
if (uWritePtr >= pCmdDesc->end)
uWritePtr = pCmdDesc->start;
pCmdDesc->wptr = uWritePtr;
}
void rpc_send_cmd_buf_encoder(struct shared_addr *This,
u_int32 idx,
u_int32 cmdid,
u_int32 cmdnum,
u_int32 *local_cmddata)
{
pENC_RPC_HOST_IFACE pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir;
BUFFER_DESCRIPTOR_TYPE *pCmdDesc = &pSharedInterface->StreamCmdBufferDesc;
u_int32 *cmddata;
u_int32 i;
u_int32 *cmdword = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->wptr - pCmdDesc->start);
*cmdword = 0;
*cmdword |= ((idx & 0x000000ff) << 24);
*cmdword |= ((cmdnum & 0x000000ff) << 16);
*cmdword |= ((cmdid & 0x00003fff) << 0);
rpc_update_cmd_buffer_ptr_encoder(pCmdDesc);
for (i = 0; i < cmdnum; i++) {
cmddata = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->wptr - pCmdDesc->start);
*cmddata = local_cmddata[i];
rpc_update_cmd_buffer_ptr_encoder(pCmdDesc);
}
}
u_int32 rpc_MediaIPFW_Video_message_check_encoder(struct shared_addr *This)
{
u_int32 uSpace;
u_int32 uIgnore;
pENC_RPC_HOST_IFACE pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir;
BUFFER_DESCRIPTOR_TYPE *pMsgDesc = &pSharedInterface->StreamMsgBufferDesc;
u_int32 msgword;
u_int32 msgnum;
uSpace = rpc_MediaIPFW_Video_buffer_space_check_encoder(pMsgDesc, TRUE, 0, &uIgnore);
uSpace = (uSpace >> 2);
if (uSpace) {
/* get current msgword word */
msgword = *((u_int32 *)(This->msg_mem_vir+pMsgDesc->rptr - pMsgDesc->start));
/* Find the number of additional words */
msgnum = ((msgword & 0x00ff0000) >> 16);
/*
* * Check the number of message words against
* * 1) a limit - some sort of maximum or at least
* * the size of the SW buffer the message is read into
* * 2) The space reported (where space is write ptr - read ptr in 32bit words)
* * It must be less than space (as opposed to <=) because
* * the message itself is not included in msgword
*/
if (msgnum < VID_API_MESSAGE_LIMIT) {
if (msgnum < uSpace)
return API_MSG_AVAILABLE;
else
return API_MSG_INCOMPLETE;
} else
return API_MSG_BUFFER_ERROR;
}
return API_MSG_UNAVAILABLE;
}
static void rpc_update_msg_buffer_ptr_encoder(BUFFER_DESCRIPTOR_TYPE *pMsgDesc)
{
u_int32 uReadPtr;
uReadPtr = pMsgDesc->rptr + 4;
if (uReadPtr >= pMsgDesc->end)
uReadPtr = pMsgDesc->start;
pMsgDesc->rptr = uReadPtr;
}
u32 rpc_read_msg_u32(struct shared_addr *shared_mem)
{
u32 msgword;
u32 *ptr = NULL;
pENC_RPC_HOST_IFACE iface = NULL;
BUFFER_DESCRIPTOR_TYPE *msg_buf = NULL;
if (!shared_mem)
return 0;
iface = shared_mem->pSharedInterface;
msg_buf = &iface->StreamMsgBufferDesc;
ptr = shared_mem->msg_mem_vir + msg_buf->rptr - msg_buf->start;
rpc_update_msg_buffer_ptr_encoder(msg_buf);
msgword = *ptr;
return msgword;
}
int rpc_read_msg_array(struct shared_addr *shared_mem, u32 *buf, u32 number)
{
int i;
u32 val;
if (!shared_mem)
return -EINVAL;
for (i = 0; i < number; i++) {
val = rpc_read_msg_u32(shared_mem);
if (buf)
buf[i] = val;
}
return 0;
}
int rpc_get_msg_header(struct shared_addr *shared_mem, struct msg_header *msg)
{
u32 msgword;
if (!shared_mem || !msg)
return -EINVAL;
msgword = rpc_read_msg_u32(shared_mem);
msg->idx = ((msgword & 0xff000000) >> 24);
msg->msgnum = ((msgword & 0x00ff0000) >> 16);
msg->msgid = ((msgword & 0x00003fff) >> 0);
return 0;
}
static void *phy_to_virt(u_int32 src, unsigned long long offset)
{
void *result;
result = (void *)(src + offset);
return result;
}
#define GET_CTRL_INTERFACE_MEMBER(shared_mem, index, name, member) \
do {\
pENC_RPC_HOST_IFACE iface = shared_mem->pSharedInterface; \
pMEDIA_ENC_API_CONTROL_INTERFACE ctrl_interface =\
phy_to_virt(iface->pEncCtrlInterface[index],\
shared_mem->base_offset);\
name = phy_to_virt(ctrl_interface->member,\
shared_mem->base_offset);\
} while (0)
pMEDIAIP_ENC_YUV_BUFFER_DESC rpc_get_yuv_buffer_desc(
struct shared_addr *shared_mem, int index)
{
pMEDIAIP_ENC_YUV_BUFFER_DESC desc = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index, desc, pEncYUVBufferDesc);
return desc;
}
pBUFFER_DESCRIPTOR_TYPE rpc_get_stream_buffer_desc(
struct shared_addr *shared_mem, int index)
{
pBUFFER_DESCRIPTOR_TYPE desc = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index,
desc, pEncStreamBufferDesc);
return desc;
}
pMEDIAIP_ENC_EXPERT_MODE_PARAM rpc_get_expert_mode_param(
struct shared_addr *shared_mem, int index)
{
pMEDIAIP_ENC_EXPERT_MODE_PARAM param = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index,
param, pEncExpertModeParam);
return param;
}
pMEDIAIP_ENC_PARAM rpc_get_enc_param(
struct shared_addr *shared_mem, int index)
{
pMEDIAIP_ENC_PARAM param = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index, param, pEncParam);
return param;
}
pMEDIAIP_ENC_MEM_POOL rpc_get_mem_pool(
struct shared_addr *shared_mem, int index)
{
pMEDIAIP_ENC_MEM_POOL pool = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index, pool, pEncMemPool);
return pool;
}
pENC_ENCODING_STATUS rpc_get_encoding_status(
struct shared_addr *shared_mem, int index)
{
pENC_ENCODING_STATUS encoding_status = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index,
encoding_status, pEncEncodingStatus);
return encoding_status;
}
pENC_DSA_STATUS_t rpc_get_dsa_status(struct shared_addr *shared_mem, int index)
{
pENC_DSA_STATUS_t dsa_status = NULL;
GET_CTRL_INTERFACE_MEMBER(shared_mem, index, dsa_status, pEncDSAStatus);
return dsa_status;
}
void rpc_set_print_buffer(struct shared_addr *shared_mem,
unsigned long print_phy_addr, u32 size)
{
pENC_RPC_HOST_IFACE pSharedInterface;
pBUFFER_DESCRIPTOR_TYPE debugBufDesc;
pSharedInterface = shared_mem->pSharedInterface;
debugBufDesc = &pSharedInterface->DebugBufferDesc;
debugBufDesc->start = print_phy_addr;
debugBufDesc->end = debugBufDesc->start + size;
debugBufDesc->wptr = debugBufDesc->rptr = debugBufDesc->start;
}

View File

@ -0,0 +1,132 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2018 NXP. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __VPU_ENCODER_RPC_H__
#define __VPU_ENCODER_RPC_H__
#include "mediasys_types.h"
#define CMD_SIZE 2560
#define MSG_SIZE 25600
#define CODEC_SIZE 0x1000
#define JPEG_SIZE 0x1000
#define SEQ_SIZE 0x1000
#define GOP_SIZE 0x1000
#define PIC_SIZE 0x1000
#define QMETER_SIZE 0x1000
#define DEBUG_SIZE 0x1000
#define ENG_SIZE 0x1000
#define LOCAL_MSG_NUM VID_API_MESSAGE_LIMIT
struct shared_addr {
pENC_RPC_HOST_IFACE pSharedInterface;
unsigned long long shared_mem_phy;
void *shared_mem_vir;
unsigned long long cmd_mem_phy;
void *cmd_mem_vir;
unsigned long long msg_mem_phy;
void *msg_mem_vir;
unsigned long long codec_mem_phy;
void *codec_mem_vir;
unsigned long long jpeg_mem_phy;
void *jpeg_mem_vir;
unsigned long long seq_mem_phy;
void *seq_mem_vir;
unsigned long long pic_mem_phy;
void *pic_mem_vir;
unsigned long long gop_mem_phy;
void *gop_mem_vir;
unsigned long long qmeter_mem_phy;
void *qmeter_mem_vir;
unsigned long long base_offset;
};
struct msg_header {
u32 idx;
u32 msgnum;
u32 msgid;
};
void rpc_init_shared_memory_encoder(struct shared_addr *This,
unsigned long long base_phy_addr,
void *base_virt_addr,
u_int32 total_size,
u32 *actual_size);
void rpc_set_system_cfg_value_encoder(void *Interface, u_int32 regs_base, u_int32 core_id);
void rpc_send_cmd_buf_encoder(struct shared_addr *This,
u_int32 idx,
u_int32 cmdid,
u_int32 cmdnum,
u_int32 *local_cmddata);
u32 rpc_read_msg_u32(struct shared_addr *shared_mem);
int rpc_read_msg_array(struct shared_addr *shared_mem, u32 *buf, u32 number);
int rpc_get_msg_header(struct shared_addr *shared_mem, struct msg_header *msg);
pMEDIAIP_ENC_YUV_BUFFER_DESC rpc_get_yuv_buffer_desc(
struct shared_addr *shared_mem, int index);
pBUFFER_DESCRIPTOR_TYPE rpc_get_stream_buffer_desc(
struct shared_addr *shared_mem, int index);
pMEDIAIP_ENC_EXPERT_MODE_PARAM rpc_get_expert_mode_param(
struct shared_addr *shared_mem, int index);
pMEDIAIP_ENC_PARAM rpc_get_enc_param(
struct shared_addr *shared_mem, int index);
pMEDIAIP_ENC_MEM_POOL rpc_get_mem_pool(
struct shared_addr *shared_mem, int index);
pENC_ENCODING_STATUS rpc_get_encoding_status(
struct shared_addr *shared_mem, int index);
pENC_DSA_STATUS_t rpc_get_dsa_status(struct shared_addr *shared_mem, int index);
void rpc_set_print_buffer(struct shared_addr *shared_mem,
unsigned long print_phy_addr, u32 size);
#endif

View File

@ -0,0 +1,235 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_event_msg.c
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include "vpu_encoder_b0.h"
#include "vpu_event_msg.h"
static atomic64_t total_ext_data = ATOMIC64_INIT(0);
static struct vpu_event_msg *alloc_event_msg(void)
{
struct vpu_event_msg *msg = NULL;
msg = vzalloc(sizeof(*msg));
return msg;
}
static void free_event_msg(struct vpu_event_msg *msg)
{
if (!msg)
return;
free_msg_ext_buffer(msg);
vfree(msg);
}
static void set_msg_count(struct vpu_ctx *ctx, unsigned long count)
{
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
if (attr)
attr->msg_count = count;
}
static void inc_msg_count(struct vpu_ctx *ctx)
{
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
if (attr)
attr->msg_count++;
}
static void dec_msg_count(struct vpu_ctx *ctx)
{
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
if (attr)
attr->msg_count--;
}
static bool is_msg_count_full(struct vpu_ctx *ctx)
{
struct vpu_attr *attr = get_vpu_ctx_attr(ctx);
if (!attr)
return false;
if (attr->msg_count > MSG_COUNT_THD)
return true;
return false;
}
void cleanup_ctx_msg_queue(struct vpu_ctx *ctx)
{
struct vpu_event_msg *msg;
struct vpu_event_msg *tmp;
WARN_ON(!ctx);
mutex_lock(&ctx->instance_mutex);
list_for_each_entry_safe(msg, tmp, &ctx->msg_q, list) {
list_del_init(&msg->list);
vpu_dbg(LVL_WARN, "drop core[%d] ctx[%d] msg:[%d]\n",
ctx->core_dev->id, ctx->str_index, msg->msgid);
free_event_msg(msg);
dec_msg_count(ctx);
}
list_for_each_entry_safe(msg, tmp, &ctx->idle_q, list) {
list_del_init(&msg->list);
free_event_msg(msg);
dec_msg_count(ctx);
}
mutex_unlock(&ctx->instance_mutex);
}
static int increase_idle_msg(struct vpu_ctx *ctx, u32 count)
{
int i;
for (i = 0; i < count; i++) {
struct vpu_event_msg *msg = alloc_event_msg();
if (!msg)
continue;
list_add_tail(&msg->list, &ctx->idle_q);
inc_msg_count(ctx);
}
return 0;
}
int init_ctx_msg_queue(struct vpu_ctx *ctx)
{
WARN_ON(!ctx);
if (!ctx)
return -EINVAL;
mutex_lock(&ctx->instance_mutex);
set_msg_count(ctx, 0);
INIT_LIST_HEAD(&ctx->msg_q);
INIT_LIST_HEAD(&ctx->idle_q);
mutex_unlock(&ctx->instance_mutex);
return 0;
}
struct vpu_event_msg *get_idle_msg(struct vpu_ctx *ctx)
{
struct vpu_event_msg *msg = NULL;
WARN_ON(!ctx);
mutex_lock(&ctx->instance_mutex);
if (list_empty(&ctx->idle_q))
increase_idle_msg(ctx, 1);
msg = list_first_entry(&ctx->idle_q, struct vpu_event_msg, list);
if (msg)
list_del_init(&msg->list);
mutex_unlock(&ctx->instance_mutex);
return msg;
}
void put_idle_msg(struct vpu_ctx *ctx, struct vpu_event_msg *msg)
{
WARN_ON(!ctx);
if (!ctx || !msg)
return;
free_msg_ext_buffer(msg);
mutex_lock(&ctx->instance_mutex);
if (is_msg_count_full(ctx)) {
free_event_msg(msg);
dec_msg_count(ctx);
} else {
list_add_tail(&msg->list, &ctx->idle_q);
}
mutex_unlock(&ctx->instance_mutex);
}
struct vpu_event_msg *pop_event_msg(struct vpu_ctx *ctx)
{
struct vpu_event_msg *msg = NULL;
WARN_ON(!ctx);
mutex_lock(&ctx->instance_mutex);
if (list_empty(&ctx->msg_q))
goto exit;
msg = list_first_entry(&ctx->msg_q, struct vpu_event_msg, list);
if (msg)
list_del_init(&msg->list);
exit:
mutex_unlock(&ctx->instance_mutex);
return msg;
}
void push_back_event_msg(struct vpu_ctx *ctx, struct vpu_event_msg *msg)
{
WARN_ON(!ctx);
if (!ctx || !msg)
return;
mutex_lock(&ctx->instance_mutex);
list_add_tail(&msg->list, &ctx->msg_q);
mutex_unlock(&ctx->instance_mutex);
}
int alloc_msg_ext_buffer(struct vpu_event_msg *msg, u32 number)
{
WARN_ON(!msg);
if (!msg || !number)
return -EINVAL;
msg->ext_data = vzalloc(number * sizeof(u32));
if (!msg->ext_data)
return -ENOMEM;
msg->number = number;
atomic64_add(number, &total_ext_data);
vpu_dbg(LVL_DEBUG, "++++alloc %d msg ext data: %lld\n",
number, get_total_ext_data_number());
return 0;
}
void free_msg_ext_buffer(struct vpu_event_msg *msg)
{
WARN_ON(!msg);
if (!msg || !msg->ext_data)
return;
atomic64_sub(msg->number, &total_ext_data);
vfree(msg->ext_data);
msg->ext_data = NULL;
vpu_dbg(LVL_DEBUG, "----free %d msg ext data: %lld\n",
msg->number, get_total_ext_data_number());
}
long long get_total_ext_data_number(void)
{
return atomic64_read(&total_ext_data);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright(c) 2018 NXP. All rights reserved.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* vpu_event_msg.h
*
* Author Ming Qian<ming.qian@nxp.com>
*/
#ifndef _VPU_EVENT_MSG_H
#define _VPU_EVENT_MSG_H
#include "vpu_encoder_config.h"
struct vpu_event_msg {
struct list_head list;
u32 idx;
u32 msgid;
u32 number;
u32 data[MSG_DATA_DEFAULT_SIZE];
u32 *ext_data;
};
int init_ctx_msg_queue(struct vpu_ctx *ctx);
void cleanup_ctx_msg_queue(struct vpu_ctx *ctx);
struct vpu_event_msg *get_idle_msg(struct vpu_ctx *ctx);
void put_idle_msg(struct vpu_ctx *ctx, struct vpu_event_msg *msg);
struct vpu_event_msg *pop_event_msg(struct vpu_ctx *ctx);
void push_back_event_msg(struct vpu_ctx *ctx, struct vpu_event_msg *msg);
int alloc_msg_ext_buffer(struct vpu_event_msg *msg, u32 number);
void free_msg_ext_buffer(struct vpu_event_msg *msg);
long long get_total_ext_data_number(void);
#endif