blob: bd97bb6926f58da5fef4b74d9dcace20f8be04ab [file] [log] [blame]
/*
* drivers/amlogic/amports/encoder.h
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
*/
#ifndef __H264_H__
#define __H264_H__
#include <linux/mutex.h>
#include <linux/semaphore.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/slab.h>
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
#include <linux/amlogic/media/ge2d/ge2d.h>
#endif
#include <linux/dma-buf.h>
#define AMVENC_DEVINFO_M8 "AML-M8"
#define AMVENC_DEVINFO_G9 "AML-G9"
#define AMVENC_DEVINFO_GXBB "AML-GXBB"
#define AMVENC_DEVINFO_GXTVBB "AML-GXTVBB"
#define AMVENC_DEVINFO_GXL "AML-GXL"
#define HCODEC_IRQ_MBOX_CLR HCODEC_ASSIST_MBOX2_CLR_REG
#define HCODEC_IRQ_MBOX_MASK HCODEC_ASSIST_MBOX2_MASK
#define H264_ENC_SVC
/* M8: 2550/10 = 255M GX: 2000/10 = 200M */
#define HDEC_L0() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(2 << 25) | (1 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/8 = 319M GX: 2000/8 = 250M */
#define HDEC_L1() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(0 << 25) | (1 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/7 = 364M GX: 2000/7 = 285M */
#define HDEC_L2() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(3 << 25) | (0 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/6 = 425M GX: 2000/6 = 333M */
#define HDEC_L3() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(1 << 25) | (1 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/5 = 510M GX: 2000/5 = 400M */
#define HDEC_L4() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(2 << 25) | (0 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/4 = 638M GX: 2000/4 = 500M */
#define HDEC_L5() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(0 << 25) | (0 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
/* M8: 2550/3 = 850M GX: 2000/3 = 667M */
#define HDEC_L6() WRITE_HHI_REG(HHI_VDEC_CLK_CNTL, \
(1 << 25) | (0 << 16) | (1 << 24) | \
(0xffff & READ_HHI_REG(HHI_VDEC_CLK_CNTL)))
#define hvdec_clock_enable(level) \
do { \
if (level == 0) \
HDEC_L0(); \
else if (level == 1) \
HDEC_L1(); \
else if (level == 2) \
HDEC_L2(); \
else if (level == 3) \
HDEC_L3(); \
else if (level == 4) \
HDEC_L4(); \
else if (level == 5) \
HDEC_L5(); \
else if (level == 6) \
HDEC_L6(); \
WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); \
} while (0)
#define hvdec_clock_disable() \
do { \
WRITE_VREG_BITS(DOS_GCLK_EN0, 0, 12, 15); \
WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1); \
} while (0)
#define LOG_ALL 0
#define LOG_INFO 1
#define LOG_DEBUG 2
#define LOG_ERROR 3
#define enc_pr(level, x...) \
do { \
if (level >= encode_print_level) \
printk(x); \
} while (0)
#define AMVENC_AVC_IOC_MAGIC 'E'
#define AMVENC_AVC_IOC_GET_DEVINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0xf0, u32)
#define AMVENC_AVC_IOC_MAX_INSTANCE _IOW(AMVENC_AVC_IOC_MAGIC, 0xf1, u32)
#define AMVENC_AVC_IOC_GET_CPU_ID _IOW(AMVENC_AVC_IOC_MAGIC, 0xf2, u32)
#define AMVENC_AVC_IOC_GET_ADDR _IOW(AMVENC_AVC_IOC_MAGIC, 0x00, u32)
#define AMVENC_AVC_IOC_INPUT_UPDATE _IOW(AMVENC_AVC_IOC_MAGIC, 0x01, u32)
#define AMVENC_AVC_IOC_NEW_CMD _IOW(AMVENC_AVC_IOC_MAGIC, 0x02, u32)
#define AMVENC_AVC_IOC_GET_STAGE _IOW(AMVENC_AVC_IOC_MAGIC, 0x03, u32)
#define AMVENC_AVC_IOC_GET_OUTPUT_SIZE _IOW(AMVENC_AVC_IOC_MAGIC, 0x04, u32)
#define AMVENC_AVC_IOC_CONFIG_INIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x05, u32)
#define AMVENC_AVC_IOC_FLUSH_CACHE _IOW(AMVENC_AVC_IOC_MAGIC, 0x06, u32)
#define AMVENC_AVC_IOC_FLUSH_DMA _IOW(AMVENC_AVC_IOC_MAGIC, 0x07, u32)
#define AMVENC_AVC_IOC_GET_BUFFINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0x08, u32)
#define AMVENC_AVC_IOC_SUBMIT _IOW(AMVENC_AVC_IOC_MAGIC, 0x09, u32)
#define AMVENC_AVC_IOC_READ_CANVAS _IOW(AMVENC_AVC_IOC_MAGIC, 0x0a, u32)
#define AMVENC_AVC_IOC_QP_MODE _IOW(AMVENC_AVC_IOC_MAGIC, 0x0b, u32)
#define IE_PIPPELINE_BLOCK_SHIFT 0
#define IE_PIPPELINE_BLOCK_MASK 0x1f
#define ME_PIXEL_MODE_SHIFT 5
#define ME_PIXEL_MODE_MASK 0x3
enum amvenc_mem_type_e {
LOCAL_BUFF = 0,
CANVAS_BUFF,
PHYSICAL_BUFF,
DMA_BUFF,
MAX_BUFF_TYPE
};
enum amvenc_frame_fmt_e {
FMT_YUV422_SINGLE = 0,
FMT_YUV444_SINGLE,
FMT_NV21,
FMT_NV12,
FMT_YUV420,
FMT_YUV444_PLANE,
FMT_RGB888,
FMT_RGB888_PLANE,
FMT_RGB565,
FMT_RGBA8888,
FMT_YUV422_12BIT,
FMT_YUV444_10BIT,
FMT_YUV422_10BIT,
FMT_BGR888,
MAX_FRAME_FMT
};
#define MAX_ENCODE_REQUEST 8 /* 64 */
#define MAX_ENCODE_INSTANCE 8 /* 64 */
#define ENCODE_PROCESS_QUEUE_START 0
#define ENCODE_PROCESS_QUEUE_STOP 1
#define AMVENC_FLUSH_FLAG_INPUT 0x1
#define AMVENC_FLUSH_FLAG_OUTPUT 0x2
#define AMVENC_FLUSH_FLAG_REFERENCE 0x4
#define AMVENC_FLUSH_FLAG_INTRA_INFO 0x8
#define AMVENC_FLUSH_FLAG_INTER_INFO 0x10
#define AMVENC_FLUSH_FLAG_QP 0x20
#define AMVENC_FLUSH_FLAG_DUMP 0x40
#define AMVENC_FLUSH_FLAG_CBR 0x80
#define ENCODER_BUFFER_INPUT 0
#define ENCODER_BUFFER_REF0 1
#define ENCODER_BUFFER_REF1 2
#define ENCODER_BUFFER_OUTPUT 3
#define ENCODER_BUFFER_INTER_INFO 4
#define ENCODER_BUFFER_INTRA_INFO 5
#define ENCODER_BUFFER_QP 6
#define ENCODER_BUFFER_DUMP 7
#define ENCODER_BUFFER_CBR 8
struct encode_wq_s;
struct enc_dma_cfg {
int fd;
void *dev;
void *vaddr;
void *paddr;
struct dma_buf *dbuf;
struct dma_buf_attachment *attach;
struct sg_table *sg;
enum dma_data_direction dir;
};
struct encode_request_s {
u32 quant;
u32 cmd;
u32 ucode_mode;
u32 src;
u32 framesize;
u32 me_weight;
u32 i4_weight;
u32 i16_weight;
u32 crop_top;
u32 crop_bottom;
u32 crop_left;
u32 crop_right;
u32 src_w;
u32 src_h;
u32 scale_enable;
u32 nr_mode;
u32 flush_flag;
u32 timeout;
enum amvenc_mem_type_e type;
enum amvenc_frame_fmt_e fmt;
struct encode_wq_s *parent;
struct enc_dma_cfg dma_cfg[3];
u32 plane_num;
};
struct encode_queue_item_s {
struct list_head list;
struct encode_request_s request;
};
struct Buff_s {
u32 buf_start;
u32 buf_size;
bool used;
};
struct BuffInfo_s {
u32 lev_id;
u32 min_buffsize;
u32 max_width;
u32 max_height;
struct Buff_s dct;
struct Buff_s dec0_y;
struct Buff_s dec0_uv;
struct Buff_s dec1_y;
struct Buff_s dec1_uv;
struct Buff_s assit;
struct Buff_s bitstream;
struct Buff_s scale_buff;
struct Buff_s dump_info;
struct Buff_s cbr_info;
};
struct encode_meminfo_s {
u32 buf_start;
u32 buf_size;
u32 BitstreamStart;
u32 BitstreamEnd;
/*input buffer define*/
u32 dct_buff_start_addr;
u32 dct_buff_end_addr;
/*microcode assitant buffer*/
u32 assit_buffer_offset;
u32 scaler_buff_start_addr;
u32 dump_info_ddr_start_addr;
u32 dump_info_ddr_size;
u32 cbr_info_ddr_start_addr;
u32 cbr_info_ddr_size;
u8 * cbr_info_ddr_virt_addr;
s32 dblk_buf_canvas;
s32 ref_buf_canvas;
struct BuffInfo_s bufspec;
#ifdef CONFIG_CMA
struct page *venc_pages;
#endif
};
struct encode_picinfo_s {
u32 encoder_width;
u32 encoder_height;
u32 rows_per_slice;
u32 idr_pic_id; /* need reset as 0 for IDR */
u32 frame_number; /* need plus each frame */
/* need reset as 0 for IDR and plus 2 for NON-IDR */
u32 pic_order_cnt_lsb;
u32 log2_max_pic_order_cnt_lsb;
u32 log2_max_frame_num;
u32 init_qppicture;
#ifdef H264_ENC_SVC
u32 enable_svc;
u32 non_ref_limit;
u32 non_ref_cnt;
#endif
u32 color_space;
};
struct encode_cbr_s {
u16 block_w;
u16 block_h;
u16 long_th;
u8 start_tbl_id;
u8 short_shift;
u8 long_mb_num;
};
struct encode_wq_s {
struct list_head list;
/* dev info */
u32 ucode_index;
u32 hw_status;
u32 output_size;
u32 sps_size;
u32 pps_size;
u32 me_weight;
u32 i4_weight;
u32 i16_weight;
u32 quant_tbl_i4[8];
u32 quant_tbl_i16[8];
u32 quant_tbl_me[8];
struct encode_meminfo_s mem;
struct encode_picinfo_s pic;
struct encode_request_s request;
struct encode_cbr_s cbr_info;
atomic_t request_ready;
wait_queue_head_t request_complete;
};
struct encode_event_s {
wait_queue_head_t hw_complete;
struct completion process_complete;
spinlock_t sem_lock; /* for queue switch and create destroy queue. */
struct completion request_in_com;
};
struct encode_manager_s {
struct list_head wq;
struct list_head process_queue;
struct list_head free_queue;
u32 encode_hw_status;
u32 process_queue_state;
s32 irq_num;
u32 wq_count;
u32 ucode_index;
u32 max_instance;
#ifdef CONFIG_AMLOGIC_MEDIA_GE2D
struct ge2d_context_s *context;
#endif
bool irq_requested;
bool need_reset;
bool process_irq;
bool inited; /* power on encode */
bool remove_flag; /* remove wq; */
bool uninit_flag; /* power off encode */
bool use_reserve;
#ifdef CONFIG_CMA
bool check_cma;
ulong cma_pool_size;
#endif
struct platform_device *this_pdev;
struct Buff_s *reserve_buff;
struct encode_wq_s *current_wq;
struct encode_wq_s *last_wq;
struct encode_queue_item_s *current_item;
struct task_struct *encode_thread;
struct Buff_s reserve_mem;
struct encode_event_s event;
struct tasklet_struct encode_tasklet;
};
extern s32 encode_wq_add_request(struct encode_wq_s *wq);
extern struct encode_wq_s *create_encode_work_queue(void);
extern s32 destroy_encode_work_queue(struct encode_wq_s *encode_work_queue);
/********************************************
* AV Scratch Register Re-Define
****************************************** *
*/
#define ENCODER_STATUS HCODEC_HENC_SCRATCH_0
#define MEM_OFFSET_REG HCODEC_HENC_SCRATCH_1
#define DEBUG_REG HCODEC_HENC_SCRATCH_2
#define IDR_PIC_ID HCODEC_HENC_SCRATCH_5
#define FRAME_NUMBER HCODEC_HENC_SCRATCH_6
#define PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_7
#define LOG2_MAX_PIC_ORDER_CNT_LSB HCODEC_HENC_SCRATCH_8
#define LOG2_MAX_FRAME_NUM HCODEC_HENC_SCRATCH_9
#define ANC0_BUFFER_ID HCODEC_HENC_SCRATCH_A
#define QPPICTURE HCODEC_HENC_SCRATCH_B
#define IE_ME_MB_TYPE HCODEC_HENC_SCRATCH_D
/* bit 0-4, IE_PIPPELINE_BLOCK
* bit 5 me half pixel in m8
* disable i4x4 in gxbb
* bit 6 me step2 sub pixel in m8
* disable i16x16 in gxbb
*/
#define IE_ME_MODE HCODEC_HENC_SCRATCH_E
#define IE_REF_SEL HCODEC_HENC_SCRATCH_F
/* [31:0] NUM_ROWS_PER_SLICE_P */
/* [15:0] NUM_ROWS_PER_SLICE_I */
#define FIXED_SLICE_CFG HCODEC_HENC_SCRATCH_L
/* For GX */
#define INFO_DUMP_START_ADDR HCODEC_HENC_SCRATCH_I
/* For CBR */
#define H264_ENC_CBR_TABLE_ADDR HCODEC_HENC_SCRATCH_3
#define H264_ENC_CBR_MB_SIZE_ADDR HCODEC_HENC_SCRATCH_4
/* Bytes(Float) * 256 */
#define H264_ENC_CBR_CTL HCODEC_HENC_SCRATCH_G
/* [31:28] : init qp table idx */
/* [27:24] : short_term adjust shift */
/* [23:16] : Long_term MB_Number between adjust, */
/* [15:0] Long_term adjust threshold(Bytes) */
#define H264_ENC_CBR_TARGET_SIZE HCODEC_HENC_SCRATCH_H
/* Bytes(Float) * 256 */
#define H264_ENC_CBR_PREV_BYTES HCODEC_HENC_SCRATCH_J
#define H264_ENC_CBR_REGION_SIZE HCODEC_HENC_SCRATCH_J
/* for SVC */
#define H264_ENC_SVC_PIC_TYPE HCODEC_HENC_SCRATCH_K
/* define for PIC header */
#define ENC_SLC_REF 0x8410
#define ENC_SLC_NON_REF 0x8010
/* --------------------------------------------------- */
/* ENCODER_STATUS define */
/* --------------------------------------------------- */
#define ENCODER_IDLE 0
#define ENCODER_SEQUENCE 1
#define ENCODER_PICTURE 2
#define ENCODER_IDR 3
#define ENCODER_NON_IDR 4
#define ENCODER_MB_HEADER 5
#define ENCODER_MB_DATA 6
#define ENCODER_SEQUENCE_DONE 7
#define ENCODER_PICTURE_DONE 8
#define ENCODER_IDR_DONE 9
#define ENCODER_NON_IDR_DONE 10
#define ENCODER_MB_HEADER_DONE 11
#define ENCODER_MB_DATA_DONE 12
#define ENCODER_NON_IDR_INTRA 13
#define ENCODER_NON_IDR_INTER 14
#define ENCODER_ERROR 0xff
/********************************************
* defines for H.264 mb_type
*******************************************
*/
#define HENC_MB_Type_PBSKIP 0x0
#define HENC_MB_Type_PSKIP 0x0
#define HENC_MB_Type_BSKIP_DIRECT 0x0
#define HENC_MB_Type_P16x16 0x1
#define HENC_MB_Type_P16x8 0x2
#define HENC_MB_Type_P8x16 0x3
#define HENC_MB_Type_SMB8x8 0x4
#define HENC_MB_Type_SMB8x4 0x5
#define HENC_MB_Type_SMB4x8 0x6
#define HENC_MB_Type_SMB4x4 0x7
#define HENC_MB_Type_P8x8 0x8
#define HENC_MB_Type_I4MB 0x9
#define HENC_MB_Type_I16MB 0xa
#define HENC_MB_Type_IBLOCK 0xb
#define HENC_MB_Type_SI4MB 0xc
#define HENC_MB_Type_I8MB 0xd
#define HENC_MB_Type_IPCM 0xe
#define HENC_MB_Type_AUTO 0xf
#define HENC_MB_CBP_AUTO 0xff
#define HENC_SKIP_RUN_AUTO 0xffff
extern bool amvenc_avc_on(void);
#endif