blob: c16f42f87adbc9097bd22e2b20c3fa148b3fee49 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#define DEBUG
#include <linux/module.h>
#include <linux/amlogic/media/frame_sync/tsync.h>
#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
#include <linux/amlogic/media/registers/register.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#ifdef CONFIG_AMLOGIC_DEBUG_ATRACE
#include <trace/events/meson_atrace.h>
#endif
u32 acc_apts_inc;
u32 acc_apts_dec;
u32 acc_pcrscr_inc;
u32 acc_pcrscr_dec;
static s32 system_time_inc_adj;
static u32 system_time;
static u32 system_time_up;
static u32 audio_pts_up;
static u32 audio_pts_started;
static u32 first_vpts;
static u32 first_checkin_vpts;
static u32 first_checkin_apts;
static u32 first_apts;
static u32 pcrscr_lantcy = 200*90;
static u32 video_pts;
static u32 audio_pts;
static u32 system_time_scale_base = 1;
static u32 system_time_scale_remainder;
#ifdef MODIFY_TIMESTAMP_INC_WITH_PLL
#define PLL_FACTOR 10000
static u32 timestamp_inc_factor = PLL_FACTOR;
void set_timestamp_inc_factor(u32 factor)
{
timestamp_inc_factor = factor;
}
#endif
#ifndef CONFIG_AMLOGIC_DEBUG_ATRACE
static void ATRACE_COUNTER(const char *name, int val) { }
#endif
u32 timestamp_vpts_get(void)
{
return video_pts;
}
EXPORT_SYMBOL(timestamp_vpts_get);
void timestamp_vpts_set(u32 pts)
{
video_pts = pts;
}
EXPORT_SYMBOL(timestamp_vpts_set);
void timestamp_vpts_inc(s32 val)
{
video_pts += val;
}
EXPORT_SYMBOL(timestamp_vpts_inc);
u32 timestamp_apts_get(void)
{
return audio_pts;
}
EXPORT_SYMBOL(timestamp_apts_get);
void timestamp_apts_set(u32 pts)
{
audio_pts = pts;
}
EXPORT_SYMBOL(timestamp_apts_set);
void timestamp_apts_inc(s32 inc)
{
if (audio_pts_up) {
#ifdef MODIFY_TIMESTAMP_INC_WITH_PLL
inc = inc * timestamp_inc_factor / PLL_FACTOR;
#endif
audio_pts += inc;
}
}
EXPORT_SYMBOL(timestamp_apts_inc);
void timestamp_apts_enable(u32 enable)
{
audio_pts_up = enable;
pr_info("%s enable:%x,\n", __func__, enable);
}
EXPORT_SYMBOL(timestamp_apts_enable);
void timestamp_apts_start(u32 enable)
{
audio_pts_started = enable;
pr_info("audio pts started::::::: %d\n", enable);
}
EXPORT_SYMBOL(timestamp_apts_start);
u32 timestamp_apts_started(void)
{
return audio_pts_started;
}
EXPORT_SYMBOL(timestamp_apts_started);
u32 timestamp_pcrscr_get(void)
{
if (tsync_get_mode() == TSYNC_MODE_AMASTER)
return system_time;
if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb()) {
if (tsync_pcr_demux_pcr_used() == 0) {
return system_time;
}
else {
if (tsdemux_pcrscr_get_cb)
return tsdemux_pcrscr_get_cb()-pcrscr_lantcy;
else
return system_time;
}
} else
return system_time;
}
EXPORT_SYMBOL(timestamp_pcrscr_get);
u32 timestamp_get_pcrlatency(void)
{
return pcrscr_lantcy;
}
EXPORT_SYMBOL(timestamp_get_pcrlatency);
u32 timestamp_tsdemux_pcr_get(void)
{
if (tsdemux_pcrscr_get_cb)
return tsdemux_pcrscr_get_cb();
return (u32)-1;
}
EXPORT_SYMBOL(timestamp_tsdemux_pcr_get);
void timestamp_pcrscr_set(u32 pts)
{
/*pr_info("timestamp_pcrscr_set system time = %x\n", pts);*/
ATRACE_COUNTER("PCRSCR", pts);
system_time = pts;
}
EXPORT_SYMBOL(timestamp_pcrscr_set);
void timestamp_firstvpts_set(u32 pts)
{
first_vpts = pts;
pr_info("video first pts = %x\n", first_vpts);
}
EXPORT_SYMBOL(timestamp_firstvpts_set);
u32 timestamp_firstvpts_get(void)
{
return first_vpts;
}
EXPORT_SYMBOL(timestamp_firstvpts_get);
void timestamp_checkin_firstvpts_set(u32 pts)
{
first_checkin_vpts = pts;
pr_info("video first checkin pts = %x\n", first_checkin_vpts);
}
EXPORT_SYMBOL(timestamp_checkin_firstvpts_set);
void timestamp_checkin_firstapts_set(u32 pts)
{
first_checkin_apts = pts;
pr_info("audio first checkin pts =%x\n", first_checkin_apts);
}
EXPORT_SYMBOL(timestamp_checkin_firstapts_set);
u32 timestamp_checkin_firstvpts_get(void)
{
return first_checkin_vpts;
}
EXPORT_SYMBOL(timestamp_checkin_firstvpts_get);
u32 timestamp_checkin_firstapts_get(void)
{
return first_checkin_apts;
}
EXPORT_SYMBOL(timestamp_checkin_firstapts_get);
void timestamp_firstapts_set(u32 pts)
{
first_apts = pts;
pr_info("audio first pts = %x\n", first_apts);
}
EXPORT_SYMBOL(timestamp_firstapts_set);
u32 timestamp_firstapts_get(void)
{
return first_apts;
}
EXPORT_SYMBOL(timestamp_firstapts_get);
void timestamp_pcrscr_inc(s32 inc)
{
if (system_time_up) {
#ifdef MODIFY_TIMESTAMP_INC_WITH_PLL
inc = inc * timestamp_inc_factor / PLL_FACTOR;
#endif
system_time += inc + system_time_inc_adj;
ATRACE_COUNTER("PCRSCR", system_time);
}
}
EXPORT_SYMBOL(timestamp_pcrscr_inc);
void timestamp_pcrscr_inc_scale(s32 inc, u32 base)
{
if (system_time_scale_base != base) {
system_time_scale_remainder =
system_time_scale_remainder *
base / system_time_scale_base;
system_time_scale_base = base;
}
if (system_time_up) {
u32 r;
system_time +=
div_u64_rem(90000ULL * inc, base, &r) +
system_time_inc_adj;
system_time_scale_remainder += r;
if (system_time_scale_remainder >= system_time_scale_base) {
system_time++;
system_time_scale_remainder -= system_time_scale_base;
}
ATRACE_COUNTER("PCRSCR", system_time);
}
}
EXPORT_SYMBOL(timestamp_pcrscr_inc_scale);
void timestamp_pcrscr_set_adj(s32 inc)
{
system_time_inc_adj = inc;
}
EXPORT_SYMBOL(timestamp_pcrscr_set_adj);
void timestamp_pcrscr_set_adj_pcr(s32 inc)
{
const struct vinfo_s *info = get_current_vinfo();
if (inc != 0) {
system_time_inc_adj =
900 * info->sync_duration_den /
(info->sync_duration_num*inc);
} else
system_time_inc_adj = 0;
}
EXPORT_SYMBOL(timestamp_pcrscr_set_adj_pcr);
void timestamp_pcrscr_enable(u32 enable)
{
system_time_up = enable;
}
EXPORT_SYMBOL(timestamp_pcrscr_enable);
u32 timestamp_pcrscr_enable_state(void)
{
return system_time_up;
}
EXPORT_SYMBOL(timestamp_pcrscr_enable_state);
MODULE_DESCRIPTION("AMLOGIC time sync management driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");