blob: 12ed65b62e7396ace116ffa4f6ae1e8361e51330 [file] [log] [blame]
/*
* Copyright (C) 2017 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.
*
* 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Description:
*/
#ifndef _AML_DVB_H_
#define _AML_DVB_H_
#include <linux/interrupt.h>
#include <linux/socket.h>
#include <linux/netdevice.h>
#include <linux/i2c.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/ca.h>
#include <linux/dvb/osd.h>
#include <linux/dvb/net.h>
#include <linux/dvb/frontend.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <dvbdev.h>
#include <demux.h>
#include <dvb_demux.h>
#include <dmxdev.h>
#include <dvb_filter.h>
#include <dvb_net.h>
#include <dvb_ringbuffer.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include "aml_demod_gt.h"
#define TS_IN_COUNT 4
#define S2P_COUNT 3
#define ASYNCFIFO_COUNT 3
#if 0
#define TS_IN_COUNT 3
#define S2P_COUNT 2
#define ASYNCFIFO_COUNT 2
#endif
#define DMX_DEV_COUNT 3
#define FE_DEV_COUNT 2
#define CHANNEL_COUNT 31
#define FILTER_COUNT 31
#define FILTER_LEN 15
#define DSC_DEV_COUNT 2
#define DSC_COUNT 8
#define SEC_BUF_GRP_COUNT 4
#define SEC_BUF_BUSY_SIZE 4
#define SEC_BUF_COUNT (SEC_BUF_GRP_COUNT*8)
enum aml_dmx_id_t {
AM_DMX_0 = 0,
AM_DMX_1,
AM_DMX_2,
AM_DMX_MAX,
};
enum aml_ts_source_t {
AM_TS_SRC_TS0,
AM_TS_SRC_TS1,
AM_TS_SRC_TS2,
AM_TS_SRC_TS3,
AM_TS_SRC_S_TS0,
AM_TS_SRC_S_TS1,
AM_TS_SRC_S_TS2,
AM_TS_SRC_S_TS3,
AM_TS_SRC_HIU,
AM_TS_SRC_HIU1,
AM_TS_SRC_DMX0,
AM_TS_SRC_DMX1,
AM_TS_SRC_DMX2
};
struct aml_sec_buf {
unsigned long addr;
int len;
};
struct aml_channel {
int type;
enum dmx_ts_pes pes_type;
int pid;
int used;
int filter_count;
struct dvb_demux_feed *feed;
struct dvb_demux_feed *dvr_feed;
int pkt_type;
};
struct aml_filter {
int chan_id;
int used;
struct dmx_section_filter *filter;
u8 value[FILTER_LEN];
u8 maskandmode[FILTER_LEN];
u8 maskandnotmode[FILTER_LEN];
u8 neq;
};
#define DVBCSA_MODE 0
#define CIPLUS_MODE 1
#define CBC_MODE 0
#define ECB_MODE 1
#define IDSA_MODE 2
#define DSC_SET_EVEN 1
#define DSC_SET_ODD 2
#define DSC_SET_AES_EVEN 4
#define DSC_SET_AES_ODD 8
#define DSC_FROM_KL 16
#define DSC_SET_SM4_EVEN 32
#define DSC_SET_SM4_ODD 64
#define DSC_KEY_SIZE_MAX 16
struct aml_dsc_channel {
int pid;
u8 even[DSC_KEY_SIZE_MAX];
u8 odd[DSC_KEY_SIZE_MAX];
u8 even_iv[DSC_KEY_SIZE_MAX];
u8 odd_iv[DSC_KEY_SIZE_MAX];
int used;
int set;
int id;
struct aml_dsc *dsc;
int work_mode;
int mode;
};
struct aml_dsc {
struct dvb_device *dev;
struct aml_dsc_channel channel[DSC_COUNT];
enum aml_ts_source_t source;
enum aml_ts_source_t dst;
struct aml_dvb *dvb;
int id;
int work_mode;
};
struct aml_smallsec {
struct aml_dmx *dmx;
int enable;
int bufsize;
#define SS_BUFSIZE_DEF (16*4*256) /*16KB*/
long buf;
long buf_map;
};
struct aml_dmxtimeout {
struct aml_dmx *dmx;
int enable;
int timeout;
#define DTO_TIMEOUT_DEF (9000) /*0.5s*/
u32 ch_disable;
#define DTO_CHDIS_VAS (0xfffffff8) /*v/a/s only*/
int match;
int trigger;
};
struct aml_dmx {
struct dvb_demux demux;
struct dmxdev dmxdev;
int id;
int feed_count;
int chan_count;
enum aml_ts_source_t source;
int init;
int record;
struct dmx_frontend hw_fe[DMX_DEV_COUNT];
struct dmx_frontend mem_fe;
struct dvb_net dvb_net;
int dmx_irq;
int dvr_irq;
struct tasklet_struct dmx_tasklet;
struct tasklet_struct dvr_tasklet;
unsigned long sec_pages;
unsigned long sec_pages_map;
int sec_total_len;
struct aml_sec_buf sec_buf[SEC_BUF_COUNT];
unsigned long pes_pages;
unsigned long pes_pages_map;
int pes_buf_len;
union {
unsigned long sub_pages;
unsigned long sub_buf_base;
};
union {
unsigned long sub_pages_map;
u8 *sub_buf_base_virt;
};
int sub_buf_len;
struct aml_channel channel[CHANNEL_COUNT+1];
struct aml_filter filter[FILTER_COUNT+1];
irq_handler_t irq_handler;
void *irq_data;
int aud_chan;
int vid_chan;
int sub_chan;
int pcr_chan;
u32 section_busy[SEC_BUF_BUSY_SIZE];
struct dvb_frontend *fe;
int int_check_count;
u32 int_check_time;
int in_tune;
int error_check;
int dump_ts_select;
int sec_buf_watchdog_count[SEC_BUF_COUNT];
struct aml_smallsec smallsec;
struct aml_dmxtimeout timeout;
int demux_filter_user;
unsigned long sec_cnt[3];
unsigned long sec_cnt_match[3];
unsigned long sec_cnt_crc_fail[3];
#define SEC_CNT_HW (0)
#define SEC_CNT_SW (1)
#define SEC_CNT_SS (2)
#define SEC_CNT_MAX (3)
int crc_check_count;
u32 crc_check_time;
int om_status_error_count;
};
struct aml_dvr_block {
u32 addr;
u32 len;
};
struct aml_asyncfifo {
int id;
int init;
int asyncfifo_irq;
enum aml_dmx_id_t source;
unsigned long pages;
unsigned long pages_map;
int buf_len;
int buf_toggle;
int buf_read;
int flush_size;
int secure_enable;
struct tasklet_struct asyncfifo_tasklet;
struct aml_dvb *dvb;
struct aml_dvr_block blk;
unsigned long stored_pages;
};
enum{
AM_TS_DISABLE,
AM_TS_PARALLEL,
AM_TS_SERIAL
};
struct aml_ts_input {
int mode;
struct pinctrl *pinctrl;
int control;
int s2p_id;
};
struct aml_s2p {
int invert;
};
struct aml_swfilter {
int user;
struct aml_dmx *dmx;
struct aml_asyncfifo *afifo;
struct dvb_ringbuffer rbuf;
#define SF_BUFFER_SIZE (10*188*1024)
u8 wrapbuf[188];
int track_dmx;
};
struct aml_dvb {
struct dvb_device dvb_dev;
int ts_in_total_count;
struct aml_ts_input ts[TS_IN_COUNT];
int s2p_total_count;
struct aml_s2p s2p[S2P_COUNT];
struct aml_dmx dmx[DMX_DEV_COUNT];
struct aml_dsc dsc[DSC_DEV_COUNT];
int async_fifo_total_count;
struct aml_asyncfifo asyncfifo[ASYNCFIFO_COUNT];
struct dvb_adapter dvb_adapter;
struct device *dev;
struct platform_device *pdev;
enum aml_ts_source_t stb_source;
enum aml_ts_source_t tso_source;
int dmx_init;
int reset_flag;
spinlock_t slock;
struct timer_list watchdog_timer;
int dmx_watchdog_disable[DMX_DEV_COUNT];
struct aml_swfilter swfilter;
int ts_out_invert;
/*bufs for dmx shared*/
unsigned long pes_pages;
unsigned long pes_pages_map;
int pes_buf_len;
unsigned long sub_pages;
unsigned long sub_pages_map;
int sub_buf_len;
};
/*AMLogic demux interface*/
extern int aml_dmx_hw_init(struct aml_dmx *dmx);
extern int aml_dmx_hw_deinit(struct aml_dmx *dmx);
extern int aml_dmx_hw_start_feed(struct dvb_demux_feed *dvbdmxfeed);
extern int aml_dmx_hw_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
extern int aml_dmx_hw_set_source(struct dmx_demux *demux,
dmx_source_t src);
extern int aml_stb_hw_set_source(struct aml_dvb *dvb, dmx_source_t src);
extern int aml_dsc_hw_set_source(struct aml_dsc *dsc,
dmx_source_t src, dmx_source_t dst);
extern int aml_tso_hw_set_source(struct aml_dvb *dvb, dmx_source_t src);
extern int aml_dmx_set_skipbyte(struct aml_dvb *dvb, int skipbyte);
extern int aml_dmx_set_demux(struct aml_dvb *dvb, int id);
extern int aml_dmx_hw_set_dump_ts_select
(struct dmx_demux *demux, int dump_ts_select);
extern int dmx_alloc_chan(struct aml_dmx *dmx, int type,
int pes_type, int pid);
extern void dmx_free_chan(struct aml_dmx *dmx, int cid);
extern int dmx_get_ts_serial(enum aml_ts_source_t src);
extern int dmx_get_sub_buffer(unsigned long *base, unsigned long *virt);
extern int dmx_init_sub_buffer(struct aml_dmx *dmx, unsigned long base, unsigned long virt);
/*AMLogic dsc interface*/
extern int dsc_set_pid(struct aml_dsc_channel *ch, int pid);
extern int dsc_set_key(struct aml_dsc_channel *ch, int flags,
enum ca_cw_type type, u8 *key);
extern void dsc_release(void);
extern int aml_ciplus_hw_set_source(int src);
/*AMLogic ASYNC FIFO interface*/
extern int aml_asyncfifo_hw_init(struct aml_asyncfifo *afifo);
extern int aml_asyncfifo_hw_deinit(struct aml_asyncfifo *afifo);
extern int aml_asyncfifo_hw_set_source(struct aml_asyncfifo *afifo,
enum aml_dmx_id_t src);
extern int aml_asyncfifo_hw_reset(struct aml_asyncfifo *afifo);
/*Get the Audio & Video PTS*/
extern u32 aml_dmx_get_video_pts(struct aml_dvb *dvb);
extern u32 aml_dmx_get_audio_pts(struct aml_dvb *dvb);
extern u32 aml_dmx_get_video_pts_bit32(struct aml_dvb *dvb);
extern u32 aml_dmx_get_audio_pts_bit32(struct aml_dvb *dvb);
extern u32 aml_dmx_get_first_video_pts(struct aml_dvb *dvb);
extern u32 aml_dmx_get_first_audio_pts(struct aml_dvb *dvb);
/*Get the DVB device*/
extern struct aml_dvb *aml_get_dvb_device(void);
extern int aml_regist_dmx_class(void);
extern int aml_unregist_dmx_class(void);
extern void aml_register_parser_mconfig(void);
struct devio_aml_platform_data {
int (*io_setup)(void *);
int (*io_cleanup)(void *);
int (*io_power)(void *, int enable);
int (*io_reset)(void *, int enable);
};
void get_aml_dvb(struct aml_dvb *dvb_device);
/*Reset the demux device*/
void dmx_reset_hw(struct aml_dvb *dvb);
void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq);
/*Reset the individual demux*/
void dmx_reset_dmx_hw(struct aml_dvb *dvb, int id);
void dmx_reset_dmx_id_hw_ex(struct aml_dvb *dvb, int id, int reset_irq);
void dmx_reset_dmx_id_hw_ex_unlock(struct aml_dvb *dvb, int id, int reset_irq);
void dmx_reset_dmx_hw_ex(struct aml_dvb *dvb,
struct aml_dmx *dmx,
int reset_irq);
void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb,
struct aml_dmx *dmx,
int reset_irq);
#endif