blob: 89464459d1df713a28a635753b36d0a5925986f2 [file] [log] [blame]
/*
* drivers/amlogic/media/frame_sync/tsync_pcr.c
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/amlogic/media/frame_sync/tsync.h>
#include <linux/platform_device.h>
#include <linux/amlogic/media/frame_sync/timestamp.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
#include <linux/amlogic/cpu_version.h>
#ifdef CONFIG_AM_PCRSYNC_LOG
#define AMLOG
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_ATTENTION 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_VAR amlog_level_tsync_pcr
#define LOG_MASK_VAR amlog_mask_tsync_pcr
#endif
#include <linux/amlogic/media/utils/amlog.h>
MODULE_AMLOG(AMLOG_DEFAULT_LEVEL, 0, LOG_DEFAULT_LEVEL_DESC,
LOG_DEFAULT_MASK_DESC);
enum play_mode_e {
PLAY_MODE_NORMAL = 0,
PLAY_MODE_SLOW,
PLAY_MODE_SPEED,
PLAY_MODE_FORCE_SLOW,
PLAY_MODE_FORCE_SPEED,
};
enum pcr_init_priority_e {
INIT_PRIORITY_PCR = 0,
INIT_PRIORITY_AUDIO = 1,
INIT_PRIORITY_VIDEO = 2,
};
#define PCR_DISCONTINUE 0x01
#define VIDEO_DISCONTINUE 0x02
#define AUDIO_DISCONTINUE 0x10
#define CHECK_INTERVAL (HZ * 5)
#define START_AUDIO_LEVEL 256
#define START_VIDEO_LEVEL 2048
#define PAUSE_AUDIO_LEVEL 32
#define PAUSE_VIDEO_LEVEL 2560
#define UP_RESAMPLE_AUDIO_LEVEL 128
#define UP_RESAMPLE_VIDEO_LEVEL 1024
#define DOWN_RESAMPLE_CACHE_TIME (90000*2)
#define NO_DATA_CHECK_TIME 4000
/*
*the diff of system time and referrence lock,
* which use the threshold to adjust the system time
*/
#define OPEN_RECOVERY_THRESHOLD 18000
#define CLOSE_RECOVERY_THRESHOLD 300
/*#define RECOVERY_SPAN 3 */
#define FORCE_RECOVERY_SPAN 20
#define PAUSE_CHECK_TIME 2700
#define PAUSE_RESUME_TIME 18000
/* modify it by dolby av sync 20160126 */
static u32 tsync_pcr_recovery_span = 3; /* 10 */
/* the delay from ts demuxer to the amvideo */
#define DEFAULT_VSTREAM_DELAY 18000
#define RESAMPLE_TYPE_NONE 0
#define RESAMPLE_TYPE_DOWN 1
#define RESAMPLE_TYPE_UP 2
#define RESAMPLE_DOWN_FORCE_PCR_SLOW 3
#define MS_INTERVAL (HZ/1000)
#define TEN_MS_INTERVAL (HZ/100)
/* local system inited check type */
#define TSYNC_PCR_INITCHECK_PCR 0x0001
#define TSYNC_PCR_INITCHECK_VPTS 0x0002
#define TSYNC_PCR_INITCHECK_APTS 0x0004
#define TSYNC_PCR_INITCHECK_RECORD 0x0008
#define TSYNC_PCR_INITCHECK_END 0x0010
#define MIN_GAP (90000*3) /* 3s */
#define MAX_GAP (90000*3) /* 4s */
/* av sync monitor threshold */
#define MAX_SYNC_VGAP_TIME 90000
#define MIN_SYNC_VCHACH_TIME 45000
#define MAX_SYNC_AGAP_TIME 45000
#define MIN_SYNC_ACHACH_TIME 27000
#define PLAY_MODE_THRESHOLD 500 /*ms*/
#define PLAY_PCR_INVALID_THRESHOLD (10*90000)
/* ------------------------------------------------------------------ */
/* The const */
static u32 tsync_pcr_discontinue_threshold = (TIME_UNIT90K * 1.5);
static u32 tsync_pcr_ref_latency = (TIME_UNIT90K * 0.3);
/* use for pcr valid mode */
static u32 tsync_pcr_max_cache_time = TIME_UNIT90K * 2.4;
static u32 tsync_pcr_up_cache_time = TIME_UNIT90K * 2.2;
/* modify it by dolby av sync */
static u32 tsync_pcr_down_cache_time = TIME_UNIT90K * 0.8; /* 0.6 */
static u32 tsync_pcr_min_cache_time = TIME_UNIT90K * 0.4; /* 0.2 */
static u32 tsync_apts_adj_value = 150000; /* add it by dolby av sync */
static u32 tsync_pcr_adj_value = 27000; /* 300ms */
static u32 tsync_pcr_first_video_frame_pts;
static u32 tsync_pcr_first_audio_frame_pts;
/* reset control flag */
static u8 tsync_pcr_reset_flag;
static int tsync_pcr_asynccheck_cnt;
static int tsync_pcr_vsynccheck_cnt;
static int init_check_first_systemtime;
static int init_check_first_demuxpcr;
/* ------------------------------------------------------------------ */
/* The variate */
static struct timer_list tsync_pcr_check_timer;
static u32 tsync_pcr_tsdemux_startpcr;
static int tsync_pcr_vpause_flag;
static int tsync_pcr_apause_flag;
static int tsync_pcr_vstart_flag;
static int tsync_pcr_astart_flag;
static u8 tsync_pcr_inited_flag;
static u8 tsync_pcr_inited_mode = INIT_PRIORITY_PCR;
static u32 tsync_pcr_freerun_mode;
static int64_t tsync_pcr_stream_delta;
/* the really ts demuxer pcr, haven't delay */
static u32 tsync_pcr_last_tsdemuxpcr;
static u32 tsync_pcr_discontinue_local_point;
static u32 tsync_pcr_discontinue_waited;
/* the time waited the v-discontinue to happen */
static u8 tsync_pcr_tsdemuxpcr_discontinue;
/* the boolean value */
static u32 tsync_pcr_discontinue_point;
static int abuf_level;
static int abuf_size;
static int vbuf_level;
static int vbuf_size;
static int play_mode = PLAY_MODE_NORMAL;
static u8 tsync_pcr_started;
static int tsync_pcr_read_cnt;
static u8 tsync_pcr_usepcr;
/* static int tsync_pcr_debug_pcrscr = 100; */
static u64 first_time_record;
static u8 wait_pcr_count;
static int abuf_fatal_error;
static int vbuf_fatal_error;
static u32 tsync_pcr_first_jiffes;
static u32 tsync_pcr_first_systime;
static u32 tsync_pcr_jiffes_diff;
static u32 tysnc_pcr_systime_diff;
static u32 tsync_last_play_mode;
static u32 tsync_use_demux_pcr = 1;
static u32 tsync_pcr_debug;
static DEFINE_SPINLOCK(tsync_pcr_lock);
module_param(tsync_pcr_max_cache_time, uint, 0664);
MODULE_PARM_DESC(tsync_pcr_max_cache_time, "\n tsync pcr max cache time\n");
module_param(tsync_pcr_up_cache_time, uint, 0664);
MODULE_PARM_DESC(tsync_pcr_up_cache_time, "\n tsync pcr up cache time\n");
module_param(tsync_pcr_down_cache_time, uint, 0664);
MODULE_PARM_DESC(tsync_pcr_down_cache_time, "\n tsync pcr down cache time\n");
module_param(tsync_pcr_min_cache_time, uint, 0664);
MODULE_PARM_DESC(tsync_pcr_min_cache_time, "\n tsync pcr min cache time\n");
struct stream_buf_s {
s32 flag;
u32 type;
unsigned long buf_start;
struct page *buf_pages;
int buf_page_num;
u32 buf_size;
u32 default_buf_size;
u32 canusebuf_size;
u32 first_tstamp;
const ulong reg_base;
wait_queue_head_t wq;
struct timer_list timer;
u32 wcnt;
u32 buf_wp;
u32 buf_rp;
u32 max_buffer_delay_ms;
u64 last_write_jiffies64;
void *write_thread;
int for_4k;
bool is_secure;
} /*stream_buf_t */;
int get_stream_buffer_level(int type)
{
struct stream_buf_s *pbuf = NULL;
if (type == 0) {
/* video */
if (get_buf_by_type_cb)
pbuf = get_buf_by_type_cb(PTS_TYPE_VIDEO);
if (pbuf != NULL && stbuf_level_cb
&& pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/)
return stbuf_level_cb(pbuf);
} else {
/* audio */
if (get_buf_by_type_cb)
pbuf = get_buf_by_type_cb(PTS_TYPE_AUDIO);
if (pbuf != NULL && stbuf_level_cb &&
pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/)
return stbuf_level_cb(pbuf);
}
return 0;
}
EXPORT_SYMBOL(get_stream_buffer_level);
int get_stream_buffer_size(int type)
{
struct stream_buf_s *pbuf = NULL;
if (type == 0) {
/* video */
if (get_buf_by_type_cb)
pbuf = get_buf_by_type_cb(PTS_TYPE_VIDEO);
if (pbuf != NULL && stbuf_size_cb &&
pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/)
return stbuf_size_cb(pbuf);
} else {
/* audio */
if (get_buf_by_type_cb)
pbuf = get_buf_by_type_cb(PTS_TYPE_AUDIO);
if (pbuf != NULL && stbuf_size_cb
&& pbuf->flag & 0x02/*BUF_FLAG_IN_USE*/)
return stbuf_size_cb(pbuf);
}
return 0;
}
EXPORT_SYMBOL(get_stream_buffer_size);
int get_min_cache_delay(void)
{
/*int video_cache_time = calculation_vcached_delayed();*/
/*int audio_cache_time = calculation_acached_delayed();*/
int audio_cache_time = 90 * calculation_stream_delayed_ms(
PTS_TYPE_AUDIO, NULL, NULL);
int video_cache_time = 90 * calculation_stream_delayed_ms(
PTS_TYPE_VIDEO, NULL, NULL);
if (video_cache_time > 0 && audio_cache_time > 0)
return min(video_cache_time, audio_cache_time);
else if (video_cache_time > 0)
return video_cache_time;
else if (audio_cache_time > 0)
return audio_cache_time;
else
return 0;
}
EXPORT_SYMBOL(get_min_cache_delay);
u32 tsync_pcr_vstream_delayed(void)
{
int cur_delay = calculation_vcached_delayed();
if (cur_delay == -1)
return DEFAULT_VSTREAM_DELAY;
return cur_delay;
}
EXPORT_SYMBOL(tsync_pcr_vstream_delayed);
u32 tsync_pcr_get_min_checkinpts(void)
{
u32 last_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
u32 last_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
if (last_checkin_vpts > 0 && last_checkin_apts > 0)
return min(last_checkin_vpts, last_checkin_apts);
else if (last_checkin_apts > 0)
return last_checkin_apts;
else if (last_checkin_vpts > 0)
return last_checkin_vpts;
else
return 0;
}
EXPORT_SYMBOL(tsync_pcr_get_min_checkinpts);
void tsync_pcr_pcrscr_set(void)
{
u32 first_pcr = 0, first_vpts = 0, first_apts = 0;
u32 cur_checkin_apts = 0, cur_checkin_vpts = 0, min_checkinpts = 0;
u32 cur_pcr = 0, ref_pcr = 0;
u8 complete_init_flag =
TSYNC_PCR_INITCHECK_PCR | TSYNC_PCR_INITCHECK_VPTS |
TSYNC_PCR_INITCHECK_APTS;
if (tsync_pcr_inited_flag & complete_init_flag) {
return;
}
if (tsdemux_first_pcrscr_get_cb)
first_pcr = tsdemux_first_pcrscr_get_cb();
first_apts = timestamp_firstapts_get();
first_vpts = timestamp_firstvpts_get();
cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
min_checkinpts = tsync_pcr_get_min_checkinpts();
if (tsdemux_pcrscr_get_cb)
cur_pcr = tsdemux_pcrscr_get_cb();
abuf_level = get_stream_buffer_level(1);
vbuf_level = get_stream_buffer_level(0);
if (tsdemux_pcrvideo_valid_cb &&
tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb()) {
if (cur_checkin_apts == 0xffffffff)
return;
} else {
if (tsync_pcr_debug&0x01)
pr_info("now and the cur_checkin_apts is %x\n ",
cur_checkin_apts);
}
/* check the valid of the pcr */
if (cur_pcr && cur_checkin_vpts && cur_checkin_apts) {
u32 gap_pa, gap_pv, gap_av;
gap_pa = abs(cur_pcr - cur_checkin_apts);
gap_av = abs(cur_checkin_apts - cur_checkin_vpts);
gap_pv = abs(cur_pcr - cur_checkin_vpts);
if ((gap_pa > MAX_GAP) && (gap_pv > MAX_GAP))
cur_pcr = 0;
}
/* decide use which para to init */
if (cur_pcr && !(tsync_pcr_inited_flag & complete_init_flag)
&& (min_checkinpts != 0)) {
tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_PCR;
if (abs(cur_pcr - min_checkinpts) >
PLAY_PCR_INVALID_THRESHOLD) {
ref_pcr = min_checkinpts;
timestamp_pcrscr_set(ref_pcr);
tsync_use_demux_pcr = 0;
if (tsync_pcr_debug&0x01) {
pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ",
first_pcr, first_apts);
pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ",
first_vpts, cur_pcr, cur_checkin_vpts);
pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n",
cur_checkin_apts, abuf_level, vbuf_level);
pr_info("[%d]init by pcr. pcr=%x usepcr=%d\n",
__LINE__, ref_pcr, tsync_pcr_usepcr);
}
} else {
ref_pcr = timestamp_pcrscr_get();
tsync_use_demux_pcr = 1;
if ((tsync_pcr_debug&0x01) && tsdemux_pcrscr_get_cb) {
pr_info("use the pcr from stream , the cur demux pcr is %x\n",
tsdemux_pcrscr_get_cb());
pr_info("the timestamp pcr is %x\n",
timestamp_pcrscr_get());
pr_info("the timestamp video pts is %x\n",
timestamp_firstvpts_get());
}
}
init_check_first_systemtime = ref_pcr;
if (tsdemux_pcrscr_get_cb)
init_check_first_demuxpcr = tsdemux_pcrscr_get_cb();
}
if (first_apts && !(tsync_pcr_inited_flag & complete_init_flag)
&& (min_checkinpts != 0)) {
tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_APTS;
ref_pcr = first_apts;
if (abs(cur_pcr - first_apts) > PLAY_PCR_INVALID_THRESHOLD) {
ref_pcr = first_apts;
timestamp_pcrscr_set(ref_pcr);
tsync_use_demux_pcr = 0;
if (tsync_pcr_debug&0x01) {
pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ",
first_pcr, first_apts);
pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ",
first_vpts, cur_pcr, cur_checkin_vpts);
pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n",
cur_checkin_apts, abuf_level, vbuf_level);
pr_info("[%d]init by pcr. pcr=%x usepcr=%d\n",
__LINE__, ref_pcr, tsync_pcr_usepcr);
}
} else {
tsync_use_demux_pcr = 1;
ref_pcr = timestamp_pcrscr_get();
if ((tsync_pcr_debug & 0x01) && tsdemux_pcrscr_get_cb) {
pr_info("use the pcr from stream , the cur demux pcr is %x\n",
tsdemux_pcrscr_get_cb());
pr_info("the timestamp pcr is %x\n",
timestamp_pcrscr_get());
pr_info("the timestamp video pts is %x\n",
timestamp_firstvpts_get());
}
}
init_check_first_systemtime = ref_pcr;
if (tsdemux_pcrscr_get_cb)
init_check_first_demuxpcr = tsdemux_pcrscr_get_cb();
}
if (first_vpts && !(tsync_pcr_inited_flag & complete_init_flag)
&& (min_checkinpts != 0)) {
tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS;
if (abs(cur_pcr - first_vpts) > PLAY_PCR_INVALID_THRESHOLD) {
ref_pcr = min_checkinpts;
timestamp_pcrscr_set(ref_pcr);
tsync_use_demux_pcr = 0;
if (tsync_pcr_debug&0x01) {
pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ",
first_pcr, first_apts);
pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ",
first_vpts, cur_pcr, cur_checkin_vpts);
pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n",
cur_checkin_apts, abuf_level, vbuf_level);
pr_info("[%d]init by pcr. pcr=%x usepcr=%d\n",
__LINE__, ref_pcr, tsync_pcr_usepcr);
}
} else {
ref_pcr = timestamp_pcrscr_get();
tsync_use_demux_pcr = 1;
if ((tsync_pcr_debug&0x01) && tsdemux_pcrscr_get_cb) {
pr_info("use the pcr from stream , the cur demux pcr is %x\n",
tsdemux_pcrscr_get_cb());
pr_info("the timestamp pcr is %x\n",
timestamp_pcrscr_get());
pr_info("the timestamp video pts is %x\n",
timestamp_firstvpts_get());
}
}
}
}
static int speed_check_count;
static int normal_count;
static u8 tsync_process_checkspeed(void)
{
u32 demuxpcr_diff = 0;
u32 jiffies_diff = 0;
u32 cur_jiffiestime = 0;
u32 cur_demuxpcr = 0;
u32 checkin_apts = 0;
u32 checkin_vpts = 0;
u32 checkout_vpts = 0;
u32 checkout_apts = 0;
if (tsync_pcr_first_jiffes == 0)
return tsync_last_play_mode;
cur_jiffiestime = jiffies_to_msecs(jiffies);
if (tsdemux_pcrscr_get_cb)
cur_demuxpcr = tsdemux_pcrscr_get_cb();
if (timestamp_pcrscr_enable_state() == 0)
return PLAY_MODE_NORMAL;
jiffies_diff = cur_jiffiestime - tsync_pcr_first_jiffes;
demuxpcr_diff = cur_demuxpcr - init_check_first_demuxpcr;
demuxpcr_diff = demuxpcr_diff / 90;
if (demuxpcr_diff > jiffies_diff) {
u32 diff_delta = demuxpcr_diff - jiffies_diff;
if (diff_delta > PLAY_MODE_THRESHOLD) {
tsync_last_play_mode = PLAY_MODE_SPEED;
if (tsync_pcr_debug&0x01) {
pr_info("pcr_diff %x ", demuxpcr_diff);
pr_info("jiffies_diff %x ", jiffies_diff);
pr_info("normal_count %d\n", normal_count);
}
} else {
tsync_last_play_mode = PLAY_MODE_NORMAL;
}
} else if (demuxpcr_diff < jiffies_diff) {
u32 diff_delta = jiffies_diff - demuxpcr_diff;
if (diff_delta > PLAY_MODE_THRESHOLD) {
tsync_last_play_mode = PLAY_MODE_SLOW;
if (tsync_pcr_debug&0x01) {
pr_info("pcr_diff %x ", demuxpcr_diff);
pr_info("jiffies_diff %x ", jiffies_diff);
pr_info("normal_count %d\n", normal_count);
}
} else {
tsync_last_play_mode = PLAY_MODE_NORMAL;
}
} else {
tsync_last_play_mode = PLAY_MODE_NORMAL;
}
{
checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
checkout_vpts = timestamp_vpts_get();
checkout_apts = timestamp_apts_get();
if (checkin_apts > checkout_apts) {
if ((checkin_apts - checkout_apts) >
(PLAY_MODE_THRESHOLD * 90)) {
tsync_last_play_mode = PLAY_MODE_SPEED;
if (tsync_pcr_debug&0x01)
pr_info(" audio cache time %d normal_count %d\n",
(checkin_apts - checkout_apts),
normal_count);
} else {
tsync_last_play_mode = PLAY_MODE_NORMAL;
}
}
if (checkin_vpts > checkout_vpts) {
if ((checkin_vpts - checkout_vpts) >
(PLAY_MODE_THRESHOLD * 90)) {
tsync_last_play_mode = PLAY_MODE_SPEED;
if (tsync_pcr_debug&0x01)
pr_info(" video cached time %d normal_count %d\n",
(checkin_vpts - checkout_vpts),
normal_count);
} else {
tsync_last_play_mode = PLAY_MODE_NORMAL;
}
}
}
if (tsync_last_play_mode == PLAY_MODE_NORMAL)
normal_count++;
return tsync_last_play_mode;
}
static void tsync_process_discontinue(void)
{
u32 cur_apts = timestamp_apts_get();
u32 cur_vpts = timestamp_vpts_get();
if (tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb() &&
tsdemux_pcrvideo_valid_cb && tsdemux_pcrvideo_valid_cb()) {
/*set pcr after discontinue according to apts and vpts */
if ((tsync_pcr_tsdemuxpcr_discontinue &
(AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) ==
(AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) {
tsync_pcr_tsdemuxpcr_discontinue = 0;
tsync_pcr_reset_flag = 1;
if (tsync_pcr_debug&0x02) {
pr_info(" now audio &video discontinue,need replay now\n");
}
}
} else if (tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb()) {
if ((tsync_pcr_tsdemuxpcr_discontinue &
AUDIO_DISCONTINUE) ==
AUDIO_DISCONTINUE) {
if (tsync_pcr_debug&0x02) {
pr_info(" now audio discontinue\n");
tsync_pcr_tsdemuxpcr_discontinue = 0;
pr_info("after discontinue, pcr = 0x%x,apts=0x%x\n",
timestamp_pcrscr_get(), cur_apts);
}
timestamp_pcrscr_set(cur_apts);
}
} else {
if ((tsync_pcr_tsdemuxpcr_discontinue & VIDEO_DISCONTINUE) ==
VIDEO_DISCONTINUE) {
if (tsync_pcr_debug&0x02)
pr_info(" now video discontinue\n");
tsync_pcr_tsdemuxpcr_discontinue = 0;
pr_info("after discontinue, pcr = 0x%x,vpts=0x%x\n",
timestamp_pcrscr_get(), cur_vpts);
}
timestamp_pcrscr_set(cur_vpts);
}
}
static u32 last_pcr_checkin_apts;
static u32 last_pcr_checkin_vpts;
static u32 last_pcr_checkin_apts_count;
static u32 last_pcr_checkin_vpts_count;
void tsync_pcr_check_checinpts(void)
{
u32 checkin_vpts = 0;
u32 checkin_apts = 0;
checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
if (tsync_pcr_vstart_flag == 0 && tsync_pcr_astart_flag == 0)
return;
if (checkin_vpts == 0xffffffff)
return;
if (checkin_apts == 0xffffffff)
return;
if (last_pcr_checkin_apts == 0 || last_pcr_checkin_vpts == 0) {
last_pcr_checkin_apts = checkin_apts;
last_pcr_checkin_vpts = checkin_vpts;
return;
}
if (last_pcr_checkin_apts > checkin_apts)
tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE;
if (abs(last_pcr_checkin_vpts - checkin_vpts) > 2 * 90000)
tsync_pcr_tsdemuxpcr_discontinue |= VIDEO_DISCONTINUE;
if (last_pcr_checkin_apts == checkin_apts) {
last_pcr_checkin_apts_count++;
if (last_pcr_checkin_apts_count > 100)
tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE;
} else {
last_pcr_checkin_apts = checkin_apts;
last_pcr_checkin_apts_count = 0;
}
if (last_pcr_checkin_vpts == checkin_vpts) {
last_pcr_checkin_vpts_count++;
if (last_pcr_checkin_vpts_count > 100)
tsync_pcr_tsdemuxpcr_discontinue |= VIDEO_DISCONTINUE;
} else {
last_pcr_checkin_vpts = checkin_vpts;
last_pcr_checkin_vpts_count = 0;
}
}
EXPORT_SYMBOL(tsync_pcr_pcrscr_set);
void tsync_pcr_avevent_locked(enum avevent_e event, u32 param)
{
ulong flags;
spin_lock_irqsave(&tsync_pcr_lock, flags);
switch (event) {
case VIDEO_START:
if (tsync_pcr_vstart_flag == 0) {
/* play_mode=PLAY_MODE_NORMAL; */
tsync_pcr_first_video_frame_pts = param;
pr_info("video start! param=%x cur_pcr=%x\n", param,
timestamp_pcrscr_get());
}
/*tsync_pcr_inited_mode = INIT_MODE_VIDEO;*/
tsync_pcr_pcrscr_set();
tsync_pcr_vstart_flag = 1;
break;
case VIDEO_STOP:
timestamp_pcrscr_enable(0);
pr_info("timestamp_firstvpts_set !\n");
timestamp_firstvpts_set(0);
timestamp_firstapts_set(0);
timestamp_vpts_set(0);
/* tsync_pcr_debug_pcrscr=100; */
tsync_pcr_vpause_flag = 0;
tsync_pcr_vstart_flag = 0;
tsync_pcr_inited_flag = 0;
wait_pcr_count = 0;
pr_info("wait_pcr_count = 0\n");
tsync_pcr_tsdemuxpcr_discontinue = 0;
tsync_pcr_discontinue_point = 0;
tsync_pcr_discontinue_local_point = 0;
tsync_pcr_discontinue_waited = 0;
tsync_pcr_first_video_frame_pts = 0;
tsync_pcr_tsdemux_startpcr = 0;
play_mode = PLAY_MODE_NORMAL;
pr_info("video stop!\n");
break;
case VIDEO_TSTAMP_DISCONTINUITY:{
/* unsigned oldpts=timestamp_vpts_get(); */
if (!get_vsync_pts_inc_mode()) {
tsync_pcr_tsdemuxpcr_discontinue |=
VIDEO_DISCONTINUE;
timestamp_pcrscr_enable(0);
tsync_process_discontinue();
}
timestamp_vpts_set(param);
break;
}
case AUDIO_TSTAMP_DISCONTINUITY:{
tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE;
timestamp_apts_set(param);
tsync_process_discontinue();
}
break;
case AUDIO_PRE_START:
timestamp_apts_start(0);
tsync_pcr_astart_flag = 0;
pr_info("audio prestart!\n");
break;
case AUDIO_START:
timestamp_apts_set(param);
timestamp_apts_enable(1);
timestamp_apts_start(1);
tsync_pcr_first_audio_frame_pts = param;
tsync_pcr_astart_flag = 1;
tsync_pcr_apause_flag = 0;
pr_info("audio start!timestamp_apts_set =%x. cur_pcr %x\n",
param, timestamp_pcrscr_get());
break;
case AUDIO_RESUME:
timestamp_apts_enable(1);
tsync_pcr_apause_flag = 0;
pr_info("audio resume!\n");
break;
case AUDIO_STOP:
timestamp_apts_enable(0);
timestamp_apts_set(-1);
timestamp_firstapts_set(0);
timestamp_apts_start(0);
tsync_pcr_astart_flag = 0;
tsync_pcr_apause_flag = 0;
tsync_pcr_first_audio_frame_pts = 0;
pr_info("audio stop!\n");
break;
case AUDIO_PAUSE:
timestamp_apts_enable(0);
tsync_pcr_apause_flag = 1;
pr_info("audio pause!\n");
break;
case VIDEO_PAUSE:
if (param == 1) {
timestamp_pcrscr_enable(0);
tsync_pcr_vpause_flag = 1;
pr_info("video pause!\n");
} else {
timestamp_pcrscr_enable(1);
tsync_pcr_vpause_flag = 0;
pr_info("video resume\n");
}
break;
default:
break;
}
switch (event) {
case VIDEO_START:
case AUDIO_START:
case AUDIO_RESUME:
/*amvdev_resume();*//*DEBUG_TMP*/
break;
case VIDEO_STOP:
case AUDIO_STOP:
case AUDIO_PAUSE:
/*amvdev_pause();*//*DEBUG_TMP*/
break;
case VIDEO_PAUSE:
/*if (tsync_pcr_vpause_flag)*/
/*amvdev_pause();*//*DEBUG_TMP*/
/*else*/
/*amvdev_resume();*//*DEBUG_TMP*/
break;
default:
break;
}
spin_unlock_irqrestore(&tsync_pcr_lock, flags);
}
EXPORT_SYMBOL(tsync_pcr_avevent_locked);
/* timer to check the system with the referrence time in ts stream. */
static unsigned long tsync_pcr_check(void)
{
u32 tsdemux_pcr = 0;
u32 tsdemux_pcr_diff = 0;
int need_recovery = 1;
unsigned long res = 1;
int64_t last_checkin_vpts = 0;
int64_t last_checkin_apts = 0;
int64_t last_cur_pcr = 0;
int64_t last_checkin_minpts = 0;
u32 cur_apts = 0;
u32 cur_vpts = 0;
if (tsync_get_mode() != TSYNC_MODE_PCRMASTER
|| tsync_pcr_freerun_mode == 1)
return res;
if (tsync_pcr_first_jiffes != 0) {
tsync_pcr_jiffes_diff = jiffies_to_msecs(jiffies)
- tsync_pcr_first_jiffes;
if (tsdemux_pcrscr_get_cb)
tysnc_pcr_systime_diff =
tsdemux_pcrscr_get_cb()-tsync_pcr_first_systime;
}
tsync_pcr_check_checinpts();
if (tsdemux_pcrscr_get_cb)
tsdemux_pcr = tsdemux_pcrscr_get_cb();
if (tsync_pcr_usepcr == 1) {
/* To monitor the pcr discontinue */
tsdemux_pcr_diff = abs(tsdemux_pcr - tsync_pcr_last_tsdemuxpcr);
if (tsync_pcr_last_tsdemuxpcr != 0 && tsdemux_pcr != 0
&& tsdemux_pcr_diff > tsync_pcr_discontinue_threshold
&& tsync_pcr_inited_flag >= TSYNC_PCR_INITCHECK_PCR) {
u32 video_delayed = 0;
tsync_pcr_tsdemuxpcr_discontinue |= PCR_DISCONTINUE;
video_delayed = tsync_pcr_vstream_delayed();
if (TIME_UNIT90K * 2 <= video_delayed
&& video_delayed <= TIME_UNIT90K * 4) {
tsync_pcr_discontinue_waited =
video_delayed + TIME_UNIT90K;
} else if (TIME_UNIT90K * 2 > video_delayed)
tsync_pcr_discontinue_waited = TIME_UNIT90K * 3;
else
tsync_pcr_discontinue_waited = TIME_UNIT90K * 5;
if (tsync_pcr_debug&0x02) {
pr_info("[tsync_pcr_check] refpcr_discontinue.\n");
pr_info("tsdemux_pcr_diff=%x, last refpcr=%x,\n",
tsdemux_pcr_diff,
tsync_pcr_last_tsdemuxpcr);
pr_info("repcr=%x,waited=%x\n",
tsdemux_pcr,
tsync_pcr_discontinue_waited);
pr_info("last checkin vpts:%d\n",
(u32)get_last_checkin_pts(PTS_TYPE_VIDEO));
pr_info("last checkin apts:%d\n",
(u32)get_last_checkin_pts(PTS_TYPE_AUDIO));
}
tsync_pcr_discontinue_local_point =
timestamp_pcrscr_get();
tsync_pcr_discontinue_point =
tsdemux_pcr - tsync_pcr_ref_latency;
need_recovery = 0;
} else if (tsync_pcr_tsdemuxpcr_discontinue & PCR_DISCONTINUE) {
/* to pause the pcr check */
if ((abs
(timestamp_pcrscr_get()
- tsync_pcr_discontinue_local_point))
> tsync_pcr_discontinue_waited){
if (tsync_pcr_debug & 0x02) {
u32 temp = 0;
temp =
tsync_pcr_discontinue_local_point;
pr_info(
"[tsync_pcr_check] audio or video");
pr_info(
"discontinue didn't happen, waited=%x\n",
tsync_pcr_discontinue_waited);
pr_info(
" timestamp_pcrscr_get() =%x\n",
timestamp_pcrscr_get());
pr_info(
"tsync_pcr_discontinue_local_point =%x\n",
temp);
}
/* the v-discontinue did'n happen */
tsync_pcr_tsdemuxpcr_discontinue = 0;
tsync_pcr_discontinue_point = 0;
tsync_pcr_discontinue_local_point = 0;
tsync_pcr_discontinue_waited = 0;
}
need_recovery = 0;
}
tsync_pcr_last_tsdemuxpcr = tsdemux_pcr;
}
if ((!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_VPTS))
&& (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_PCR))
&& (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_APTS))) {
u64 cur_system_time = (jiffies * TIME_UNIT90K) / HZ;
if (cur_system_time - first_time_record < 270000) {
} else {
tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO;
tsync_pcr_pcrscr_set();
}
return res;
}
abuf_level = get_stream_buffer_level(1);
abuf_size = get_stream_buffer_size(1);
vbuf_level = get_stream_buffer_level(0);
vbuf_size = get_stream_buffer_size(0);
/*
**********************************************************
* On S905/S905X Platform, when we play avs video file on dtv
*which contian long cabac some time it will cause amstream
*video buffer enter an error status. vbuf_level will over vbuf_size,
*this will cause a lot of print in this function. And that will
*prevent reset ts monitor work thread from getting cpu control
*and to reset ts module. So we add the following code to avoid
*this case.
*
* Rong.Zhang@amlogic.com 2016-08-10
**********************************************************
*/
if (abuf_level > abuf_size) {
if (!abuf_fatal_error) {
abuf_fatal_error = 1;
}
return res;
}
if (vbuf_level > vbuf_size) {
if (!vbuf_fatal_error) {
vbuf_fatal_error = 1;
}
return res;
}
last_checkin_vpts = (u32) get_last_checkin_pts(PTS_TYPE_VIDEO);
last_checkin_apts = (u32) get_last_checkin_pts(PTS_TYPE_AUDIO);
last_cur_pcr = timestamp_pcrscr_get();
last_checkin_minpts = tsync_pcr_get_min_checkinpts();
cur_apts = timestamp_apts_get();
cur_vpts = timestamp_vpts_get();
tsync_process_discontinue();
play_mode = tsync_process_checkspeed();
return res;
}
static void tsync_pcr_check_timer_func(unsigned long arg)
{
ulong flags;
spin_lock_irqsave(&tsync_pcr_lock, flags);
tsync_pcr_check();
spin_unlock_irqrestore(&tsync_pcr_lock, flags);
tsync_pcr_check_timer.expires = jiffies + TEN_MS_INTERVAL;
add_timer(&tsync_pcr_check_timer);
}
static void tsync_pcr_param_reset(void)
{
tsync_pcr_tsdemux_startpcr = 0;
tsync_pcr_vpause_flag = 0;
tsync_pcr_apause_flag = 0;
tsync_pcr_vstart_flag = 0;
tsync_pcr_astart_flag = 0;
tsync_pcr_inited_flag = 0;
wait_pcr_count = 0;
tsync_pcr_reset_flag = 0;
tsync_pcr_asynccheck_cnt = 0;
tsync_pcr_vsynccheck_cnt = 0;
pr_info("wait_pcr_count = 0\n");
tsync_pcr_last_tsdemuxpcr = 0;
tsync_pcr_discontinue_local_point = 0;
tsync_pcr_discontinue_point = 0;
/* the time waited the v-discontinue to happen */
tsync_pcr_discontinue_waited = 0;
tsync_pcr_tsdemuxpcr_discontinue = 0; /* the boolean value */
abuf_level = 0;
abuf_size = 0;
vbuf_level = 0;
vbuf_size = 0;
play_mode = PLAY_MODE_NORMAL;
tsync_pcr_started = 0;
/*tsync_pcr_inited_mode = INIT_MODE_VIDEO; */
tsync_pcr_stream_delta = 0;
last_pcr_checkin_apts = 0;
last_pcr_checkin_vpts = 0;
last_pcr_checkin_apts_count = 0;
last_pcr_checkin_vpts_count = 0;
tsync_last_play_mode = PLAY_MODE_NORMAL;
tsync_pcr_first_jiffes = 0;
tsync_pcr_first_systime = 0;
speed_check_count = 0;
}
int tsync_pcr_set_apts(unsigned int pts)
{
timestamp_apts_set(pts);
/* pr_info("[tsync_pcr_set_apts]set apts=%x",pts); */
return 0;
}
EXPORT_SYMBOL(tsync_pcr_set_apts);
int tsync_pcr_start(void)
{
timestamp_pcrscr_enable(0);
timestamp_pcrscr_set(0);
tsync_pcr_param_reset();
if (tsync_get_mode() == TSYNC_MODE_PCRMASTER) {
pr_info("[tsync_pcr_start]PCRMASTER started success.\n");
init_timer(&tsync_pcr_check_timer);
tsync_pcr_check_timer.function = tsync_pcr_check_timer_func;
tsync_pcr_check_timer.expires = jiffies;
first_time_record = (jiffies * TIME_UNIT90K) / HZ;
tsync_pcr_started = 1;
if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 0) {
tsync_use_demux_pcr = 0;
tsync_pcr_inited_mode = INIT_PRIORITY_AUDIO;
} else {
tsync_use_demux_pcr = 1;
tsync_pcr_inited_mode = INIT_PRIORITY_PCR;
}
tsync_pcr_read_cnt = 0;
pr_info("[tsync_pcr_start]usepcr=%d tsync_pcr_inited_mode=%d\n",
tsync_pcr_usepcr, tsync_pcr_inited_mode);
add_timer(&tsync_pcr_check_timer);
}
abuf_fatal_error = 0;
vbuf_fatal_error = 0;
return 0;
}
EXPORT_SYMBOL(tsync_pcr_start);
int tsync_pcr_demux_pcr_used(void)
{
return tsync_use_demux_pcr;
}
EXPORT_SYMBOL(tsync_pcr_demux_pcr_used);
void tsync_pcr_stop(void)
{
if (tsync_pcr_started == 1) {
del_timer_sync(&tsync_pcr_check_timer);
pr_info("[tsync_pcr_stop]PCRMASTER stop success.\n");
}
tsync_pcr_freerun_mode = 0;
tsync_pcr_started = 0;
}
EXPORT_SYMBOL(tsync_pcr_stop);
/* ------------------------------------------------------------------------ */
/* define of tsync pcr class node */
static ssize_t show_play_mode(struct class *class,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", play_mode);
}
static ssize_t pcr_diff_show(struct class *class,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d %d %d %s\n", tsync_pcr_jiffes_diff * 90,
tysnc_pcr_systime_diff,
tsync_pcr_jiffes_diff - tysnc_pcr_systime_diff / 90,
"ms");
}
static ssize_t show_tsync_pcr_dispoint(struct class *class,
struct class_attribute *attr, char *buf)
{
pr_info("[%s:%d] tsync_pcr_discontinue_point:%x, HZ:%x,\n",
__func__, __LINE__, tsync_pcr_discontinue_point, HZ);
return sprintf(buf, "0x%x\n", tsync_pcr_discontinue_point);
}
static ssize_t store_tsync_pcr_dispoint(struct class *class,
struct class_attribute *attr,
const char *buf, size_t size)
{
unsigned int pts;
ssize_t r;
/*r = sscanf(buf, "0x%x", &pts);*/
r = kstrtoint(buf, 0, &pts);
if (r != 0)
return -EINVAL;
tsync_pcr_discontinue_point = pts;
pr_info("[%s:%d] tsync_pcr_discontinue_point:%x,\n", __func__,
__LINE__, tsync_pcr_discontinue_point);
return size;
}
static ssize_t store_tsync_pcr_audio_resample_type(struct class *class,
struct class_attribute *attr,
const char *buf, size_t size)
{
unsigned int type;
ssize_t r;
/*r = sscanf(buf, "%d", &type);*/
r = kstrtoint(buf, 0, &type);
if (r != 0)
return -EINVAL;
if (type == RESAMPLE_DOWN_FORCE_PCR_SLOW) {
play_mode = PLAY_MODE_SLOW;
pr_info("[%s:%d] Audio to FORCE_PCR_SLOW\n", __func__,
__LINE__);
}
return size;
}
static ssize_t tsync_pcr_freerun_mode_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", tsync_pcr_freerun_mode);
}
static ssize_t tsync_pcr_freerun_mode_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
size_t r;
/*r = sscanf(buf, "%d", &tsync_pcr_freerun_mode);*/
r = kstrtoint(buf, 0, &tsync_pcr_freerun_mode);
pr_info("%s(%d)\n", __func__, tsync_pcr_freerun_mode);
if (r != 0)
return -EINVAL;
return count;
}
static ssize_t show_reset_flag(struct class *class,
struct class_attribute *attr, char *buf)
{
ssize_t size = 0;
size = sprintf(buf, "%d\n", tsync_pcr_reset_flag);
tsync_pcr_reset_flag = 0;
return size;
}
static ssize_t show_apause_flag(struct class *class,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", tsync_pcr_apause_flag);
}
static ssize_t tsync_pcr_recovery_span_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", tsync_pcr_recovery_span);
}
static ssize_t tsync_pcr_recovery_span_store(struct class *cla,
struct class_attribute *attr, const char *buf, size_t count)
{
size_t r;
/*r = sscanf(buf, "%d", &tsync_pcr_recovery_span);*/
r = kstrtoint(buf, 0, &tsync_pcr_recovery_span);
pr_info("%s(%d)\n", __func__, tsync_pcr_recovery_span);
if (r != 0)
return -EINVAL;
return count;
}
/* add it for dolby av sync 20160126 */
static ssize_t tsync_apts_adj_value_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", tsync_apts_adj_value);
}
static ssize_t tsync_apts_adj_value_store(struct class *cla,
struct class_attribute *attr, const char *buf, size_t count)
{
size_t r;
/*r = sscanf(buf, "%d", &tsync_apts_adj_value);*/
r = kstrtoint(buf, 0, &tsync_apts_adj_value);
pr_info("%s(%d)\n", __func__, tsync_apts_adj_value);
if (r != 0)
return -EINVAL;
return count;
}
static ssize_t tsync_pcr_adj_value_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", tsync_pcr_adj_value);
}
static ssize_t tsync_pcr_adj_value_store(struct class *cla,
struct class_attribute *attr, const char *buf, size_t count)
{
size_t r;
/*r = sscanf(buf, "%d", &tsync_pcr_adj_value);*/
r = kstrtoint(buf, 0, &tsync_pcr_adj_value);
pr_info("%s(%d)\n", __func__, tsync_pcr_adj_value);
if (r != 0)
return -EINVAL;
return count;
}
static ssize_t tsync_pcr_discontinue_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "0x%x\n", tsync_pcr_tsdemuxpcr_discontinue);
}
static ssize_t tsync_pcr_debug_store(struct class *cla,
struct class_attribute *attr,
const char *buf, size_t count)
{
size_t r;
/*r = sscanf(buf, "%d", &tsync_pcr_debug);*/
r = kstrtoint(buf, 0, &tsync_pcr_debug);
pr_info("%s(%d)\n", __func__, tsync_pcr_debug);
if (r != 0)
return -EINVAL;
return count;
}
static ssize_t tsync_pcr_debug_show(struct class *cla,
struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", tsync_pcr_debug);
}
static ssize_t show_vstream_cache(struct class *class,
struct class_attribute *attr, char *buf)
{
unsigned int cur_vpts = timestamp_vpts_get();
unsigned int last_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
unsigned int diff = 0;
if (last_checkin_vpts > cur_vpts)
diff = last_checkin_vpts - cur_vpts;
else
diff = cur_vpts - last_checkin_vpts;
return sprintf(buf, "%d\n", diff);
}
static ssize_t show_astream_cache(struct class *class,
struct class_attribute *attr, char *buf)
{
unsigned int cur_apts = timestamp_apts_get();
unsigned int last_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO);
unsigned int diff = 0;
if (last_checkin_apts > cur_apts)
diff = last_checkin_apts - cur_apts;
else
diff = cur_apts - last_checkin_apts;
return sprintf(buf, "%d\n", diff);
}
/* ----------------------------------------------------------------------- */
/* define of tsync pcr module */
static struct class_attribute tsync_pcr_class_attrs[] = {
__ATTR(play_mode, 0664, show_play_mode, NULL),
__ATTR(tsync_pcr_discontinue_point, 0644,
show_tsync_pcr_dispoint, store_tsync_pcr_dispoint),
__ATTR(audio_resample_type, 0644, NULL,
store_tsync_pcr_audio_resample_type),
__ATTR(tsync_pcr_freerun_mode, 0644,
tsync_pcr_freerun_mode_show, tsync_pcr_freerun_mode_store),
__ATTR(tsync_pcr_reset_flag, 0664,
show_reset_flag, NULL),
__ATTR(tsync_pcr_apause_flag, 0664,
show_apause_flag, NULL),
__ATTR(tsync_pcr_recovery_span, 0644,
tsync_pcr_recovery_span_show, tsync_pcr_recovery_span_store),
__ATTR(tsync_apts_adj_value, 0644,
tsync_apts_adj_value_show, tsync_apts_adj_value_store),
__ATTR(tsync_pcr_adj_value, 0644,
tsync_pcr_adj_value_show, tsync_pcr_adj_value_store),
__ATTR(tsync_pcr_debug, 0644,
tsync_pcr_debug_show, tsync_pcr_debug_store),
__ATTR_RO(tsync_pcr_discontinue),
__ATTR_RO(pcr_diff),
__ATTR(tsync_vstream_cache, 0644,
show_vstream_cache, NULL),
__ATTR(tsync_astream_cache, 0644,
show_astream_cache, NULL),
__ATTR_NULL};
static struct class tsync_pcr_class = {
.name = "tsync_pcr",
.class_attrs = tsync_pcr_class_attrs,
};
int tsync_pcr_init(void)
{
int r;
r = class_register(&tsync_pcr_class);
if (r) {
pr_info("[tsync_pcr_init]tsync_pcr_class create fail.\n");
return r;
}
/* init audio pts to -1, others to 0 */
timestamp_apts_set(-1);
timestamp_vpts_set(0);
timestamp_pcrscr_set(0);
wait_pcr_count = 0;
tsync_pcr_debug = 0;
pr_info("[tsync_pcr_init]init success.\n");
return 0;
}
EXPORT_SYMBOL(tsync_pcr_init);
void tsync_pcr_exit(void)
{
class_unregister(&tsync_pcr_class);
pr_info("[tsync_pcr_exit]exit success.\n");
}
EXPORT_SYMBOL(tsync_pcr_exit);
/*
*module_init(tsync_pcr_init);
*module_exit(tsync_pcr_exit);
*
*MODULE_DESCRIPTION
*("AMLOGIC time sync management driver of referrence by pcrscr");
*MODULE_LICENSE("GPL");
*MODULE_AUTHOR("le yang <le.yang@amlogic.com>");
*/