AMLOGIC MESONGXL ADD P241 DTS
M: Lianghu Su <lianghu.su@amlogic.com>
F: arch/arm64/boot/dts/amlogic/gxl_p241_1g_buildroot.dts
+
+AMLOGIC tee
+M: Nanxin Qin <nanxin.qin@amlogic.com>
+F: drivers/amlogic/tee/*
+F: include/linux/amlogic/tee.h
CONFIG_AMLOGIC_IIO=y
CONFIG_AMLOGIC_SARADC=y
CONFIG_AMLOGIC_DDR_WINDOW_TOOL=m
+CONFIG_AMLOGIC_TEE=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
source "drivers/amlogic/secure_monitor/Kconfig"
+source "drivers/amlogic/tee/Kconfig"
endmenu
endif
obj-$(CONFIG_DRM_MESON) += drm/
obj-$(CONFIG_AMLOGIC_M8B_SM) += secure_monitor/
+
+obj-$(CONFIG_AMLOGIC_TEE) += tee/
if (!mem)
return;
- spin_lock_irqsave(&mem->lock, flags);
+ spin_lock_irqsave(&mgt->lock, flags);
index = atomic_dec_return(&mem->use_cnt);
max_owner = mem->owner[index];
for (i = 0; i < index; i++) {
mem->from_flags, index);
mem->owner[index] = NULL;
if (index == 0) {
- spin_unlock_irqrestore(&mem->lock, flags);
- codec_mm_free_in(mgt, mem);
list_del(&mem->list);
+ spin_unlock_irqrestore(&mgt->lock, flags);
+ codec_mm_free_in(mgt, mem);
kfree(mem);
return;
}
- spin_unlock_irqrestore(&mem->lock, flags);
+ spin_unlock_irqrestore(&mgt->lock, flags);
}
EXPORT_SYMBOL(codec_mm_release);
u32 enable_slot_from_sys;
u32 no_cache_size_M;
u32 support_from_slot_sys;
+ u32 no_alloc_from_sys;
};
struct codec_mm_scatter_mgt {
int alloc_from_cma_first;
u32 enable_slot_from_sys;
u32 no_cache_size_M;
+ u32 no_alloc_from_sys;
u32 support_from_slot_sys;
int one_page_cnt;
int scatters_cnt;
break; /*ignore codec_mm */
if ((try_alloc_size <= 0 ||
try_alloc_size > 64 * 1024) && /*must > 512K. */
- codec_mm_get_free_size() >
- smgt->reserved_block_mm_M * SZ_1M) {
+ (smgt->tvp_mode ||
+ (codec_mm_get_free_size() >
+ smgt->reserved_block_mm_M * SZ_1M))) {
/*try from codec_mm */
if (try_alloc_size <= 0) {
try_alloc_size =
goto error; /*don't alloc 1 page with slot. */
}
}
- if (!have_alloced && smgt->tvp_mode) {
+ if (!have_alloced) {
/*tvp not support alloc from sys.*/
- goto error;
+ if (smgt->tvp_mode || smgt->no_alloc_from_sys)
+ goto error;
}
while (!have_alloced) {
/*don't alloc 1 page with slot. */
int n;
codec_mm_list_lock(smgt);
- if (list_empty(&smgt->free_list) &&
- (codec_mm_get_free_size() < /*no codec mm */
- smgt->reserved_block_mm_M * SZ_1M) &&
- !smgt->support_from_slot_sys) { /*no sys */
+ if (!smgt->tvp_mode &&
+ list_empty(&smgt->free_list) &&
+ (codec_mm_get_free_size() </*no codec mm*/
+ smgt->reserved_block_mm_M * SZ_1M) &&
+ !smgt->support_from_slot_sys) {/*no sys*/
codec_mm_list_unlock(smgt);
return 0;
}
num - alloced);
if (new_alloc <= 0)
can_from_slot = 0;
- } else if (!smgt->tvp_mode) {
+ } else if (!smgt->no_alloc_from_sys && !smgt->tvp_mode) {
new_alloc = codec_mm_page_alloc_from_one_pages(
smgt,
pages + alloced,
if (src_mms->page_used >= src_mms->page_cnt)
return -1; /*no need free. */
dst_mms = smgt->cache_sc;
- if (!dst_mms)
+ if (!dst_mms || src_mms == dst_mms)
return 0;
codec_mm_scatter_lock(dst_mms);
moved = min(src_mms->page_cnt - src_mms->page_used,
}
codec_mm_list_lock(smgt);
smgt->alloced_page_num -= freeNum;
+ if (smgt->cache_sc == mms)
+ smgt->cached_pages = mms->page_cnt;
codec_mm_list_unlock(smgt);
return 0;
}
/*
-*free pages from id(include id);
-*/
+ *fast_mode:
+ *1: set page_used: call by owner
+ *2: free to scatter: call by owner
+ *3: free to slot or others: call by owner
+ *
+ *free_mode:
+ *0: free from id pages.
+ *1: free not used pages;call by moniter.
+ *2: less pages.: call by moniter for cache
+ * id is negative.
+ */
static int codec_mm_scatter_free_tail_pages_in(
struct codec_mm_scatter *mms,
- int start_free_id,
- int fast)
+ int id,
+ int fast_mode,
+ int free_mode)
{
- int id = start_free_id;
struct codec_mm_scatter_mgt *smgt;
- if (!mms || id < 0 || id >= mms->page_cnt || mms->page_tail < 0) {
- if (mms)
- ERR_LOG("free mm scatters error id %d,page_cnt=%d\n",
- id, mms->page_cnt);
+ int start_free_id = id;
+
+ if (!mms)
+ return -1;
+ codec_mm_scatter_lock(mms);
+ if (free_mode == 1)
+ start_free_id = mms->page_used;
+ if (free_mode == 2) {
+ if (id > 0) {
+ if (id >= mms->page_cnt)
+ start_free_id = 0;
+ else
+ start_free_id = mms->page_cnt - id;
+ } else
+ start_free_id = -1;
+ }
+ if ((start_free_id < 0) ||
+ (start_free_id >= mms->page_cnt) ||
+ (mms->page_tail < 0)) {
+ if (mms &&
+ start_free_id != mms->page_cnt) {
+ ERR_LOG(
+ "mms[%p],free error id %d(%d),cnt=%d ,=m:%d,%d\n",
+ mms,
+ id,
+ start_free_id,
+ mms->page_cnt,
+ fast_mode,
+ free_mode);
+ }
+ codec_mm_scatter_unlock(mms);
return -1;
}
smgt = (struct codec_mm_scatter_mgt *)mms->manager;
- codec_mm_scatter_lock(mms);
mms->page_used = start_free_id;
- if (fast == 1) {
+ if (fast_mode == 1) {
codec_mm_scatter_unlock(mms);
return 0;
}
- if (fast == 2 || fast == 3) {
+ if (fast_mode == 2 || fast_mode == 3) {
codec_mm_pages_free_to_scatter(smgt, mms);
- if (fast == 2 || mms->page_used == mms->page_cnt) {
+ if (fast_mode == 2 || mms->page_used == mms->page_cnt) {
codec_mm_scatter_unlock(mms);
return 0;
}
int codec_mm_scatter_free_tail_pages(
struct codec_mm_scatter *mms,
- int start_free_id)
+ int start_id)
{
int ret = 0;
-
- if (start_free_id < mms->page_cnt)
- ret = codec_mm_scatter_free_tail_pages_in(
+ ret = codec_mm_scatter_free_tail_pages_in(
mms,
- start_free_id, 0);
+ start_id, 0, 0);
return ret;
}
EXPORT_SYMBOL(codec_mm_scatter_free_tail_pages);
if (start_free_id < mms->page_cnt)
ret = codec_mm_scatter_free_tail_pages_in(
mms,
- start_free_id, 2);
+ start_free_id, 2, 0);
codec_mm_schedule_delay_work(
(struct codec_mm_scatter_mgt *)mms->manager,
100, 0);
int codec_mm_scatter_free_unused_pages(struct codec_mm_scatter *mms)
{
int ret = 0;
-
- if (mms->page_used < mms->page_cnt)
- ret = codec_mm_scatter_free_tail_pages_in(mms,
- mms->page_used, 3);
+ ret = codec_mm_scatter_free_tail_pages_in(mms,
+ 0, 0, 1);
return ret;
}
EXPORT_SYMBOL(codec_mm_scatter_free_unused_pages);
+int codec_mm_scatter_less_pages(struct codec_mm_scatter *mms,
+ int nums)
+{
+ int ret = 0;
+
+ ret = codec_mm_scatter_free_tail_pages_in(mms,
+ nums, 0, 2);
+ return ret;
+}
+EXPORT_SYMBOL(codec_mm_scatter_less_pages);
+
/*free all pages only
*don't free scatter
*/
codec_mm_list_unlock(smgt);
codec_mm_scatter_unlock(mms);
if (mms->page_cnt > 0)
- ret = codec_mm_scatter_free_tail_pages_in(mms, 0, 0);
+ ret = codec_mm_scatter_free_tail_pages_in(mms, 0, 0, 0);
if (free >= 256 &&
(smgt->try_alloc_in_sys_page_cnt <
smgt->try_alloc_in_sys_page_cnt_max) &&
codec_mm_list_unlock(smgt);
return ret <= 0 ? ret : 0; /*must add before user cnt >= 0 */
}
-
static int codec_mm_scatter_inc_user_in(
struct codec_mm_scatter *mms,
int cnt)
int delay_free_ms, int cnt)
{
int after_users = 1;
+
codec_mm_list_lock(smgt);
if (!codec_mm_scatter_valid_locked(smgt, mms)) {
codec_mm_list_unlock(smgt);
{
struct codec_mm_scatter_mgt *smgt;
int ret;
+
if (!mms)
return -1;
smgt = codec_mm_get_scatter_mgt(0);
}
return ret;
}
+
/*
*maybe a render/sink.video/osd/
*/
smgt->enable_slot_from_sys = g_scatter.enable_slot_from_sys;
smgt->support_from_slot_sys = g_scatter.support_from_slot_sys;
smgt->no_cache_size_M = g_scatter.no_cache_size_M;
+ smgt->no_alloc_from_sys = g_scatter.no_alloc_from_sys;
return 0;
}
smgt->delay_free_timeout_jiffies64)) {
/*wait time out can free.*/
mms = smgt->cache_sc;
- if (mms) { /*only free some 1M cache */
- int free_start = smgt->cached_pages - 256;
-
- if (free_start < smgt->keep_size_PAGE)
- free_start = smgt->keep_size_PAGE;
- codec_mm_scatter_free_tail_pages(mms,
- free_start);
+ if (mms) {/*only free some 1M cache*/
+ codec_mm_scatter_less_pages(mms,
+ 256);
}
codec_mm_free_all_free_slots_in(smgt);
/*free some slots.*/
MC_PU32("enable_slot_from_sys",
&g_scatter.enable_slot_from_sys),
MC_PU32("no_cache_size_M", &g_scatter.no_cache_size_M),
+ MC_PU32("no_alloc_from_sys", &g_scatter.no_alloc_from_sys),
};
static struct mconfig_node codec_mm_sc;
g_scatter.enable_slot_from_sys = smgt->enable_slot_from_sys;
g_scatter.support_from_slot_sys = smgt->support_from_slot_sys;
g_scatter.no_cache_size_M = smgt->no_cache_size_M;
-
+ g_scatter.no_alloc_from_sys = smgt->no_cache_size_M;
INIT_REG_NODE_CONFIGS("media.codec_mm",
&codec_mm_sc, "scatter",
codec_mm_sc_configs,
#include "vftrace.h"
#define MAX_PROVIDER_NUM 32
-struct vframe_provider_s *provider_table[MAX_PROVIDER_NUM];
+static struct vframe_provider_s *provider_table[MAX_PROVIDER_NUM];
+static atomic_t provider_used = ATOMIC_INIT(0);
+
+#define providers_lock() atomic_inc(&provider_used)
+#define providers_unlock() atomic_dec(&provider_used)
+#define providers_used() atomic_read(&provider_used)
+
+static DEFINE_MUTEX(provider_table_mutex);
+#define TABLE_LOCK() mutex_lock(&provider_table_mutex)
+#define TABLE_UNLOCK() mutex_unlock(&provider_table_mutex)
+
+#define VFPROVIER_DEBUG
+#ifdef VFPROVIER_DEBUG
+static DEFINE_SPINLOCK(provider_lock);
+static const char *last_receiver;
+static const char *last_provider;
+void provider_update_caller(const char *receiver, const char *provider)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&provider_lock, flags);
+ last_receiver = receiver;
+ last_provider = provider;
+ spin_unlock_irqrestore(&provider_lock, flags);
+}
+
+void provider_print_last_info(void)
+{
+ unsigned long flags;
+ struct vframe_provider_s *p;
+ int i;
+
+ spin_lock_irqsave(&provider_lock, flags);
+ pr_info("last receiver: %s\n",
+ last_receiver ? last_receiver : "null");
+ pr_info("last provider: %s\n",
+ last_provider ? last_provider : "null");
+ pr_info("register provider:\n");
+ for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+ p = provider_table[i];
+ if (p)
+ pr_info("%s: user_cnt:%d\n", p->name,
+ atomic_read(&p->use_cnt));
+ }
+ spin_unlock_irqrestore(&provider_lock, flags);
+}
+#else
+void provider_update_caller(
+ const char *receiver,
+ const char *provider) {return }
+void provider_print_last_info(void) {return}
+
+#endif
int provider_list(char *buf)
{
if (ret > CLOSED_CNT) {
pr_err("**ERR***,release, provider %s not finised,%d, wait=%d\n",
prov->name, ret, wait_max);
+ provider_print_last_info();
}
return 0;
}
prov->traceget = NULL;
prov->traceput = NULL;
atomic_set(&prov->use_cnt, 0);/*set it ready for use.*/
+ TABLE_LOCK();
for (i = 0; i < MAX_PROVIDER_NUM; i++) {
p = provider_table[i];
if (p) {
- if (!strcmp(p->name, prov->name))
+ if (!strcmp(p->name, prov->name)) {
+ TABLE_UNLOCK();
return -1;
+ }
}
}
for (i = 0; i < MAX_PROVIDER_NUM; i++) {
break;
}
}
+ TABLE_UNLOCK();
if (i < MAX_PROVIDER_NUM) {
vf_update_active_map();
receiver = vf_get_receiver(prov->name);
int i;
for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+ TABLE_LOCK();
p = provider_table[i];
if (p && !strcmp(p->name, prov->name)) {
+ provider_table[i] = NULL;
+ TABLE_UNLOCK();
if (p->traceget) {
- vftrace_free_trace(p->traceget);
+ vftrace_free_trace(prov->traceget);
p->traceget = NULL;
}
if (p->traceput) {
- vftrace_free_trace(p->traceput);
+ vftrace_free_trace(prov->traceput);
p->traceput = NULL;
}
vf_provider_close(prov);
- provider_table[i] = NULL;
if (vfm_debug_flag & 1)
pr_err("%s:%s\n", __func__, prov->name);
receiver = vf_get_receiver(prov->name);
vf_update_active_map();
break;
}
+ TABLE_UNLOCK();
+ }
+ {
+ /*
+ * wait no one used provider,
+ * if some one have on used.
+ * the provider memory may free,
+ * become unreachable.
+ */
+ int cnt = 0;
+
+ while (providers_used()) {
+ schedule();
+ cnt++;
+ if (cnt > 10000) {
+ pr_err("unreg provider locked %s,%d!\n",
+ prov->name, cnt);
+ provider_print_last_info();
+ break;
+ }
+ }
}
}
EXPORT_SYMBOL(vf_unreg_provider);
int i;
for (i = 0; i < MAX_PROVIDER_NUM; i++) {
+ TABLE_LOCK();
p = provider_table[i];
if (p && !strcmp(p->name, prov->name)) {
provider_table[i] = NULL;
+ TABLE_UNLOCK();
if (vfm_debug_flag & 1)
pr_err("%s:%s\n", __func__, prov->name);
vf_update_active_map();
break;
}
+ TABLE_UNLOCK();
}
}
EXPORT_SYMBOL(vf_ext_light_unreg_provider);
{
struct vframe_provider_s *vfp;
struct vframe_s *vf = NULL;
+ providers_lock();
vfp = vf_get_provider(receiver);
if (use_provider(vfp)) {
if (vfp->ops && vfp->ops->peek)
vf = vfp->ops->peek(vfp->op_arg);
unuse_provider(vfp);
}
+ providers_unlock();
return vf;
}
EXPORT_SYMBOL(vf_peek);
struct vframe_provider_s *vfp;
struct vframe_s *vf = NULL;
+ providers_lock();
vfp = vf_get_provider(receiver);
+
if (use_provider(vfp)) {
+ provider_update_caller(receiver, vfp->name);
if (vfp->ops && vfp->ops->get)
vf = vfp->ops->get(vfp->op_arg);
if (vf)
vftrace_info_in(vfp->traceget, vf);
unuse_provider(vfp);
- }
+ } else
+ provider_update_caller(receiver, NULL);
+
+ providers_unlock();
return vf;
}
EXPORT_SYMBOL(vf_get);
void vf_put(struct vframe_s *vf, const char *receiver)
{
struct vframe_provider_s *vfp;
-
+ providers_lock();
vfp = vf_get_provider(receiver);
if (use_provider(vfp)) {
+ provider_update_caller(receiver, vfp->name);
if (vfp->ops && vfp->ops->put)
vfp->ops->put(vf, vfp->op_arg);
if (vf)
vftrace_info_in(vfp->traceput, vf);
unuse_provider(vfp);
+ } else {
+ provider_update_caller(receiver, NULL);
}
+ providers_unlock();
}
EXPORT_SYMBOL(vf_put);
struct vframe_states *states)
{
int ret = -1;
-
+ providers_lock();
if (use_provider(vfp)) {
+ provider_update_caller(NULL, vfp->name);
if (vfp->ops && vfp->ops->vf_states)
ret = vfp->ops->vf_states(states, vfp->op_arg);
unuse_provider(vfp);
}
+ providers_unlock();
return ret;
}
EXPORT_SYMBOL(vf_get_states);
#include <linux/amlogic/media/frame_sync/tsync.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
#include <linux/amlogic/media/registers/register.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
u32 acc_apts_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;
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_apts > 0 && last_checkin_apts > 0)
+ 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;
if (cur_pcr && !(tsync_pcr_inited_flag & complete_init_flag)
&& (min_checkinpts != 0)) {
tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_PCR;
- ref_pcr = cur_pcr - tsync_pcr_adj_value * 15;
+ if (cur_pcr > tsync_pcr_adj_value * 15)
+ ref_pcr = cur_pcr - tsync_pcr_adj_value * 15;
+
timestamp_pcrscr_set(ref_pcr);
tsync_pcr_usepcr = 1;
ref_pcr = first_apts;
/* add it for dolby av sync */
- if (cur_pcr > 0)
+ if (cur_pcr > tsync_apts_adj_value)
ref_pcr = cur_pcr - tsync_apts_adj_value;
timestamp_pcrscr_set(ref_pcr);
if (cur_pcr > 0)
tsync_pcr_usepcr = 1;
+ else
+ tsync_pcr_usepcr = 0;
timestamp_pcrscr_enable(1);
pr_info
if (first_vpts && !(tsync_pcr_inited_flag & complete_init_flag)
&& (min_checkinpts != 0)) {
tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS;
- ref_pcr = first_vpts - tsync_pcr_ref_latency * 15;
+ if (first_vpts > tsync_pcr_ref_latency * 15)
+ ref_pcr = first_vpts - tsync_pcr_ref_latency * 15;
+
timestamp_pcrscr_set(ref_pcr);
if (cur_pcr > 0)
tsync_pcr_usepcr = 1;
+ else
+ tsync_pcr_usepcr = 0;
timestamp_pcrscr_enable(1);
pr_info
}
if (need_recovery && !tsync_pcr_vpause_flag) {
- if (play_mode == PLAY_MODE_SLOW) {
- timestamp_pcrscr_set(timestamp_pcrscr_get() -
- tsync_pcr_recovery_span);
- } else if (play_mode == PLAY_MODE_FORCE_SLOW) {
- timestamp_pcrscr_set(timestamp_pcrscr_get() -
- FORCE_RECOVERY_SPAN);
- } else if (play_mode == PLAY_MODE_SPEED) {
- timestamp_pcrscr_set(timestamp_pcrscr_get() +
- tsync_pcr_recovery_span);
- } else if (play_mode == PLAY_MODE_FORCE_SPEED) {
- timestamp_pcrscr_set(timestamp_pcrscr_get() +
- FORCE_RECOVERY_SPAN);
- }
+ if (play_mode == PLAY_MODE_SLOW)
+ timestamp_pcrscr_set_adj_pcr(-1);
+ else if (play_mode == PLAY_MODE_FORCE_SLOW)
+ timestamp_pcrscr_set_adj_pcr(-2);
+ else if (play_mode == PLAY_MODE_SPEED)
+ timestamp_pcrscr_set_adj_pcr(1);
+ else if (play_mode == PLAY_MODE_FORCE_SPEED)
+ timestamp_pcrscr_set_adj_pcr(2);
+ else if (play_mode == PLAY_MODE_NORMAL)
+ timestamp_pcrscr_set_adj_pcr(0);
}
/* } */
del_timer_sync(&tsync_pcr_check_timer);
pr_info("[tsync_pcr_stop]PCRMASTER stop success.\n");
}
+ timestamp_pcrscr_set(0);
tsync_pcr_freerun_mode = 0;
tsync_pcr_started = 0;
}
#define DEBUG_TMP 0
static int video_global_output = 1;
+/* video_pause_global: 0 is play, 1 is pause, 2 is invalid */
+static int video_pause_global = 1;
#ifdef CONFIG_GE2D_KEEP_FRAME
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
}
EXPORT_SYMBOL(get_video0_frame_info);
-static struct vframe_s vf_local;
+static struct vframe_s vf_local, vf_local2;
static u32 vsync_pts_inc;
static u32 vsync_pts_inc_scale;
static u32 vsync_pts_inc_scale_base = 1;
atomic_t trickmode_framedone = ATOMIC_INIT(0);
atomic_t video_sizechange = ATOMIC_INIT(0);
atomic_t video_unreg_flag = ATOMIC_INIT(0);
+atomic_t video_inirq_flag = ATOMIC_INIT(0);
atomic_t video_pause_flag = ATOMIC_INIT(0);
int trickmode_duration;
int trickmode_duration_count;
*rs = *ls + (height >> 1);
*re = *le + (height >> 1);
}
- }
if ((process_3d_type & MODE_3D_TO_2D_MASK)
|| (process_3d_type & MODE_3D_OUT_LR)) {
/* same width,half height */
*le = zoom_end_y_lines;
*rs = zoom_start_y_lines + (height >> 1);
*re = zoom_end_y_lines + (height >> 1);
+ }
}
break;
case VPP_3D_MODE_LR:
#endif
static void zoom_display_horz(int hscale)
{
- u32 ls, le, rs, re;
+ u32 ls = 0, le = 0, rs = 0, re = 0;
#ifdef TV_REVERSE
int content_w, content_l, content_r;
#endif
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(AFBC_SIZE_OUT,
- (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT) & 0xffff) |
+ (VSYNC_RD_MPEG_REG(AFBC_SIZE_OUT)
+ & 0xffff) |
(((r_aligned - l_aligned) / h_skip) << 16));
}
#ifdef TV_REVERSE
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int l_aligned;
int r_aligned;
+ int h_skip = cur_frame_par->hscale_skip_count + 1;
if ((zoom2_start_x_lines > 0) ||
(zoom2_end_x_lines < ori2_end_x_lines)) {
l_aligned = round_down(ori2_start_x_lines, 32);
r_aligned = round_up(ori2_end_x_lines + 1, 32);
} else {
- l_aligned = round_down(ori2_start_x_lines, 32);
- r_aligned = round_up(ori2_end_x_lines + 1, 32);
+ l_aligned = round_down(zoom2_start_x_lines, 32);
+ r_aligned = round_up(zoom2_end_x_lines + 1, 32);
}
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_W,
- ((r_aligned - l_aligned) << 16) |
- (r_aligned / 2 - l_aligned / 2));
+ (((r_aligned - l_aligned) / h_skip) << 16) |
+ ((r_aligned / 2 - l_aligned / 2) / h_skip));
+
VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_HOR_SCOPE,
((l_aligned / 32) << 16) |
((r_aligned / 32) - 1));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
- (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) &
- 0xffff) | ((r_aligned - l_aligned) << 16));
+ (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
+ & 0xffff) |
+ (((r_aligned - l_aligned) / h_skip) << 16));
}
#ifdef TV_REVERSE
if (reverse) {
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
int t_aligned;
int b_aligned;
-
+ int ori_t_aligned;
+ int ori_b_aligned;
+ int v_skip = cur_frame_par->vscale_skip_count + 1;
t_aligned = round_down(zoom2_start_y_lines, 4);
b_aligned = round_up(zoom2_end_y_lines + 1, 4);
+ ori_t_aligned = round_down(ori2_start_y_lines, 4);
+ ori_b_aligned = round_up(ori2_end_y_lines + 1, 4);
+
/* TODO: afbc setting only support 420 for now */
VSYNC_WR_MPEG_REG(VD2_AFBC_VD_CFMT_H,
- (b_aligned - t_aligned) / 2);
+ (b_aligned - t_aligned) / 2 / v_skip);
VSYNC_WR_MPEG_REG(VD2_AFBC_MIF_VER_SCOPE,
((t_aligned / 4) << 16) |
(zoom2_end_y_lines - t_aligned));
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_IN,
- (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN) & 0xffff0000) |
- (b_aligned - t_aligned));
+ (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_IN)
+ & 0xffff0000) |
+ (ori_b_aligned - ori_t_aligned));
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
VSYNC_WR_MPEG_REG(VD2_AFBC_SIZE_OUT,
- (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT) & 0xffff0000)
- | (b_aligned - t_aligned));
+ (VSYNC_RD_MPEG_REG(VD2_AFBC_SIZE_OUT)
+ & 0xffff0000) |
+ ((b_aligned - t_aligned) / v_skip));
}
}
}
u32 type = vf->type, bit_mode = 0;
bool vf_with_el = false;
+ pr_debug("set dcu for vd1 %p, type:0x%x\n", vf, type);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
if (frame_par->nocomp)
type &= ~VIDTYPE_COMPRESS;
VFORMATTER_EN);
else
VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL,
- (is_dolby_vision_on() ?
- HFORMATTER_REPEAT |
- (0xc << VFORMATTER_INIPHASE_BIT) :
- HFORMATTER_RRT_PIXEL0) |
+ HFORMATTER_REPEAT |
+ (0xc << VFORMATTER_INIPHASE_BIT) |
HFORMATTER_YC_RATIO_2_1 |
HFORMATTER_EN |
VFORMATTER_RPTLINE0_EN |
VFORMATTER_EN);
else
VSYNC_WR_MPEG_REG(AFBC_VD_CFMT_CTRL,
- (is_dolby_vision_on() ?
- HFORMATTER_REPEAT |
- (0xc << VFORMATTER_INIPHASE_BIT) :
- HFORMATTER_RRT_PIXEL0) |
- HFORMATTER_YC_RATIO_2_1 |
- HFORMATTER_EN |
- VFORMATTER_RPTLINE0_EN |
- (0x8 << VFORMATTER_PHASE_BIT) |
- VFORMATTER_EN);
+ HFORMATTER_REPEAT |
+ (0xc << VFORMATTER_INIPHASE_BIT) |
+ HFORMATTER_YC_RATIO_2_1 |
+ HFORMATTER_EN |
+ VFORMATTER_RPTLINE0_EN |
+ (0x8 << VFORMATTER_PHASE_BIT) |
+ VFORMATTER_EN);
}
if ((VSYNC_RD_MPEG_REG(DI_POST_CTRL) & 0x100) == 0)
VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 +
VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0 +
cur_dev->viu_off, 1, 20, 1);
+ VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG +
+ cur_dev->viu_off, 0);
return;
} else {
}
VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG3,
(bit_mode&0x3), 8, 2);
+ if ((vf->type & VIDTYPE_MVC) && (!vf_with_el))
+ VSYNC_WR_MPEG_REG_BITS(
+ VD2_IF0_GEN_REG3,
+ (bit_mode & 0x3), 8, 2);
VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG3,
(bit_mode&0x3), 8, 2);
if (is_meson_txl_cpu() || is_meson_txlx_cpu())
((type & VIDTYPE_VIU_422) ?
0 :
VFORMATTER_EN));
- pr_info("\tvd1 set fmt(dovi tv)\n");
+ pr_debug("\tvd1 set fmt(dovi tv)\n");
} else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
is_meson_txlx_cpu()) {
if ((vf->width >= 3840) &&
static const u32 vpat[] = { 0, 0x8, 0x9, 0xa, 0xb, 0xc };
u32 u, v;
u32 type = vf->type, bit_mode = 0;
- u32 skip_count = 0;
- pr_info("set dcu for vd2 %p, type:0x%x\n", vf, type);
+ pr_debug("set dcu for vd2 %p, type:0x%x\n", vf, type);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
if (type & VIDTYPE_COMPRESS) {
r = (3 << 24) |
(1 << 14) | /*burst1 1*/
(vf->bitdepth & BITDEPTH_MASK);
- if (skip_count)
+ if (frame_par->hscale_skip_count)
r |= 0x33;
- if (skip_count)
+ if (frame_par->vscale_skip_count)
r |= 0xcc;
#ifdef TV_REVERSE
#endif
VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL1 +
cur_dev->viu_off, 1, 1, 1);
+ VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG +
+ cur_dev->viu_off, 0);
return;
} else {
if ((vf->bitdepth & BITDEPTH_Y10) &&
}
}
- if (skip_count)
+ if (frame_par->hscale_skip_count)
r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, r);
(((type & VIDTYPE_VIU_422) ? 0x10 : 0x08)
<< VFORMATTER_PHASE_BIT) |
VFORMATTER_EN);
- pr_info("\tvd2 set fmt(dovi tv)\n");
+ pr_debug("\tvd2 set fmt(dovi tv)\n");
} else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() ||
is_meson_txlx_cpu()) {
if ((vf->width >= 3840) &&
}
}
/* LOOP/SKIP pattern */
- pat = vpat[skip_count];
+ pat = vpat[frame_par->vscale_skip_count];
if (type & VIDTYPE_VIU_FIELD) {
loop = 0;
if (type & VIDTYPE_INTERLACE)
- pat = vpat[skip_count >> 1];
+ pat = vpat[frame_par->vscale_skip_count >> 1];
} else if (type & VIDTYPE_MVC) {
loop = 0x11;
pat = 0x80;
tsync_avevent_locked(VIDEO_TSTAMP_DISCONTINUITY,
pts);
- pr_info("discontinue, systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n",
- systime,
- pts,
- next_vf->pts);
+ /* pr_info("discontinue,
+ * systime=0x%x vpts=0x%x next_vf->pts = 0x%x\n",
+ * systime,
+ * pts,
+ * next_vf->pts);
+ */
/* pts==0 is a keep frame maybe. */
if (systime > next_vf->pts || next_vf->pts == 0)
}
}
+void correct_vd1_mif_size_for_DV(struct vpp_frame_par_s *par)
+{
+ u32 aligned_mask = 0xfffffffe;
+ u32 old_len;
+
+ if ((is_dolby_vision_on() == true) &&
+ (par->VPP_line_in_length_ > 0)) {
+ if (cur_dispbuf2) {
+ /*
+ *if (cur_dispbuf2->type
+ * & VIDTYPE_COMPRESS)
+ * aligned_mask = 0xffffffc0;
+ *else
+ */
+ aligned_mask = 0xfffffffc;
+ }
+#if 0 /* def TV_REVERSE */
+ if (reverse) {
+ par->VPP_line_in_length_
+ &= 0xfffffffe;
+ par->VPP_hd_end_lines_
+ &= 0xfffffffe;
+ par->VPP_hd_start_lines_ =
+ par->VPP_hd_end_lines_ + 1
+ - par->VPP_line_in_length_;
+ } else
+#endif
+ {
+ par->VPP_line_in_length_
+ &= aligned_mask;
+ par->VPP_hd_start_lines_
+ &= aligned_mask;
+ par->VPP_hd_end_lines_ =
+ par->VPP_hd_start_lines_ +
+ par->VPP_line_in_length_ - 1;
+ /* if have el layer, need 2 pixel align by height */
+ if (cur_dispbuf2) {
+ old_len =
+ par->VPP_vd_end_lines_ -
+ par->VPP_vd_start_lines_ + 1;
+ if (old_len & 1)
+ par->VPP_vd_end_lines_--;
+ if (par->VPP_vd_start_lines_ & 1) {
+ par->VPP_vd_start_lines_--;
+ par->VPP_vd_end_lines_--;
+ }
+ old_len =
+ par->VPP_vd_end_lines_ -
+ par->VPP_vd_start_lines_ + 1;
+ old_len = old_len >> par->vscale_skip_count;
+ if (par->VPP_pic_in_height_ < old_len)
+ par->VPP_pic_in_height_ = old_len;
+ }
+ }
+ }
+}
+
+#if DEBUG_TMP
+void correct_vd2_mif_size_for_DV(
+ struct vpp_frame_par_s *par,
+ struct vframe_s *bl_vf)
+{
+ int width_bl, width_el, line_in_length;
+ int shift;
+
+ if ((is_dolby_vision_on() == true) &&
+ (par->VPP_line_in_length_ > 0)) {
+ width_el = (cur_dispbuf2->type
+ & VIDTYPE_COMPRESS) ?
+ cur_dispbuf2->compWidth :
+ cur_dispbuf2->width;
+ width_bl = (bl_vf->type
+ & VIDTYPE_COMPRESS) ?
+ bl_vf->compWidth :
+ bl_vf->width;
+ if (width_el >= width_bl)
+ shift = 0;
+ else
+ shift = 1;
+ zoom2_start_x_lines =
+ par->VPP_hd_start_lines_ >> shift;
+ line_in_length =
+ par->VPP_line_in_length_ >> shift;
+ zoom2_end_x_lines
+ &= 0xfffffffe;
+ line_in_length
+ &= 0xfffffffe;
+ if (line_in_length > 1)
+ zoom2_end_x_lines =
+ zoom2_start_x_lines +
+ line_in_length - 1;
+ else
+ zoom2_end_x_lines = zoom2_start_x_lines;
+
+ zoom2_start_y_lines =
+ par->VPP_vd_start_lines_ >> shift;
+ if (zoom2_start_y_lines >= zoom2_end_y_lines)
+ zoom2_end_y_lines = zoom2_start_y_lines;
+ /* TODO: if el len is 0, need disable bl */
+ }
+}
+#endif
+
#ifdef FIQ_VSYNC
-void vsync_fisr(void)
+void vsync_fisr_in(void)
#else
-static irqreturn_t vsync_isr(int irq, void *dev_id)
+static irqreturn_t vsync_isr_in(int irq, void *dev_id)
#endif
{
int hold_line;
#endif
#if DEBUG_TMP
struct vframe_s *toggle_vf = NULL;
- int ret;
#endif
+ struct vframe_s *toggle_frame = NULL;
int video1_off_req = 0;
struct vframe_s *cur_dispbuf_back = cur_dispbuf;
+ static struct vframe_s *pause_vf;
if (debug_flag & DEBUG_FLAG_VSYNC_DONONE)
return IRQ_HANDLED;
/* check video frame before VECM process */
if (is_dolby_vision_enable() && vf)
dolby_vision_check_hdr10(vf);
-#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
- amvecm_on_vs(vf);
-#endif
#endif
#ifdef CONFIG_TVIN_VDIN
if (atomic_read(&video_unreg_flag))
goto exit;
- if (atomic_read(&video_pause_flag))
+ if (atomic_read(&video_pause_flag)
+ && (!((video_global_output == 1)
+ && (video_enabled != video_status_saved))))
goto exit;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_vsync_rdma_enable())
#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
refresh_on_vs(vf);
+ if (amvecm_on_vs(
+ (cur_dispbuf != &vf_local)
+ ? cur_dispbuf : NULL,
+ vf, CSC_FLAG_CHECK_OUTPUT) == 1)
+ break;
#endif
if (is_dolby_vision_enable()
*/
if (vf && hdmiin_frame_check &&
(vf->source_type == VFRAME_SOURCE_TYPE_HDMI) &&
- (video_vf_disp_mode_get(vf) !=
- VFRAME_DISP_MODE_OK) &&
+ (video_vf_disp_mode_get(vf) ==
+ VFRAME_DISP_MODE_UNKNOWN) &&
(hdmiin_frame_check_cnt++ < 10))
break;
-
- hdmiin_frame_check_cnt = 0;
+ else
+ hdmiin_frame_check_cnt = 0;
vf = video_vf_get();
if (!vf)
}
}
vsync_toggle_frame(vf);
-#if DEBUG_TMP
- if (is_dolby_vision_enable())
- toggle_vf = dolby_vision_toggle_frame(vf);
- else
-#endif
+ toggle_frame = vf;
+ if (0/*is_dolby_vision_enable()*/) { /*DEBUG_TMP*/
+ //toggle_vf = dolby_vision_toggle_frame(vf);
+ video_pause_global = 0;
+ } else {
cur_dispbuf2 = NULL;
-
+ video_pause_global = 2;
+ pause_vf = NULL;
+ }
if (trickmode_fffb == 1) {
trickmode_vpts = vf->pts;
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
if (is_dolby_vision_enable()
&& dolby_vision_need_wait())
break;
+#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
+ refresh_on_vs(vf);
+ if (amvecm_on_vs(
+ (cur_dispbuf != &vf_local)
+ ? cur_dispbuf : NULL,
+ vf, CSC_FLAG_CHECK_OUTPUT) == 1)
+ break;
+#endif
#endif
vf = video_vf_get();
if (!vf)
break;
vsync_toggle_frame(vf);
+ toggle_frame = vf;
#if DEBUG_TMP
if (is_dolby_vision_enable())
toggle_vf =
cur_dispbuf);
} else
vsync_toggle_frame(cur_dispbuf);
+ /*DEBUG_TMP*/
+ if (0/*is_dolby_vision_enable()*/) {
+ pause_vf = cur_dispbuf;
+ video_pause_global = 1;
+ } else {
+ pause_vf = NULL;
+ video_pause_global = 2;
+ }
}
-
+#if DEBUG_TMP
+ if (pause_vf && (video_pause_global == 1)
+ && is_dolby_vision_enable()) {
+ toggle_vf = pause_vf;
+ dolby_vision_parse_metadata(cur_dispbuf, true);
+ dolby_vision_set_toggle_flag(1);
+ }
+#endif
break;
}
SET_FILTER:
#if DEBUG_TMP
- if (is_dolby_vision_enable()) {
- u32 skip_mode = 0;
-
- if (cur_frame_par)
- skip_mode =
- (cur_frame_par->hscale_skip_count << 16)
- | cur_frame_par->vscale_skip_count;
- dolby_vision_process(toggle_vf, skip_mode);
- dolby_vision_update_setting();
- }
+#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
+ amvecm_on_vs(
+ (cur_dispbuf != &vf_local) ? cur_dispbuf : NULL,
+ toggle_frame,
+ toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0);
+#endif
#endif
/* filter setting management */
if ((frame_par_ready_to_set) || (frame_par_force_to_set)) {
cur_frame_par = next_frame_par;
frame_par_di_set = 1;
}
+
+#if DEBUG_TMP
+ if (is_dolby_vision_enable()) {
+ u32 frame_size = 0, h_size, v_size;
+
+ if (cur_frame_par) {
+ if (cur_frame_par->VPP_hd_start_lines_
+ >= cur_frame_par->VPP_hd_end_lines_)
+ h_size = 0;
+ else
+ h_size = cur_frame_par->VPP_hd_end_lines_
+ - cur_frame_par->VPP_hd_start_lines_ + 1;
+ h_size /= (cur_frame_par->hscale_skip_count + 1);
+ if (cur_frame_par->VPP_vd_start_lines_
+ >= cur_frame_par->VPP_vd_end_lines_)
+ v_size = 0;
+ else
+ v_size = cur_frame_par->VPP_vd_end_lines_
+ - cur_frame_par->VPP_vd_start_lines_ + 1;
+ v_size /= (cur_frame_par->vscale_skip_count + 1);
+ frame_size = (h_size << 16) | v_size;
+ } else if (toggle_vf) {
+ h_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
+ toggle_vf->compWidth : toggle_vf->width;
+ v_size = (toggle_vf->type & VIDTYPE_COMPRESS) ?
+ toggle_vf->compHeight : toggle_vf->height;
+ frame_size = (h_size << 16) | v_size;
+ }
+ dolby_vision_process(toggle_vf, frame_size);
+ dolby_vision_update_setting();
+ }
+#endif
if ((platform_type == 1) || (platform_type == 0)) {
if (mode_3d_changed) {
mode_3d_changed = 0;
if (cur_dispbuf) {
u32 zoom_start_y, zoom_end_y;
-
+ correct_vd1_mif_size_for_DV(cur_frame_par);
if (cur_dispbuf->type & VIDTYPE_INTERLACE) {
if (cur_dispbuf->type & VIDTYPE_VIU_FIELD) {
zoom_start_y =
if (is_dolby_vision_enable() && cur_dispbuf2) {
zoom2_start_x_lines = ori2_start_x_lines;
zoom2_end_x_lines = ori2_end_x_lines;
- vd2_zoom_display_horz(0);
zoom2_start_y_lines = ori2_start_y_lines;
zoom2_end_y_lines = ori2_end_y_lines;
+ correct_vd2_mif_size_for_DV(
+ cur_frame_par, cur_dispbuf);
+ vd2_zoom_display_horz(0);
vd2_zoom_display_vert();
}
#endif
cur_frame_par->supsc0_vert_ratio) & 0x1fff));
}
#endif
+ /* work around to cut the last green line*/
+ /*when two layer dv display and do vskip */
+ if (is_dolby_vision_on() &&
+ (cur_frame_par->vscale_skip_count > 0)
+ && cur_dispbuf2
+ && (cur_frame_par->VPP_pic_in_height_ > 0))
+ cur_frame_par->VPP_pic_in_height_--;
VSYNC_WR_MPEG_REG(VPP_PIC_IN_HEIGHT + cur_dev->vpp_off,
cur_frame_par->VPP_pic_in_height_);
if (debug_flag & DEBUG_FLAG_BLACKOUT)
pr_info("AFBC off now.\n");
VSYNC_WR_MPEG_REG(AFBC_ENABLE, 0);
+ VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE, 0);
+ VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG, 0);
+ VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG, 0);
}
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
}
+#ifdef FIQ_VSYNC
+void vsync_fisr(void)
+{
+ atomic_set(&video_inirq_flag, 1);
+ vsync_fisr_in();
+ atomic_set(&video_inirq_flag, 0);
+}
+#else
+static irqreturn_t vsync_isr(int irq, void *dev_id)
+{
+ irqreturn_t ret;
+
+ atomic_set(&video_inirq_flag, 1);
+ ret = vsync_isr_in(irq, dev_id);
+ atomic_set(&video_inirq_flag, 0);
+ return ret;
+}
+#endif
/*********************************************************
static void video_vf_unreg_provider(void)
{
ulong flags;
+ struct vframe_s *el_vf = NULL;
new_frame_count = 0;
first_frame_toggled = 0;
atomic_set(&video_unreg_flag, 1);
+ while (atomic_read(&video_inirq_flag) > 0)
+ schedule();
spin_lock_irqsave(&lock, flags);
#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
cur_dispbuf = &vf_local;
cur_dispbuf->video_angle = 0;
}
-#if DEBUG_TMP
- if (is_dolby_vision_enable())
+ if (0/*is_dolby_vision_enable()*/) {/*DEBUG_TMP*/
+ if (cur_dispbuf2 == &vf_local2)
+ cur_dispbuf2 = NULL;
+ else if (cur_dispbuf2 != NULL) {
+ vf_local2 = *cur_dispbuf2;
+ el_vf = &vf_local2;
+ }
cur_dispbuf2 = NULL;
-#endif
+ }
if (trickmode_fffb) {
atomic_set(&trickmode_framedone, 0);
to_notify_trick_wait = false;
if (cur_dispbuf) {
/* TODO: mod gate */
/* switch_mod_gate_by_name("ge2d", 1); */
- vf_keep_current(cur_dispbuf);
+ vf_keep_current(cur_dispbuf, el_vf);
/* TODO: mod gate */
/* switch_mod_gate_by_name("ge2d", 0); */
}
#else
/* if (!trickmode_fffb) */
if (cur_dispbuf)
- vf_keep_current(cur_dispbuf);
+ vf_keep_current(cur_dispbuf, el_vf);
if (hdmi_in_onvideo == 0)
tsync_avevent(VIDEO_STOP, 0);
#endif
static int keep_video_on;
static int keep_id;
static int keep_head_id;
+static int keep_el_id;
+static int keep_el_head_id;
#define Y_BUFFER_SIZE 0x400000 /* for 1920*1088 */
#define U_BUFFER_SIZE 0x100000 /* compatible with NV21 */
#ifdef RESERVE_CLR_FRAME
static int free_alloced_keep_buffer(void)
{
- pr_info("free_alloced_keep_buffer %p.%p.%p\n",
+ /*pr_info("free_alloced_keep_buffer %p.%p.%p\n",
(void *)keep_y_addr, (void *)keep_u_addr, (void *)keep_v_addr);
+ */
if (keep_y_addr) {
codec_mm_free_for_dma(MEM_NAME, keep_y_addr);
keep_y_addr = 0;
int free_scatter_keeper = flags & 0x1;
if (keep_video_on || free_scatter_keeper) {
- pr_info("disbled keep video before free keep buffer.\n");
+ /*pr_info("disbled keep video before free keep buffer.\n");*/
keep_video_on = 0;
- update_cur_dispbuf(NULL);
if (!get_video_enabled()) {
/*if not disable video,changed to 2 for */
pr_info("disbled video for next before free keep buffer!\n");
safe_disble_videolayer();
}
}
- if (free_scatter_keeper && keep_id > 0) {
- pr_info("try_free_keep_video keepid\n");
- codec_mm_keeper_unmask_keeper(keep_id, 0);
- keep_id = -1;
- }
- if (free_scatter_keeper && keep_head_id > 0) {
- pr_info("try_free_keep_video keep_head_id\n");
- codec_mm_keeper_unmask_keeper(keep_head_id, 0);
- keep_head_id = -1;
- }
mutex_lock(&video_keeper_mutex);
+ video_keeper_new_frame_notify();
free_alloced_keep_buffer();
mutex_unlock(&video_keeper_mutex);
-
}
EXPORT_SYMBOL(try_free_keep_video);
#endif
+static void video_keeper_update_keeper_mem(
+ void *mem_handle, int type,
+ int *id)
+{
+ int ret;
+ int old_id = *id;
+
+ if (!mem_handle)
+ return;
+ ret = codec_mm_keeper_mask_keep_mem(mem_handle,
+ type);
+ if (ret > 0) {
+ if (old_id > 0 && ret != old_id) {
+ /*wait 80 ms for vsync post.*/
+ codec_mm_keeper_unmask_keeper(old_id, 120);
+ }
+ *id = ret;
+ }
+}
+static void video_keeper_frame_keep_locked(
+ struct vframe_s *cur_dispbuf,
+ struct vframe_s *cur_dispbuf_el)
+{
+ int type = MEM_TYPE_CODEC_MM;
+
+ if (cur_dispbuf->type & VIDTYPE_SCATTER)
+ type = MEM_TYPE_CODEC_MM_SCATTER;
+ video_keeper_update_keeper_mem(
+ cur_dispbuf->mem_handle,
+ type,
+ &keep_id);
+ video_keeper_update_keeper_mem(
+ cur_dispbuf->mem_head_handle,
+ MEM_TYPE_CODEC_MM,
+ &keep_head_id);
+ if (cur_dispbuf_el) {
+ if (cur_dispbuf->type & VIDTYPE_SCATTER)
+ type = MEM_TYPE_CODEC_MM_SCATTER;
+ else
+ type = MEM_TYPE_CODEC_MM;
+ video_keeper_update_keeper_mem(
+ cur_dispbuf_el->mem_handle,
+ type,
+ &keep_el_id);
+ video_keeper_update_keeper_mem(
+ cur_dispbuf_el->mem_head_handle,
+ MEM_TYPE_CODEC_MM,
+ &keep_el_head_id);
+ }
+}
+
+/*
+ * call in irq.
+ *don't used mutex
+ */
void video_keeper_new_frame_notify(void)
{
if (keep_video_on) {
- pr_info("new toggle keep_id\n");
+ pr_info("new frame show, free keeper\n");
keep_video_on = 0;
}
if (keep_id > 0) {
/*wait 80 ms for vsync post.*/
- pr_info("new frame show, free keeper\n");
codec_mm_keeper_unmask_keeper(keep_id, 120);
keep_id = -1;
}
if (keep_head_id > 0) {
/*wait 80 ms for vsync post.*/
- pr_info("new frame show, free keeper head\n");
codec_mm_keeper_unmask_keeper(keep_head_id, 120);
keep_head_id = -1;
}
+ if (keep_el_id > 0) {
+ /*wait 80 ms for vsync post.*/
+ codec_mm_keeper_unmask_keeper(keep_el_id, 120);
+ keep_el_id = -1;
+ }
+ if (keep_el_head_id > 0) {
+ /*wait 80 ms for vsync post.*/
+ codec_mm_keeper_unmask_keeper(keep_el_head_id, 120);
+ keep_el_head_id = -1;
+ }
return;
}
-static unsigned int vf_keep_current_locked(struct vframe_s *cur_dispbuf)
+static unsigned int vf_keep_current_locked(
+ struct vframe_s *cur_dispbuf,
+ struct vframe_s *cur_dispbuf_el)
{
u32 cur_index;
u32 y_index, u_index, v_index;
pr_info("keep exit is skip VPP_VD1_POSTBLEND\n");
return 0;
}
- if (1) {
- int ret;
- int old_keep = keep_id;
- int old_head_keep = keep_head_id;
- int type = MEM_TYPE_CODEC_MM;
-
- if (cur_dispbuf->type & VIDTYPE_SCATTER)
- type = MEM_TYPE_CODEC_MM_SCATTER;
- ret = codec_mm_keeper_mask_keep_mem(cur_dispbuf->mem_handle,
- type);
- if (ret > 0) {
- keep_id = ret;
- if (old_keep > 0 && keep_id != old_keep) {
- /*wait 80 ms for vsync post.*/
- codec_mm_keeper_unmask_keeper(old_keep, 120);
- }
- }
- ret = codec_mm_keeper_mask_keep_mem(
- cur_dispbuf->mem_head_handle,
- MEM_TYPE_CODEC_MM);
- if (ret > 0) {
- keep_head_id = ret;
- if (old_head_keep > 0 &&
- keep_head_id != old_head_keep) {
- /*wait 80 ms for vsync post.*/
- codec_mm_keeper_unmask_keeper(old_head_keep,
- 120);
- }
- }
- }
+ video_keeper_frame_keep_locked(cur_dispbuf,
+ cur_dispbuf_el);
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
if (codec_mm_video_tvp_enabled()) {
return 0;
}
-unsigned int vf_keep_current(struct vframe_s *cur_dispbuf)
+unsigned int vf_keep_current(
+ struct vframe_s *cur_dispbuf,
+ struct vframe_s *cur_dispbuf2)
{
unsigned int ret;
mutex_lock(&video_keeper_mutex);
- ret = vf_keep_current_locked(cur_dispbuf);
+ ret = vf_keep_current_locked(cur_dispbuf,
+ cur_dispbuf2);
mutex_unlock(&video_keeper_mutex);
return ret;
}
next_frame_par->supsc1_hori_ratio = 0;
else
next_frame_par->supsc1_hori_ratio = 1;
+ /* disble sp1 for this case */
+ if ((vpp_wide_mode == VIDEO_WIDEOPTION_NONLINEAR)
+ && (next_frame_par->supscl_path
+ == sup0_pp_sp1_scpath))
+ next_frame_par->supsc1_hori_ratio = 0;
next_frame_par->supsc0_enable =
(next_frame_par->supsc0_hori_ratio ||
next_frame_par->supsc0_enable) ? 1 : 0;
next_frame_par->supsc1_vert_ratio;
}
+ if ((vpp_wide_mode == VIDEO_WIDEOPTION_NONLINEAR) &&
+ (next_frame_par->VPP_hsc_endp >
+ next_frame_par->VPP_hsc_startp)) {
+ s32 start, end;
+ struct vppfilter_mode_s *filter =
+ &next_frame_par->vpp_filter;
+ start = next_frame_par->VPP_hsc_startp;
+ end = next_frame_par->VPP_hsc_endp;
+ calculate_non_linear_ratio(
+ (filter->vpp_hsc_start_phase_step >> 6),
+ end - start,
+ next_frame_par);
+ next_frame_par->VPP_hsc_linear_startp =
+ next_frame_par->VPP_hsc_linear_endp = (start + end) / 2;
+ }
if (h_crop_enable) {
next_frame_par->VPP_hd_start_lines_ += video_source_crop_left;
next_frame_par->VPP_hd_end_lines_ += video_source_crop_left;
--- /dev/null
+config AMLOGIC_TEE
+ tristate "TEE Support for Amlogic"
+ default n
+ help
+ Amlogic TEE driver
+
+ Provide TEE APIs and Debug interface in sysfs, depends on the
+ tee os.
--- /dev/null
+obj-$(CONFIG_AMLOGIC_TEE) += tee.o
--- /dev/null
+/*
+ * drivers/amlogic/tee/tee.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/kernel.h>
+#include <linux/module.h>
+#include <linux/arm-smccc.h>
+#include <linux/platform_device.h>
+
+#include <linux/amlogic/tee.h>
+
+#define DRIVER_NAME "tee_info"
+#define DRIVER_DESC "Amlogic tee driver"
+
+#define TEE_MSG_UID_0 0x384fb3e0
+#define TEE_MSG_UID_1 0xe7f811e3
+#define TEE_MSG_UID_2 0xaf630002
+#define TEE_MSG_UID_3 0xa5d5c51b
+
+#define TEE_SMC_FUNCID_CALLS_REVISION 0xFF03
+#define TEE_SMC_CALLS_REVISION \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+ TEE_SMC_FUNCID_CALLS_REVISION)
+
+#define TEE_SMC_FUNCID_CALLS_UID 0xFF01
+#define TEE_SMC_CALLS_UID \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+ TEE_SMC_FUNCID_CALLS_UID)
+
+
+#define TEE_SMC_FAST_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+
+#define TEE_SMC_FUNCID_GET_OS_REVISION 0x0001
+#define TEE_SMC_CALL_GET_OS_REVISION \
+ TEE_SMC_FAST_CALL_VAL(TEE_SMC_FUNCID_GET_OS_REVISION)
+
+#define TEE_SMC_FUNCID_LOAD_VIDEO_FW 15
+#define TEE_SMC_LOAD_VIDEO_FW \
+ TEE_SMC_FAST_CALL_VAL(TEE_SMC_FUNCID_LOAD_VIDEO_FW)
+
+static struct class *tee_sys_class;
+
+struct tee_smc_calls_revision_result {
+ unsigned long major;
+ unsigned long minor;
+ unsigned long reserved0;
+ unsigned long reserved1;
+};
+
+static int tee_msg_os_revision(uint32_t *major, uint32_t *minor)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct tee_smc_calls_revision_result result;
+ } res;
+
+ arm_smccc_smc(TEE_SMC_CALL_GET_OS_REVISION,
+ 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+ *major = res.result.major;
+ *minor = res.result.minor;
+
+ return 0;
+}
+
+static int tee_msg_api_revision(uint32_t *major, uint32_t *minor)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct tee_smc_calls_revision_result result;
+ } res;
+
+ arm_smccc_smc(TEE_SMC_CALLS_REVISION,
+ 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+ *major = res.result.major;
+ *minor = res.result.minor;
+
+ return 0;
+}
+
+static ssize_t tee_os_version_show(struct class *class,
+ struct class_attribute *attr, char *buf)
+{
+ int ret;
+ uint32_t major, minor;
+
+ ret = tee_msg_os_revision(&major, &minor);
+ if (ret)
+ return 0;
+
+ ret = sprintf(buf, "os version: V%d.%d\n", major, minor);
+
+ return ret;
+}
+
+static ssize_t tee_api_version_show(struct class *class,
+ struct class_attribute *attr, char *buf)
+{
+ int ret;
+ uint32_t major, minor;
+
+ ret = tee_msg_api_revision(&major, &minor);
+ if (ret)
+ return 0;
+
+ ret = sprintf(buf, "api version: V%d.%d\n", major, minor);
+
+ return ret;
+}
+
+static CLASS_ATTR(os_version, 0644, tee_os_version_show,
+ NULL);
+static CLASS_ATTR(api_version, 0644, tee_api_version_show,
+ NULL);
+
+int tee_load_video_fw(uint32_t index)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW,
+ index, 0, 0, 0, 0, 0, 0, &res);
+
+ return res.a0;
+}
+EXPORT_SYMBOL(tee_load_video_fw);
+
+bool tee_enabled(void)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(TEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0 == TEE_MSG_UID_0 && res.a1 == TEE_MSG_UID_1 &&
+ res.a2 == TEE_MSG_UID_2 && res.a3 == TEE_MSG_UID_3)
+ return true;
+ return false;
+}
+EXPORT_SYMBOL(tee_enabled);
+
+int tee_create_sysfs(void)
+{
+ int ret;
+
+ tee_sys_class = class_create(THIS_MODULE, DRIVER_NAME);
+ ret = class_create_file(tee_sys_class, &class_attr_os_version);
+ if (ret != 0) {
+ pr_err("create class file os_version fail\n");
+ return ret;
+ }
+ ret = class_create_file(tee_sys_class, &class_attr_api_version);
+ if (ret != 0) {
+ pr_err("create class file os_version fail\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int __init aml_tee_modinit(void)
+{
+ return tee_create_sysfs();
+}
+
+arch_initcall(aml_tee_modinit);
+
+static void __exit aml_tee_modexit(void)
+{
+ class_destroy(tee_sys_class);
+}
+
+module_exit(aml_tee_modexit);
+
+MODULE_AUTHOR("pengguang.zhu<pengguang.zhu@amlogic.com>");
+MODULE_DESCRIPTION(DRIVER_TEE);
+MODULE_LICENSE("GPL");
extern void timestamp_pcrscr_set_adj(s32 inc);
+extern void timestamp_pcrscr_set_adj_pcr(s32 inc);
+
extern void timestamp_apts_enable(u32 enable);
extern void timestamp_apts_start(u32 enable);
#define AMSTREAM_SET_FRAME_BASE_PATH 0x174
#define AMSTREAM_SET_EOS 0x175
#define AMSTREAM_SET_RECEIVE_ID 0x176
+#define AMSTREAM_SET_IS_RESET 0x177
/* video set ex cmd */
#define AMSTREAM_SET_EX_VIDEO_AXIS 0x260
#ifdef CONFIG_AM_VIDEO2
extern void set_clone_frame_rate(unsigned int frame_rate, unsigned int delay);
#endif
+extern struct vframe_provider_s *vf_get_provider_by_name(
+ const char *provider_name);
extern void prot_get_parameter(u32 wide_mode, struct vframe_s *vf,
struct vpp_frame_par_s *next_frame_par,
int __init video_keeper_init(void);
void __exit video_keeper_exit(void);
-unsigned int vf_keep_current(struct vframe_s *cur_dispbuf);
+unsigned int vf_keep_current(
+ struct vframe_s *cur_dispbuf,
+ struct vframe_s *cur_dispbuf2);
#endif
--- /dev/null
+/*
+ * include/linux/amlogic/tee.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef __TEE_H__
+#define __TEE_H__
+
+extern bool tee_enabled(void);
+extern int is_secload_get(void);
+extern int tee_load_video_fw(uint32_t index);
+#endif /* __TEE_H__ */
+