blob: 27566910b1febc0520af1317df00c7d2c22278c9 [file] [log] [blame]
/*
* drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.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/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/platform_device.h>
/*#include <mach/am_regs.h>*/
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/canvas/canvas.h>
#include <linux/amlogic/media/canvas/canvas_mgr.h>
#include <linux/amlogic/media/vout/vinfo.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vfm/vframe.h>
/*#include <linux/amlogic/amports/vfp.h>*/
#include "vfp.h"
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/utils/amlog.h>
#include <linux/amlogic/cpu_version.h>
/*#include <linux/amlogic/ge2d/ge2d_main.h>*/
#include <linux/amlogic/media/ge2d/ge2d.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/sched/rt.h>
#include "ppmgr_log.h"
#include "ppmgr_pri.h"
#include "ppmgr_dev.h"
#include <linux/mm.h>
#include <linux/amlogic/media/ppmgr/ppmgr.h>
#include <linux/amlogic/media/ppmgr/ppmgr_status.h>
/*#include "../amports/video.h"*/
#include <linux/amlogic/media/video_sink/video.h>
/*#include "../amports/vdec_reg.h"*/
#include <linux/amlogic/media/utils/vdec_reg.h>
/*#include "../display/osd/osd_reg.h"*/
#include "../../osd/osd_reg.h"
#include "ppmgr_vpp.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/amlogic/media/ppmgr/tbff.h>
#include "../../../media_modules/frame_provider/decoder/utils/decoder_bmmu_box.h"
/*#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/
/*#include <mach/mod_gate.h>*/
/*#endif*/
#define PPMGRVPP_INFO(fmt, args...) pr_info("PPMGRVPP: info: "fmt"", ## args)
#define PPMGRVPP_DBG(fmt, args...) pr_debug("PPMGRVPP: dbg: "fmt"", ## args)
#define PPMGRVPP_WARN(fmt, args...) pr_warn("PPMGRVPP: warn: "fmt"", ## args)
#define PPMGRVPP_ERR(fmt, args...) pr_err("PPMGRVPP: err: "fmt"", ## args)
#define VF_POOL_SIZE 5
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
#define ASS_POOL_SIZE 2
#else
#define ASS_POOL_SIZE 1
#endif
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
#define MASK_POOL_SIZE 1
#else
#define MASK_POOL_SIZE 0
#endif
#define ALLOC_CANVAS0_INDEX0 0x4b
#define ALLOC_CANVAS0_INDEX1 0x4c
#define ALLOC_CANVAS0_INDEX2 0x4d
#define ALLOC_CANVAS1_INDEX0 0x48
#define ALLOC_CANVAS1_INDEX1 0x49
#define ALLOC_CANVAS1_INDEX2 0x4a
#define ALLOC_CANVAS0 0x4d4c4b
#define ALLOC_CANVAS1 0x4a4948
//#define PPMGR_TB_DETECT
#define RECEIVER_NAME "ppmgr"
#define PROVIDER_NAME "ppmgr"
#define MM_ALLOC_SIZE SZ_16M
#define MAX_WIDTH 1088
#define MAX_HEIGHT 1920
#define THREAD_INTERRUPT 0
#define THREAD_RUNNING 1
#define INTERLACE_DROP_MODE 1
#define EnableVideoLayer() \
SET_MPEG_REG_MASK(VPP_MISC, \
(VPP_VD1_PREBLEND) | (VPP_PREBLEND_EN) | (VPP_VD1_POSTBLEND))
#define DisableVideoLayer() \
CLEAR_MPEG_REG_MASK(VPP_MISC, \
(VPP_VD1_PREBLEND)|(VPP_VD1_POSTBLEND))
#define DisableVideoLayer_PREBELEND() \
CLEAR_MPEG_REG_MASK(VPP_MISC, \
VPP_VD1_PREBLEND)
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static int ass_index;
static int backup_index = -1;
static int backup_content_w = 0, backup_content_h;
static int scaler_x, scaler_y, scaler_w, scaler_h;
static int scale_clear_count;
static int scaler_pos_changed;
/* extern bool get_scaler_pos_reset(void); */
/* extern void set_scaler_pos_reset(bool flag); */
/* extern u32 amvideo_get_scaler_mode(void); */
/* extern u32 amvideo_get_scaler_para(
* int *x, int *y, int *w, int *h, u32 *ratio);
*/
#endif
static DEFINE_SPINLOCK(lock);
static bool ppmgr_blocking;
static bool ppmgr_inited;
static int ppmgr_reset_type;
static int ppmgr_buffer_status;
static struct ppframe_s vfp_pool[VF_POOL_SIZE];
static struct vframe_s *vfp_pool_free[VF_POOL_SIZE + 1];
static struct vframe_s *vfp_pool_ready[VF_POOL_SIZE + 1];
struct buf_status_s {
int index;
int dirty;
};
static struct buf_status_s buf_status[VF_POOL_SIZE];
struct vfq_s q_ready, q_free;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static int display_mode_change = VF_POOL_SIZE;
#endif
static struct semaphore thread_sem;
static DEFINE_MUTEX(ppmgr_mutex);
static bool ppmgr_quit_flag;
struct bmmu_info_s {
unsigned long phy_addr;
void *mem_handle;
};
static struct bmmu_info_s bmmu_info[VF_POOL_SIZE];
#ifdef PPMGR_TB_DETECT
#define TB_DETECT_BUFFER_MAX_SIZE 16
#define TB_DETECT_W 128
#define TB_DETECT_H 96
struct tb_buf_s {
ulong vaddr;
ulong paddr;
};
enum tb_status {
tb_idle,
tb_running,
tb_done,
};
static DEFINE_MUTEX(tb_mutex);
static struct tb_buf_s detect_buf[TB_DETECT_BUFFER_MAX_SIZE];
static struct task_struct *tb_detect_task;
static int tb_task_running;
static struct semaphore tb_sem;
static atomic_t detect_status;
static atomic_t tb_detect_flag;
static u8 tb_detect_last_flag;
static u32 tb_buff_wptr;
static u32 tb_buff_rptr;
static s32 tb_canvas = -1;
static u32 tb_src_canvas;
static s8 tb_buffer_status;
static u32 tb_buffer_start;
static u32 tb_buffer_size;
static u8 tb_first_frame_type;
static u32 tb_buffer_len = TB_DETECT_BUFFER_MAX_SIZE;
static atomic_t tb_reset_flag;
static u32 tb_init_mute;
static atomic_t tb_skip_flag;
static bool tb_quit_flag;
static struct TB_DetectFuncPtr *gfunc;
static int tb_buffer_init(void);
#endif
const struct vframe_receiver_op_s *vf_ppmgr_reg_provider(void);
/* void vf_ppmgr_unreg_provider(void);
* void vf_ppmgr_reset(int type);
* void ppmgr_vf_put_dec(struct vframe_s *vf);
*/
/* extern u32 timestamp_pcrscr_enable_state(void); */
#define is_valid_ppframe(pp_vf) \
((pp_vf >= &vfp_pool[0]) && (pp_vf <= &vfp_pool[VF_POOL_SIZE-1]))
/* ***********************************************
*
* Canvas helpers.
*
* ************************************************
*/
static u32 ppmgr_canvas_tab[8] = {
PPMGR_CANVAS_INDEX + 0,
PPMGR_CANVAS_INDEX + 1,
PPMGR_CANVAS_INDEX + 2,
PPMGR_CANVAS_INDEX + 3,
PPMGR_CANVAS_INDEX + 4,
PPMGR_CANVAS_INDEX + 5,
PPMGR_CANVAS_INDEX + 6,
PPMGR_CANVAS_INDEX + 7};
u32 index2canvas(u32 index)
{
return ppmgr_canvas_tab[index];
}
void canvas2cs(struct vframe_s *vf, int set, struct canvas_s *pCanvas0,
struct canvas_s *pCanvas1, struct canvas_s *pCanvas2)
{
u32 canvasSet = (set == 0) ? vf->canvas0Addr : vf->canvas1Addr;
if (canvasSet == -1) {
if (set == 0) {
canvas_config_config(ALLOC_CANVAS0_INDEX0,
&vf->canvas0_config[0]);
canvas_config_config(ALLOC_CANVAS0_INDEX1,
&vf->canvas0_config[1]);
canvas_config_config(ALLOC_CANVAS0_INDEX2,
(vf->plane_num <= 2) ?
&vf->canvas0_config[1] :
&vf->canvas0_config[2]);
canvasSet = ALLOC_CANVAS0;
} else {
canvas_config_config(ALLOC_CANVAS1_INDEX0,
&vf->canvas1_config[0]);
canvas_config_config(ALLOC_CANVAS1_INDEX1,
&vf->canvas1_config[1]);
canvas_config_config(ALLOC_CANVAS1_INDEX2,
(vf->plane_num <= 2) ?
&vf->canvas1_config[1] :
&vf->canvas1_config[2]);
canvasSet = ALLOC_CANVAS1;
}
}
canvas_read(canvasSet & 0xff, pCanvas0);
canvas_read((canvasSet >> 8) & 0xff, pCanvas1);
canvas_read((canvasSet >> 16) & 0xff, pCanvas2);
}
void canvas2cs_index(struct vframe_s *vf, int set,
int index, struct canvas_s *pCanvas)
{
u32 canvasSet = (set == 0) ? vf->canvas0Addr : vf->canvas1Addr;
if (canvasSet == -1) {
if (set == 0) {
canvas_config_config(ALLOC_CANVAS0_INDEX0
+ index, &vf->canvas0_config[index]);
canvasSet = ALLOC_CANVAS0;
} else {
canvas_config_config(ALLOC_CANVAS1_INDEX0
+ index, &vf->canvas1_config[index]);
canvasSet = ALLOC_CANVAS1;
}
}
canvas_read((canvasSet >> (8 * index)) & 0xff, pCanvas);
}
/* ***********************************************
*
* ppmgr as a frame provider
*
* ***********************************************
*/
static int task_running;
static int still_picture_notify;
/*static int q_free_set = 0 ;*/
static struct vframe_s *ppmgr_vf_peek(void *op_arg)
{
struct vframe_s *vf;
if (ppmgr_blocking)
return NULL;
vf = vfq_peek(&q_ready);
return vf;
}
static struct vframe_s *ppmgr_vf_get(void *op_arg)
{
if (ppmgr_blocking)
return NULL;
return vfq_pop(&q_ready);
}
/*recycle vframe belongs to amvideo*/
static void ppmgr_vf_video_put(struct ppframe_s *pp)
{
struct ppframe_s *pp_vf = pp;
struct ppframe_s *vf_local;
int i = vfq_level(&q_free);
int index;
while (i > 0) {
index = (q_free.rp + i - 1) % (q_free.size);
vf_local = to_ppframe(q_free.pool[index]);
if (vf_local->index == pp_vf->index)
return;
i--;
}
i = vfq_level(&q_ready);
while (i > 0) {
index = (q_ready.rp + i - 1) % (q_ready.size);
vf_local = to_ppframe(q_ready.pool[index]);
if (vf_local->index == pp_vf->index)
return;
i--;
}
/* the frame is in bypass mode, put the decoder frame */
if (pp_vf->dec_frame) {
ppmgr_vf_put_dec(pp_vf->dec_frame);
pp_vf->dec_frame = NULL;
}
}
static void ppmgr_vf_put(struct vframe_s *vf, void *op_arg)
{
struct ppframe_s *vf_local;
int i;
int index;
struct ppframe_s *pp_vf = to_ppframe(vf);
if (ppmgr_blocking)
return;
i = vfq_level(&q_free);
while (i > 0) {
index = (q_free.rp + i - 1) % (q_free.size);
vf_local = to_ppframe(q_free.pool[index]);
if (vf_local->index == pp_vf->index)
return;
i--;
}
i = vfq_level(&q_ready);
while (i > 0) {
index = (q_ready.rp + i - 1) % (q_ready.size);
vf_local = to_ppframe(q_ready.pool[index]);
if (vf_local->index == pp_vf->index)
return;
i--;
}
/* the frame is in bypass mode, put the decoder frame */
if (pp_vf->dec_frame) {
ppmgr_vf_put_dec(pp_vf->dec_frame);
pp_vf->dec_frame = NULL;
}
vfq_push(&q_free, vf);
}
int vf_ppmgr_get_states(struct vframe_states *states)
{
int ret = -1;
unsigned long flags;
struct vframe_provider_s *vfp;
vfp = vf_get_provider(RECEIVER_NAME);
spin_lock_irqsave(&lock, flags);
if (vfp && vfp->ops && vfp->ops->vf_states)
ret = vfp->ops->vf_states(states, vfp->op_arg);
spin_unlock_irqrestore(&lock, flags);
return ret;
}
static int get_input_format(struct vframe_s *vf)
{
int format = GE2D_FORMAT_M24_YUV420;
if (vf->type & VIDTYPE_VIU_422) {
#if 0
if (vf->type & VIDTYPE_INTERLACE_BOTTOM)
format =
GE2D_FORMAT_S16_YUV422|
(GE2D_FORMAT_S16_YUV422B & (3<<3));
else if (vf->type & VIDTYPE_INTERLACE_TOP)
format =
GE2D_FORMAT_S16_YUV422|
(GE2D_FORMAT_S16_YUV422T & (3<<3));
else
format = GE2D_FORMAT_S16_YUV422;
#else
if (vf->type & VIDTYPE_INTERLACE_BOTTOM) {
format = GE2D_FORMAT_S16_YUV422;
} else if (vf->type & VIDTYPE_INTERLACE_TOP) {
format = GE2D_FORMAT_S16_YUV422;
} else {
format = GE2D_FORMAT_S16_YUV422
| (GE2D_FORMAT_S16_YUV422T & (3 << 3));
}
#endif
} else if (vf->type & VIDTYPE_VIU_NV21) {
if (vf->type & VIDTYPE_INTERLACE_BOTTOM)
format =
GE2D_FORMAT_M24_NV21 |
(GE2D_FORMAT_M24_NV21B & (3 << 3));
else if (vf->type & VIDTYPE_INTERLACE_TOP)
format =
GE2D_FORMAT_M24_NV21
| (GE2D_FORMAT_M24_NV21T & (3 << 3));
else
format = GE2D_FORMAT_M24_NV21;
} else {
if (vf->type & VIDTYPE_INTERLACE_BOTTOM) {
format = GE2D_FORMAT_M24_YUV420
| (GE2D_FMT_M24_YUV420B & (3 << 3));
} else if (vf->type & VIDTYPE_INTERLACE_TOP) {
format = GE2D_FORMAT_M24_YUV420
| (GE2D_FORMAT_M24_YUV420T & (3 << 3));
} else {
format = GE2D_FORMAT_M24_YUV420;
}
}
return format;
}
#if 0
static void dma_flush(u32 buf_start, u32 buf_size)
{
return;
/*
dma_sync_single_for_device(
&ppmgr_device.pdev->dev, buf_start,
buf_size, DMA_TO_DEVICE);
*/
}
#endif
/* extern int get_property_change(void); */
/* extern void set_property_change(int flag); */
/* extern int get_buff_change(void); */
/* extern void set_buff_change(int flag); */
static int ppmgr_event_cb(int type, void *data, void *private_data)
{
if (type & VFRAME_EVENT_RECEIVER_PUT) {
#ifdef DDD
PPMGRVPP_WARN("video put, avail=%d, free=%d\n",
vfq_level(&q_ready), vfq_level(&q_free));
#endif
up(&thread_sem);
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (type & VFRAME_EVENT_RECEIVER_POS_CHANGED) {
if (task_running) {
scaler_pos_changed = 1;
/*printk("--ppmgr: get pos changed msg.\n");*/
up(&thread_sem);
}
}
#endif
if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) {
if (task_running && !ppmgr_device.use_prot) {
if (timestamp_pcrscr_enable_state())
return 0;
if (get_property_change()) {
/*printk("--ppmgr: get angle changed msg.\n");*/
set_property_change(0);
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (!amvideo_get_scaler_mode()) {
still_picture_notify = 1;
up(&thread_sem);
}
#else
still_picture_notify = 1;
up(&thread_sem);
#endif
} else {
up(&thread_sem);
}
}
}
#ifdef CONFIG_V4L_AMLOGIC_VIDEO
if ((type & VFRAME_EVENT_RECEIVER_PARAM_SET)) {
unsigned int *eventparam = (unsigned int *)data;
ppmgr_device.canvas_width = eventparam[0];
ppmgr_device.canvas_height = eventparam[1];
ppmgr_device.receiver_format = eventparam[2];
/* ppmgr_buffer_init(0); */
}
#endif
return 0;
}
static int ppmgr_vf_states(struct vframe_states *states, void *op_arg)
{
unsigned long flags;
spin_lock_irqsave(&lock, flags);
states->vf_pool_size = VF_POOL_SIZE;
states->buf_recycle_num = 0;
states->buf_free_num = vfq_level(&q_free);
states->buf_avail_num = vfq_level(&q_ready);
spin_unlock_irqrestore(&lock, flags);
return 0;
}
static const struct vframe_operations_s ppmgr_vf_provider = {
.peek = ppmgr_vf_peek,
.get = ppmgr_vf_get,
.put = ppmgr_vf_put,
.event_cb = ppmgr_event_cb,
.vf_states = ppmgr_vf_states, };
static struct vframe_provider_s ppmgr_vf_prov;
/************************************************
*
* ppmgr as a frame receiver
*
*************************************************/
static int ppmgr_receiver_event_fun(int type, void *data, void*);
static const struct vframe_receiver_op_s ppmgr_vf_receiver = {.event_cb =
ppmgr_receiver_event_fun};
static struct vframe_receiver_s ppmgr_vf_recv;
static int ppmgr_receiver_event_fun(int type, void *data, void *private_data)
{
struct vframe_states states;
switch (type) {
case VFRAME_EVENT_PROVIDER_VFRAME_READY:
#ifdef DDD
PPMGRVPP_WARN("dec put, avail=%d, free=%d\n",
vfq_level(&q_ready), vfq_level(&q_free));
#endif
up(&thread_sem);
break;
case VFRAME_EVENT_PROVIDER_QUREY_STATE:
ppmgr_vf_states(&states, NULL);
if (states.buf_avail_num > 0)
return RECEIVER_ACTIVE;
if (vf_notify_receiver(
PROVIDER_NAME,
VFRAME_EVENT_PROVIDER_QUREY_STATE,
NULL)
== RECEIVER_ACTIVE)
return RECEIVER_ACTIVE;
return RECEIVER_INACTIVE;
case VFRAME_EVENT_PROVIDER_START:
#ifdef DDD
PPMGRVPP_WARN("register now\n");
#endif
vf_ppmgr_reg_provider();
vf_notify_receiver(
PROVIDER_NAME,
VFRAME_EVENT_PROVIDER_START,
NULL);
break;
case VFRAME_EVENT_PROVIDER_UNREG:
#ifdef DDD
PPMGRVPP_WARN("unregister now\n");
#endif
vf_ppmgr_unreg_provider();
break;
case VFRAME_EVENT_PROVIDER_LIGHT_UNREG:
break;
case VFRAME_EVENT_PROVIDER_RESET:
vf_ppmgr_reset(0);
vf_notify_receiver(
PROVIDER_NAME,
VFRAME_EVENT_PROVIDER_RESET,
NULL);
break;
case VFRAME_EVENT_PROVIDER_FR_HINT:
case VFRAME_EVENT_PROVIDER_FR_END_HINT:
vf_notify_receiver(PROVIDER_NAME, type, data);
break;
case VFRAME_EVENT_PROVIDER_QUREY_FRAME_NOHOLDING:
return 1;
default:
break;
}
return 0;
}
void vf_local_init(void)
{
int i;
set_property_change(0);
still_picture_notify = 0;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
scaler_pos_changed = 0;
scaler_x = scaler_y = scaler_w = scaler_h = 0;
backup_content_w = backup_content_h = 0;
#endif
vfq_init(&q_free, VF_POOL_SIZE + 1, &vfp_pool_free[0]);
vfq_init(&q_ready, VF_POOL_SIZE + 1, &vfp_pool_ready[0]);
for (i = 0; i < VF_POOL_SIZE; i++) {
vfp_pool[i].index = i;
vfp_pool[i].dec_frame = NULL;
vfq_push(&q_free, &vfp_pool[i].frame);
}
for (i = 0; i < VF_POOL_SIZE; i++) {
buf_status[i].index = ppmgr_canvas_tab[i];
buf_status[i].dirty = 1;
}
sema_init(&thread_sem, 1);
}
static const struct vframe_provider_s *dec_vfp;
const struct vframe_receiver_op_s *vf_ppmgr_reg_provider(void)
{
const struct vframe_receiver_op_s *r = NULL;
mutex_lock(&ppmgr_mutex);
vf_local_init();
vf_reg_provider(&ppmgr_vf_prov);
if (start_ppmgr_task() == 0)
r = &ppmgr_vf_receiver;
ppmgr_device.started = 1;
mutex_unlock(&ppmgr_mutex);
return r;
}
void vf_ppmgr_unreg_provider(void)
{
mutex_lock(&ppmgr_mutex);
stop_ppmgr_task();
vf_unreg_provider(&ppmgr_vf_prov);
/*
* For last frame, can only free buff
* after receiver has increased the index
* of codec_mm_s
*/
ppmgr_buffer_uninit();
dec_vfp = NULL;
ppmgr_device.started = 0;
/*ppmgr_device.use_prot = 0;*/
mutex_unlock(&ppmgr_mutex);
}
/*skip the second reset request*/
static unsigned long last_reset_time;
static unsigned long current_reset_time;
#define PPMGR_RESET_INTERVAL (HZ/5)
void vf_ppmgr_reset(int type)
{
if (ppmgr_inited) {
current_reset_time = jiffies;
if (abs(current_reset_time-last_reset_time)
< PPMGR_RESET_INTERVAL)
return;
ppmgr_blocking = true;
ppmgr_reset_type = type;
up(&thread_sem);
last_reset_time = current_reset_time;
}
}
void vf_ppmgr_init_receiver(void)
{
vf_receiver_init(
&ppmgr_vf_recv,
RECEIVER_NAME,
&ppmgr_vf_receiver,
NULL);
}
void vf_ppmgr_reg_receiver(void)
{
vf_reg_receiver(&ppmgr_vf_recv);
}
void vf_ppmgr_init_provider(void)
{
vf_provider_init(
&ppmgr_vf_prov,
PROVIDER_NAME,
&ppmgr_vf_provider,
NULL);
}
static inline struct vframe_s *ppmgr_vf_peek_dec(void)
{
#if 0
struct vframe_provider_s *vfp;
struct vframe_s *vf;
vfp = vf_get_provider(RECEIVER_NAME);
if (!(vfp && vfp->ops && vfp->ops->peek))
return NULL;
vf = vfp->ops->peek(vfp->op_arg);
return vf;
#else
return vf_peek(RECEIVER_NAME);
#endif
}
static inline struct vframe_s *ppmgr_vf_get_dec(void)
{
#if 0
struct vframe_provider_s *vfp;
struct vframe_s *vf;
vfp = vf_get_provider(RECEIVER_NAME);
if (!(vfp && vfp->ops && vfp->ops->peek))
return NULL;
vf = vfp->ops->get(vfp->op_arg);
return vf;
#else
return vf_get(RECEIVER_NAME);
#endif
}
void ppmgr_vf_put_dec(struct vframe_s *vf)
{
#if 0
struct vframe_provider_s *vfp;
vfp = vf_get_provider(RECEIVER_NAME);
if (!(vfp && vfp->ops && vfp->ops->peek))
return;
vfp->ops->put(vf, vfp->op_arg);
#else
vf_put(vf, RECEIVER_NAME);
#endif
}
/************************************************
*
* main task functions.
*
*************************************************/
static void vf_rotate_adjust(struct vframe_s *vf, struct vframe_s *new_vf,
int angle)
{
int w = 0, h = 0, disp_w = 0, disp_h = 0;
int scale_down_value = 1;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
scale_down_value = ppmgr_device.scale_down + 1;
#endif
disp_w = ppmgr_device.disp_width / scale_down_value;
disp_h = ppmgr_device.disp_height / scale_down_value;
if (vf->type & VIDTYPE_COMPRESS) {
new_vf->org_width = vf->compWidth;
new_vf->org_height = vf->compHeight;
} else {
new_vf->org_width = vf->width;
new_vf->org_height = vf->height;
}
if (vf->sar_width && vf->sar_height) {
new_vf->org_width = new_vf->org_width * vf->sar_width
/ vf->sar_height;
}
if (angle & 1) {
int ar = (vf->ratio_control
>> DISP_RATIO_ASPECT_RATIO_BIT) & 0x3ff;
if ((vf->width <= disp_h) && (vf->height <= disp_w)) {
w = vf->height;
h = vf->width;
} else {
h = min_t(int, vf->width, disp_h);
if (ar == 0)
w = vf->height * h / vf->width;
else
w = (ar * h) >> 8;
if (w > disp_w) {
h = (h * disp_w) / w;
w = disp_w;
}
}
new_vf->ratio_control = DISP_RATIO_PORTRAIT_MODE;
new_vf->ratio_control |=
(h * 0x100 / w) << DISP_RATIO_ASPECT_RATIO_BIT;
/*set video aspect ratio*/
} else {
if ((vf->width < disp_w) && (vf->height < disp_h)) {
w = vf->width;
h = vf->height;
} else {
if ((vf->width * disp_h) > (disp_w * vf->height)) {
w = disp_w;
h = disp_w * vf->height / vf->width;
} else {
h = disp_h;
w = disp_h * vf->width / vf->height;
}
}
new_vf->ratio_control = vf->ratio_control;
}
new_vf->width = w;
new_vf->height = h;
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static void display_mode_adjust(struct ge2d_context_s *context,
struct vframe_s *new_vf, int pic_struct)
{
int canvas_width = ppmgr_device.canvas_width;
int canvas_height = ppmgr_device.canvas_height;
int vf_width = new_vf->width;
int vf_height = new_vf->height;
static int current_display_mode;
if (ppmgr_device.display_mode != current_display_mode) {
current_display_mode = ppmgr_device.display_mode;
display_mode_change = VF_POOL_SIZE;
}
if (display_mode_change > 0) {
display_mode_change--;
fillrect(context, 0, 0,
canvas_width, canvas_height, 0x008080ff);
}
if (ppmgr_device.display_mode == 0) {/*stretch full*/
stretchblt_noalpha(context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
0, 0, canvas_width,
canvas_height);
} else if (ppmgr_device.display_mode == 1) {/*keep size*/
stretchblt_noalpha(context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
(canvas_width - vf_width) / 2,
(canvas_height - vf_height) / 2,
vf_width, vf_height);
} else if (ppmgr_device.display_mode == 2) {/*keep ration black*/
int dw = 0, dh = 0;
if (vf_width / vf_height >= canvas_width / canvas_height) {
dw = canvas_width;
dh = dw * vf_height / vf_width;
stretchblt_noalpha(context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
(canvas_width - dw) / 2,
(canvas_height - dh) / 2, dw, dh);
} else {
dh = canvas_height;
dw = dh * vf_width / vf_height;
stretchblt_noalpha(context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
(canvas_width - dw) / 2,
(canvas_height - dh) / 2, dw, dh);
}
} else if (ppmgr_device.display_mode == 3) {
int dw = 0, dh = 0;
if (vf_width / vf_height
>= canvas_width / canvas_height) {
dh = canvas_height;
dw = dh * vf_width / vf_height;
stretchblt_noalpha(
context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
(canvas_width - dw) / 2,
(canvas_height - dh) / 2, dw, dh);
} else {
dw = canvas_width;
dh = dw * vf_height / vf_width;
stretchblt_noalpha(context, 0, 0, vf_width,
(pic_struct) ? (vf_height / 2) : vf_height,
(canvas_width - dw) / 2,
(canvas_height - dh) / 2, dw, dh);
}
}
}
#endif
#ifdef PPMGR_TB_DETECT
static int process_vf_tb_detect(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct canvas_s cs0, cs1, cs2, cd;
int interlace_mode;
struct vframe_s src_vf;
u32 format = GE2D_FORMAT_M24_YUV420;
u32 h_scale_coef_type =
context->config.h_scale_coef_type;
u32 v_scale_coef_type =
context->config.v_scale_coef_type;
if (unlikely(!vf))
return -1;
interlace_mode = vf->type & VIDTYPE_TYPEMASK;
if (!interlace_mode)
return 0;
if (vf->type & VIDTYPE_VIU_422)
format = GE2D_FORMAT_S16_YUV422;
else if (vf->type & VIDTYPE_VIU_NV21)
format = GE2D_FORMAT_M24_NV21;
else
format = GE2D_FORMAT_M24_YUV420;
if (tb_buff_wptr & 1) {
format = format
| (GE2D_FORMAT_M24_NV21B & (3 << 3));
context->config.h_scale_coef_type =
FILTER_TYPE_GAU0;
context->config.v_scale_coef_type =
FILTER_TYPE_GAU0_BOT;
} else {
format = format
| (GE2D_FORMAT_M24_NV21T & (3 << 3));
context->config.h_scale_coef_type =
FILTER_TYPE_GAU0;
context->config.v_scale_coef_type =
FILTER_TYPE_GAU0;
}
canvas_config(tb_canvas,
detect_buf[tb_buff_wptr].paddr,
TB_DETECT_W, TB_DETECT_H,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/* 0xff; */
ge2d_config->dst_xy_swap = 0;
canvas2cs(vf, 0, &cs0, &cs1, &cs2);
src_vf = *vf;
if (vf->canvas0Addr == (u32)-1) {
canvas_config_config(
tb_src_canvas & 0xff,
&src_vf.canvas0_config[0]);
canvas_config_config(
(tb_src_canvas >> 8) & 0xff,
&src_vf.canvas0_config[1]);
if (src_vf.plane_num == 2) {
src_vf.canvas0Addr =
tb_src_canvas & 0xffff;
} else if (src_vf.plane_num == 3) {
canvas_config_config(
(tb_src_canvas >> 16) & 0xff,
&src_vf.canvas0_config[2]);
src_vf.canvas0Addr =
tb_src_canvas & 0xffffff;
}
canvas_read(
src_vf.canvas0Addr & 0xff, &cs0);
canvas_read(
(src_vf.canvas0Addr >> 8) & 0xff, &cs1);
canvas_read(
(src_vf.canvas0Addr >> 16) & 0xff, &cs2);
} else {
canvas_read(vf->canvas0Addr & 0xff, &cs0);
canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1);
canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2);
}
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
canvas_read(tb_canvas & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = (src_vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : src_vf->canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = format;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height = vf->height / 2;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = tb_canvas;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format =
GE2D_FORMAT_S8_Y | GE2D_LITTLE_ENDIAN;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = TB_DETECT_W;
ge2d_config->dst_para.height = TB_DETECT_H;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
pr_err("++ge2d configing error.\n");
context->config.h_scale_coef_type =
h_scale_coef_type;
context->config.v_scale_coef_type =
v_scale_coef_type;
return -1;
}
stretchblt_noalpha(
context, 0, 0, vf->width,
vf->height / 2,
0, 0, TB_DETECT_W,
TB_DETECT_H);
codec_mm_dma_flush(
(void *)detect_buf[tb_buff_wptr].vaddr,
TB_DETECT_W * TB_DETECT_H,
DMA_FROM_DEVICE);
context->config.h_scale_coef_type =
h_scale_coef_type;
context->config.v_scale_coef_type =
v_scale_coef_type;
return 1;
}
#endif
static int process_vf_deinterlace_nv21(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct canvas_s cs0, cs1, cs2, cd;
if (!vf)
return -1;
if (vf->type & VIDTYPE_MVC)
return 0;
if (vf->type & VIDTYPE_COMPRESS)
return 0;
if ((vf->canvas0Addr == vf->canvas1Addr) || (ppmgr_device.angle == 0)) {
/*printk("++ppmgr interlace skip.\n");*/
return 0;
}
/* operation top line*/
/* Y data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs(vf, 0, &cs0, &cs1, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
canvas_read(PPMGR_DEINTERLACE_BUF_NV21_CANVAS, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_M24_NV21;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height = vf->height / 2;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_NV21_CANVAS;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = (GE2D_FORMAT_S24_YUV444T & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height / 2;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width, vf->height / 2, 0, 0,
vf->width, vf->height / 2);
/* operation bottom line*/
/*Y data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs(vf, 1, &cs0, &cs1, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
canvas_read(PPMGR_DEINTERLACE_BUF_NV21_CANVAS, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (vf->canvas1Addr == -1) ?
ALLOC_CANVAS1 : vf->canvas1Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_M24_NV21;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height = vf->height / 2;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_NV21_CANVAS;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = (GE2D_FORMAT_S24_YUV444B & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height / 2;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width, vf->height / 2, 0, 0,
vf->width, vf->height / 2);
return 2;
}
static int process_vf_deinterlace(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct canvas_s cs, cd;
int ret = 0;
if (!vf)
return -1;
if (vf->type & VIDTYPE_MVC)
return 0;
if (vf->type & VIDTYPE_COMPRESS)
return 0;
if ((vf->canvas0Addr == vf->canvas1Addr) || (ppmgr_device.bypass)
|| (ppmgr_device.angle == 0)) {
/*printk("++ppmgr interlace skip.\n");*/
return 0;
}
if (vf->type & VIDTYPE_VIU_NV21) {
ret = process_vf_deinterlace_nv21(vf, context, ge2d_config);
return ret;
}
/* operation top line*/
/* Y data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 0, 0, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = ((vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_Y;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height = vf->height / 2;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_Y
| (GE2D_FORMAT_M24_YUV420T & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height / 2;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width, vf->height / 2, 0, 0,
vf->width, vf->height / 2);
/*U data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 0, 1, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 1, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (((vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr) >> 8) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_CB;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width / 2;
ge2d_config->src_para.height = vf->height / 4;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS + 1;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_CB
| (GE2D_FORMAT_M24_YUV420T & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width / 2;
ge2d_config->dst_para.height = vf->height / 4;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width / 2, vf->height / 4, 0, 0,
vf->width / 2, vf->height / 4);
/*V data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 0, 2, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 2, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (((vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr) >> 16) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_CR;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width / 2;
ge2d_config->src_para.height = vf->height / 4;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS + 2;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_CR
| (GE2D_FORMAT_M24_YUV420T & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width / 2;
ge2d_config->dst_para.height = vf->height / 4;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width / 2, vf->height / 4, 0, 0,
vf->width / 2, vf->height / 4);
/* operation bottom line*/
/*Y data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 1, 0, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = ((vf->canvas1Addr == -1) ?
ALLOC_CANVAS1 : vf->canvas1Addr) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_Y;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height = vf->height / 2;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_Y
| (GE2D_FORMAT_M24_YUV420B & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height / 2;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width, vf->height / 2, 0, 0,
vf->width, vf->height / 2);
/*U data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 1, 1, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 1, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (((vf->canvas1Addr == -1) ?
ALLOC_CANVAS1 : vf->canvas1Addr) >> 8) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_CB;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width / 2;
ge2d_config->src_para.height = vf->height / 4;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS + 1;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_CB
| (GE2D_FORMAT_M24_YUV420B & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width / 2;
ge2d_config->dst_para.height = vf->height / 4;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width / 2, vf->height / 4, 0, 0,
vf->width / 2, vf->height / 4);
/*V data*/
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
ge2d_config->dst_xy_swap = 0;
canvas2cs_index(vf, 1, 2, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
ge2d_config->src_planes[1].addr = 0;
ge2d_config->src_planes[1].w = 0;
ge2d_config->src_planes[1].h = 0;
ge2d_config->src_planes[2].addr = 0;
ge2d_config->src_planes[2].w = 0;
ge2d_config->src_planes[2].h = 0;
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 2, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->dst_planes[1].addr = 0;
ge2d_config->dst_planes[1].w = 0;
ge2d_config->dst_planes[1].h = 0;
ge2d_config->dst_planes[2].addr = 0;
ge2d_config->dst_planes[2].w = 0;
ge2d_config->dst_planes[2].h = 0;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_key.key_color = 0;
ge2d_config->src_para.canvas_index = (((vf->canvas1Addr == -1) ?
ALLOC_CANVAS1 : vf->canvas1Addr) >> 16) & 0xff;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FMT_S8_CR;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width / 2;
ge2d_config->src_para.height = vf->height / 4;
ge2d_config->dst_para.canvas_index = PPMGR_DEINTERLACE_BUF_CANVAS + 2;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FMT_S8_CR
| (GE2D_FORMAT_M24_YUV420B & (3 << 3));
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width / 2;
ge2d_config->dst_para.height = vf->height / 4;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -1;
}
stretchblt_noalpha(context, 0, 0, vf->width / 2, vf->height / 4, 0, 0,
vf->width / 2, vf->height / 4);
/*printk("++ppmgr interlace success.\n");*/
return 1;
}
static int mycount;
static void process_vf_rotate(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config,
int deinterlace)
{
struct vframe_s *new_vf;
struct ppframe_s *pp_vf;
struct canvas_s cs0, cs1, cs2, cd;
int ret = 0;
unsigned int cur_angle = 0;
int pic_struct = 0, interlace_mode;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
enum platform_type_t platform_type;
#endif
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
int i;
u32 mode = 0;
int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0;
u32 ratio = 100;
mode = amvideo_get_scaler_para(
&rect_x,
&rect_y,
&rect_w,
&rect_h,
&ratio);
if ((rect_w == 0 || rect_h == 0) && mode) {
rect_w = ppmgr_device.disp_width;
rect_h = ppmgr_device.disp_height;
}
if (ppmgr_device.receiver != 0 && mode) {
rect_w = ppmgr_device.canvas_width;
rect_h = ppmgr_device.canvas_height;
mode = 0;
}
rect_w = max(rect_w, 64);
rect_h = max(rect_h, 64);
#endif
new_vf = vfq_pop(&q_free);
if (unlikely((!new_vf) || (!vf)))
return;
interlace_mode = vf->type & VIDTYPE_TYPEMASK;
pp_vf = to_ppframe(new_vf);
pp_vf->angle = 0;
cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4;
#ifdef CONFIG_V4L_AMLOGIC_VIDEO
if (ppmgr_device.receiver == 0)
pp_vf->dec_frame =
(ppmgr_device.bypass || (cur_angle == 0
&& ppmgr_device.mirror_flag == 0)
|| ppmgr_device.use_prot) ? vf : NULL;
else
pp_vf->dec_frame = NULL;
#else
pp_vf->dec_frame =
(ppmgr_device.bypass
|| (cur_angle == 0
&& ppmgr_device.mirror_flag == 0)
|| ppmgr_device.use_prot) ? vf : NULL;
#endif
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (mode)
pp_vf->dec_frame = NULL;
#endif
if (vf->type & VIDTYPE_MVC)
pp_vf->dec_frame = vf;
if (vf->type & VIDTYPE_COMPRESS)
pp_vf->dec_frame = vf;
if (pp_vf->dec_frame) {
/* bypass mode */
*new_vf = *vf;
vfq_push(&q_ready, new_vf);
return;
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
platform_type = get_platform_type();
if (platform_type == PLATFORM_TV)
ret = ppmgr_buffer_init(1);
else
ret = ppmgr_buffer_init(0);
#else
ret = ppmgr_buffer_init(0);
#endif
if (ret < 0) {
pp_vf->dec_frame = vf;
*new_vf = *vf;
vfq_push(&q_ready, new_vf);
return;
}
#ifdef INTERLACE_DROP_MODE
if (interlace_mode) {
mycount++;
if (mycount % 2 == 0) {
ppmgr_vf_put_dec(vf);
vfq_push(&q_free, new_vf);
return;
}
}
pp_vf->angle = cur_angle;
if (interlace_mode)
new_vf->duration = vf->duration * 2;
else
new_vf->duration = vf->duration;
#else
pp_vf->angle = cur_angle;
new_vf->duration = vf->duration;
#endif
new_vf->mem_handle = bmmu_info[pp_vf->index].mem_handle;
new_vf->mem_sec = vf->mem_sec;
new_vf->duration_pulldown = vf->duration_pulldown;
new_vf->pts = vf->pts;
new_vf->pts_us64 = vf->pts_us64;
new_vf->type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE
| VIDTYPE_VIU_FIELD;
new_vf->canvas0Addr = new_vf->canvas1Addr = index2canvas(pp_vf->index);
new_vf->orientation = vf->orientation;
new_vf->flag = vf->flag;
if (vf->type & VIDTYPE_VIU_422) {
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
vf->height >>= 1;
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
vf->height >>= 1;
else
pic_struct = (GE2D_FORMAT_S16_YUV422T & (3 << 3));
} else if (vf->type & VIDTYPE_VIU_NV21) {
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
pic_struct = (GE2D_FORMAT_M24_NV21T & (3 << 3));
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
pic_struct = (GE2D_FORMAT_M24_NV21B & (3 << 3));
} else {
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
pic_struct = (GE2D_FORMAT_M24_YUV420T & (3 << 3));
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
pic_struct = (GE2D_FORMAT_M24_YUV420B & (3 << 3));
}
#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
vf_rotate_adjust(vf, new_vf, cur_angle);
#else
if (!mode) {
vf_rotate_adjust(vf, new_vf, cur_angle);
scale_clear_count = 0;
} else {
pp_vf->angle = vf->orientation % 4;
cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4;
new_vf->width = ppmgr_device.disp_width;
new_vf->height = ppmgr_device.disp_height;
new_vf->ratio_control =
DISP_RATIO_FORCECONFIG | DISP_RATIO_NO_KEEPRATIO;
if ((rect_x != scaler_x)
|| (rect_w != scaler_w)
|| (rect_y != scaler_y)
|| (rect_h != scaler_h)) {
scale_clear_count = VF_POOL_SIZE;
scaler_x = rect_x;
scaler_y = rect_y;
scaler_w = rect_w;
scaler_h = rect_h;
for (i = 0; i < VF_POOL_SIZE; i++) {
buf_status[i].index = ppmgr_canvas_tab[i];
buf_status[i].dirty = 1;
}
/* printk("--ppmgr new rect x:%d, y:%d,
* w:%d, h:%d.\n", rect_x, rect_y, rect_w, rect_h);
*/
}
if ((!rect_w) || (!rect_h)) {
/*printk("++ppmgr scale out of range 1.\n");*/
ppmgr_vf_put_dec(vf);
vfq_push(&q_free, new_vf);
return;
}
if (((rect_x + rect_w) < 0) || (rect_x >= (int)new_vf->width)
|| ((rect_y + rect_h) < 0)
|| (rect_y >= (int)new_vf->height)) {
/*printk("++ppmgr scale out of range 2.\n");*/
ppmgr_vf_put_dec(vf);
vfq_push(&q_free, new_vf);
return;
}
}
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
for (i = 0; i < VF_POOL_SIZE; i++) {
if (buf_status[i].index == new_vf->canvas0Addr)
break;
}
if (buf_status[i].dirty == 1) {
buf_status[i].dirty = 0;
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(new_vf->canvas0Addr & 0xff, &cd);
ge2d_config->src_planes[0].addr = cd.addr;
ge2d_config->src_planes[0].w = cd.width;
ge2d_config->src_planes[0].h = cd.height;
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = new_vf->canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = new_vf->width;
ge2d_config->src_para.height = new_vf->height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = new_vf->canvas0Addr;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = new_vf->width;
ge2d_config->dst_para.height = new_vf->height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
ppmgr_vf_put_dec(vf);
vfq_push(&q_free, new_vf);
return;
}
fillrect(context, 0, 0,
new_vf->width, new_vf->height, 0x008080ff);
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
}
if ((backup_index > 0) && (mode)) {
unsigned int dst_w = vf->width, dst_h = vf->height;
if ((dst_w > ppmgr_device.disp_width)
|| (dst_h > ppmgr_device.disp_height)) {
if ((dst_w * ppmgr_device.disp_height)
> (dst_h * ppmgr_device.disp_width)) {
dst_h = (dst_w * ppmgr_device.disp_height)
/ ppmgr_device.disp_width;
dst_w = ppmgr_device.disp_width;
} else {
dst_w = (dst_h * ppmgr_device.disp_width)
/ ppmgr_device.disp_height;
dst_h = ppmgr_device.disp_height;
}
dst_w = dst_w & (0xfffffffe);
dst_h = dst_h & (0xfffffffe);
}
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas2cs(vf, 0, &cs0, &cs1, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
canvas_read(new_vf->canvas0Addr & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = (vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = get_input_format(vf);
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height =
(pic_struct) ? (vf->height / 2) : vf->height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = backup_index;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = new_vf->width;
ge2d_config->dst_para.height = new_vf->height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
ppmgr_vf_put_dec(vf);
vfq_push(&q_free, new_vf);
return;
}
stretchblt_noalpha(context, 0, 0, vf->width,
(pic_struct) ?
(vf->height / 2) :
vf->height, 0, 0, dst_w,
dst_h);
backup_content_w = dst_w;
backup_content_h = dst_h;
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
/* printk("--ppmgr: backup data size: content:%d*%d\n",
* backup_content_w,backup_content_h);
*/
}
#endif
/* data operating. */
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(new_vf->canvas0Addr & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
if (deinterlace) {
switch (deinterlace) {
case 1:
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS, &cs0);
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 1, &cs1);
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 2, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
ge2d_config->src_para.canvas_index =
(PPMGR_DEINTERLACE_BUF_CANVAS)
| ((PPMGR_DEINTERLACE_BUF_CANVAS + 1) << 8)
| ((PPMGR_DEINTERLACE_BUF_CANVAS + 2) << 16);
ge2d_config->src_para.format = GE2D_FORMAT_M24_YUV420;
break;
case 2:
canvas_read(PPMGR_DEINTERLACE_BUF_NV21_CANVAS, &cs0);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_para.canvas_index =
PPMGR_DEINTERLACE_BUF_NV21_CANVAS;
ge2d_config->src_para.format = GE2D_FORMAT_M24_YUV444;
break;
default:
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS, &cs0);
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 1, &cs1);
canvas_read(PPMGR_DEINTERLACE_BUF_CANVAS + 2, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
ge2d_config->src_para.canvas_index =
(PPMGR_DEINTERLACE_BUF_CANVAS)
| ((PPMGR_DEINTERLACE_BUF_CANVAS + 1) << 8)
| ((PPMGR_DEINTERLACE_BUF_CANVAS + 2) << 16);
ge2d_config->src_para.format = GE2D_FORMAT_M24_YUV420;
break;
}
} else {
canvas2cs(vf, 0, &cs0, &cs1, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
ge2d_config->src_para.canvas_index = (vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr;
ge2d_config->src_para.format = get_input_format(vf);
}
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height =
(pic_struct) ? (vf->height / 2) : vf->height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = new_vf->canvas0Addr;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
/*ge2d_config->dst_para.mem_type = CANVAS_OSD0;*/
/*ge2d_config->dst_para.format = GE2D_FORMAT_M24_YUV420;*/
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
if (cur_angle == 1) {
ge2d_config->dst_xy_swap = 1;
ge2d_config->dst_para.x_rev = 1;
} else if (cur_angle == 2) {
ge2d_config->dst_para.x_rev = 1;
ge2d_config->dst_para.y_rev = 1;
} else if (cur_angle == 3) {
ge2d_config->dst_xy_swap = 1;
ge2d_config->dst_para.y_rev = 1;
}
if (ppmgr_device.mirror_flag != 0) {
if (ppmgr_device.mirror_flag == 1) {
if (cur_angle == 2 || cur_angle == 3)
ge2d_config->dst_para.y_rev = 0;
else
ge2d_config->dst_para.y_rev = 1;
} else if (ppmgr_device.mirror_flag == 2) {
if (cur_angle == 1 || cur_angle == 2)
ge2d_config->dst_para.x_rev = 0;
else
ge2d_config->dst_para.x_rev = 1;
}
}
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
if (ppmgr_device.receiver == 0) {
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.width = new_vf->width;
ge2d_config->dst_para.height = new_vf->height;
} else {
ge2d_config->dst_para.format = ppmgr_device.receiver_format;
ge2d_config->dst_para.width = ppmgr_device.canvas_width;
ge2d_config->dst_para.height = ppmgr_device.canvas_height;
new_vf->width = ppmgr_device.canvas_width;
new_vf->height = ppmgr_device.canvas_height;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
}
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
vfq_push(&q_free, new_vf);
return;
}
pp_vf->angle = cur_angle;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (mode) {
int sx, sy, sw, sh, dx, dy, dw, dh;
unsigned int ratio_x = (vf->width << 8) / rect_w;
unsigned int ratio_y = (vf->height << 8) / rect_h;
if (rect_x < 0) {
sx = ((0 - rect_x) * ratio_x) >> 8;
sx = sx & (0xfffffffe);
dx = 0;
} else {
sx = 0;
dx = rect_x;
}
if ((rect_x + rect_w) > new_vf->width) {
sw = ((rect_x + rect_w - new_vf->width)) * ratio_x >> 8;
sw = vf->width - sx - sw;
sw = sw & (0xfffffffe);
if (rect_x < 0)
dw = new_vf->width;
else
dw = new_vf->width - dx;
} else {
sw = vf->width - sx;
sw = sw & (0xfffffffe);
if (rect_x < 0)
dw = rect_w + rect_x;
else
dw = rect_w;
}
if (rect_y < 0) {
sy = ((0 - rect_y) * ratio_y) >> 8;
sy = sy & (0xfffffffe);
dy = 0;
} else {
sy = 0;
dy = rect_y;
}
if ((rect_y + rect_h) > new_vf->height) {
sh = ((rect_y + rect_h - new_vf->height))
* ratio_y >> 8;
sh = vf->height - sy - sh;
sh = sh & (0xfffffffe);
if (rect_y < 0)
dh = new_vf->height;
else
dh = new_vf->height - dy;
} else {
sh = vf->height - sy;
sh = sh & (0xfffffffe);
if (rect_y < 0)
dh = rect_h + rect_y;
else
dh = rect_h;
}
stretchblt_noalpha(context, sx,
(pic_struct) ? (sy / 2) : sy, sw,
(pic_struct) ? (sh / 2) : sh, dx, dy, dw, dh);
} else {
if (ppmgr_device.receiver == 0)
stretchblt_noalpha(context, 0, 0, vf->width,
(pic_struct) ?
(vf->height / 2) :
vf->height, 0, 0,
new_vf->width, new_vf->height);
else
display_mode_adjust(context, vf, pic_struct);
}
#else
stretchblt_noalpha(context, 0, 0,
vf->width,
(pic_struct)?(vf->height/2):vf->height,
0, 0, new_vf->width, new_vf->height);
#endif
ppmgr_vf_put_dec(vf);
vfq_push(&q_ready, new_vf);
#ifdef DDD
PPMGRVPP_WARN("rotate avail=%d, free=%d\n",
vfq_level(&q_ready), vfq_level(&q_free));
#endif
}
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
static void process_vf_change(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct vframe_s temp_vf;
struct ppframe_s *pp_vf = to_ppframe(vf);
struct canvas_s cs0, cs1, cs2, cd;
int pic_struct = 0, interlace_mode;
unsigned int temp_angle = 0;
unsigned int cur_angle = 0;
int ret = 0;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
if (platform_type == PLATFORM_TV)
ret = ppmgr_buffer_init(1);
else
ret = ppmgr_buffer_init(0);
#else
ret = ppmgr_buffer_init(0);
#endif
if (ret < 0)
return;
temp_vf.duration = vf->duration;
temp_vf.duration_pulldown = vf->duration_pulldown;
temp_vf.pts = vf->pts;
temp_vf.pts_us64 = vf->pts_us64;
temp_vf.flag = vf->flag;
temp_vf.type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE
| VIDTYPE_VIU_FIELD;
temp_vf.canvas0Addr = temp_vf.canvas1Addr = ass_index;
cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4;
temp_angle =
(cur_angle >= pp_vf->angle) ?
(cur_angle - pp_vf->angle) :
(cur_angle + 4 - pp_vf->angle);
pp_vf->angle = cur_angle;
vf_rotate_adjust(vf, &temp_vf, temp_angle);
interlace_mode = vf->type & VIDTYPE_TYPEMASK;
if (vf->type & VIDTYPE_VIU_422)
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
vf->height >>= 1;
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
vf->height >>= 1;
else
pic_struct = (GE2D_FORMAT_S16_YUV422T & (3 << 3));
else if (vf->type & VIDTYPE_VIU_NV21) {
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
pic_struct = (GE2D_FORMAT_M24_NV21T & (3 << 3));
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
pic_struct = (GE2D_FORMAT_M24_NV21B & (3 << 3));
} else {
if (interlace_mode == VIDTYPE_INTERLACE_TOP)
pic_struct = (GE2D_FORMAT_M24_YUV420T & (3 << 3));
else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
pic_struct = (GE2D_FORMAT_M24_YUV420B & (3 << 3));
}
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
/* data operating. */
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
if (pp_vf->dec_frame) {
canvas2cs(vf, 0, &cs0, &cs1, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
ge2d_config->src_planes[0].w = cs0.width;
ge2d_config->src_planes[0].h = cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
if (vf->type & VIDTYPE_VIU_NV21)
ge2d_config->src_para.format =
GE2D_FORMAT_M24_NV21 | pic_struct;
else
ge2d_config->src_para.format =
GE2D_FORMAT_M24_YUV420 | pic_struct;
} else {
canvas2cs_index(vf, 0, 0, &cd);
ge2d_config->src_planes[0].addr = cd.addr;
ge2d_config->src_planes[0].w = cd.width;
ge2d_config->src_planes[0].h = cd.height;
ge2d_config->src_para.format =
GE2D_FORMAT_S24_YUV444 | pic_struct;
}
canvas_read(temp_vf.canvas0Addr & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = (vf->canvas0Addr == -1) ?
ALLOC_CANVAS0 : vf->canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = vf->width;
ge2d_config->src_para.height =
(pic_struct) ? (vf->height / 2) : vf->height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = temp_vf.canvas0Addr;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = temp_vf.width;
ge2d_config->dst_para.height = temp_vf.height;
ge2d_config->mem_sec = vf->mem_sec;
if (temp_angle == 1) {
ge2d_config->dst_xy_swap = 1;
ge2d_config->dst_para.x_rev = 1;
} else if (temp_angle == 2) {
ge2d_config->dst_para.x_rev = 1;
ge2d_config->dst_para.y_rev = 1;
} else if (temp_angle == 3) {
ge2d_config->dst_xy_swap = 1;
ge2d_config->dst_para.y_rev = 1;
}
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
/*vfq_push(&q_free, new_vf);*/
return;
}
stretchblt_noalpha(context, 0, 0, vf->width,
(pic_struct) ? (vf->height / 2) : vf->height,
0, 0, temp_vf.width,
temp_vf.height);
vf->type = VIDTYPE_VIU_444
| VIDTYPE_VIU_SINGLE_PLANE
| VIDTYPE_VIU_FIELD;
vf->canvas0Addr = vf->canvas1Addr = index2canvas(pp_vf->index);
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
/* data operating. */
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(temp_vf.canvas0Addr & 0xff, &cd);
ge2d_config->src_planes[0].addr = cd.addr;
ge2d_config->src_planes[0].w = cd.width;
ge2d_config->src_planes[0].h = cd.height;
ge2d_config->src_para.format = GE2D_FORMAT_S24_YUV444;
canvas_read(vf->canvas0Addr & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = temp_vf.canvas0Addr;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = temp_vf.width;
ge2d_config->src_para.height = temp_vf.height;
vf->width = temp_vf.width;
vf->height = temp_vf.height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = vf->canvas0Addr;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
/*vfq_push(&q_free, new_vf);*/
return;
}
stretchblt_noalpha(context, 0, 0, temp_vf.width, temp_vf.height, 0, 0,
vf->width, vf->height);
/*vf->duration = 0 ;*/
if (pp_vf->dec_frame) {
ppmgr_vf_put_dec(pp_vf->dec_frame);
pp_vf->dec_frame = 0;
}
vf->ratio_control = 0;
}
static int process_vf_adjust(struct vframe_s *vf,
struct ge2d_context_s *context,
struct config_para_ex_s *ge2d_config)
{
struct canvas_s cs, cd;
int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0;
u32 ratio = 100;
int sx, sy, sw, sh, dx, dy, dw, dh;
unsigned int ratio_x;
unsigned int ratio_y;
int ret = 0;
int i;
struct ppframe_s *pp_vf = to_ppframe(vf);
u32 mode = amvideo_get_scaler_para(&rect_x, &rect_y, &rect_w, &rect_h,
&ratio);
unsigned int cur_angle = pp_vf->angle;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
if (platform_type == PLATFORM_TV)
ret = ppmgr_buffer_init(1);
else
ret = ppmgr_buffer_init(0);
#else
ret = ppmgr_buffer_init(0);
#endif
if (ret < 0)
return -1;
rect_w = max(rect_w, 64);
rect_h = max(rect_h, 64);
if (ppmgr_device.receiver != 0)
mode = 0;
if (!mode) {
/*printk("--ppmgr adjust: scaler mode is disabled.\n");*/
return -1;
}
if ((rect_x == scaler_x) && (rect_w == scaler_w) && (rect_y == scaler_y)
&& (rect_h == scaler_h)) {
/*printk("--ppmgr adjust: same pos. need not adjust.\n");*/
return -1;
}
if ((!rect_w) || (!rect_h)) {
/*printk("--ppmgr adjust: scale out of range 1.\n");*/
return -1;
}
if (((rect_x + rect_w) < 0) || (rect_x >= (int)ppmgr_device.disp_width)
|| ((rect_y + rect_h) < 0)
|| (rect_y >= (int)ppmgr_device.disp_height)) {
/*printk("--ppmgr adjust: scale out of range 2.\n");*/
return -1;
}
if ((!backup_content_w) || (!backup_content_h)) {
/*printk("--ppmgr adjust: scale out of range 3.\n");*/
return -1;
}
scale_clear_count = VF_POOL_SIZE;
for (i = 0; i < VF_POOL_SIZE; i++) {
buf_status[i].index = ppmgr_canvas_tab[i];
buf_status[i].dirty = 1;
}
scaler_x = rect_x;
scaler_y = rect_y;
scaler_w = rect_w;
scaler_h = rect_h;
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(ass_index & 0xff, &cd);
ge2d_config->src_planes[0].addr = cd.addr;
ge2d_config->src_planes[0].w = cd.width;
ge2d_config->src_planes[0].h = cd.height;
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = ass_index;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = ppmgr_device.disp_width;
ge2d_config->src_para.height = ppmgr_device.disp_height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = ass_index;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = ppmgr_device.disp_width;
ge2d_config->dst_para.height = ppmgr_device.disp_height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -2;
}
fillrect(context, 0, 0,
ppmgr_device.disp_width,
ppmgr_device.disp_height,
0x008080ff);
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(backup_index & 0xff, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
canvas_read(ass_index & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = backup_index;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = ppmgr_device.disp_width;
ge2d_config->src_para.height = ppmgr_device.disp_height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = ass_index;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = ppmgr_device.disp_width;
ge2d_config->dst_para.height = ppmgr_device.disp_height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -2;
}
ratio_x = (backup_content_w << 8) / rect_w;
ratio_y = (backup_content_h << 8) / rect_h;
if (rect_x < 0) {
sx = ((0 - rect_x) * ratio_x) >> 8;
sx = sx & (0xfffffffe);
dx = 0;
} else {
sx = 0;
dx = rect_x;
}
if ((rect_x + rect_w) > vf->width) {
sw = ((rect_x + rect_w - vf->width)) * ratio_x >> 8;
sw = backup_content_w - sx - sw;
sw = sw & (0xfffffffe);
if (rect_x < 0)
dw = vf->width;
else
dw = vf->width - dx;
} else {
sw = backup_content_w - sx;
sw = sw & (0xfffffffe);
if (rect_x < 0)
dw = rect_w + rect_x;
else
dw = rect_w;
}
if (cur_angle > 0) { /* for hdmi mode player*/
sx = 0;
dx = rect_x;
sw = backup_content_w;
dw = rect_w;
}
if (rect_y < 0) {
sy = ((0 - rect_y) * ratio_y) >> 8;
sy = sy & (0xfffffffe);
dy = 0;
} else {
sy = 0;
dy = rect_y;
}
if ((rect_y + rect_h) > vf->height) {
sh = ((rect_y + rect_h - vf->height)) * ratio_y >> 8;
sh = backup_content_h - sy - sh;
sh = sh & (0xfffffffe);
if (rect_y < 0)
dh = vf->height;
else
dh = vf->height - dy;
} else {
sh = backup_content_h - sy;
sh = sh & (0xfffffffe);
if (rect_y < 0)
dh = rect_h + rect_y;
else
dh = rect_h;
}
if (cur_angle > 0) { /* for hdmi mode player*/
sy = 0;
dy = rect_y;
sh = backup_content_h;
dh = rect_h;
}
/* printk("--ppmgr adjust: src x:%d, y:%d, w:%d, h:%d. dst x:%d, y:%d,
* w:%d, h:%d.\n", sx, sy, sw, sh,dx,dy,dw,dh);
*/
stretchblt_noalpha(context, sx, sy, sw, sh, dx, dy, dw, dh);
memset(ge2d_config, 0, sizeof(struct config_para_ex_s));
/* data operating. */
ge2d_config->alu_const_color = 0;/*0x000000ff;*/
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;/*0xff;*/
ge2d_config->dst_xy_swap = 0;
canvas_read(ass_index & 0xff, &cs);
ge2d_config->src_planes[0].addr = cs.addr;
ge2d_config->src_planes[0].w = cs.width;
ge2d_config->src_planes[0].h = cs.height;
canvas_read(vf->canvas0Addr & 0xff, &cd);
ge2d_config->dst_planes[0].addr = cd.addr;
ge2d_config->dst_planes[0].w = cd.width;
ge2d_config->dst_planes[0].h = cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
ge2d_config->src_para.canvas_index = ass_index;
ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->src_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->src_para.fill_color_en = 0;
ge2d_config->src_para.fill_mode = 0;
ge2d_config->src_para.x_rev = 0;
ge2d_config->src_para.y_rev = 0;
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
ge2d_config->src_para.width = ppmgr_device.disp_width;
ge2d_config->src_para.height = ppmgr_device.disp_height;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = vf->canvas0Addr;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format = GE2D_FORMAT_S24_YUV444;
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
ge2d_config->dst_xy_swap = 0;
ge2d_config->dst_para.color = 0;
ge2d_config->dst_para.top = 0;
ge2d_config->dst_para.left = 0;
ge2d_config->dst_para.width = vf->width;
ge2d_config->dst_para.height = vf->height;
ge2d_config->mem_sec = vf->mem_sec;
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
PPMGRVPP_ERR("++ge2d configing error.\n");
return -2;
}
stretchblt_noalpha(context, 0, 0, ppmgr_device.disp_width,
ppmgr_device.disp_height, 0, 0, vf->width, vf->height);
return 0;
}
#endif
/* #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS */
/* extern int is_mid_local_source(struct vframe_s *vf); */
/* extern int is_mid_mvc_need_process(struct vframe_s *vf); */
/* extern int get_mid_process_type(struct vframe_s *vf); */
/* extern void ppmgr_vf_3d( */
/* struct vframe_s *vf, */
/* struct ge2d_context_s *context, */
/* struct config_para_ex_s *ge2d_config); */
/* */
/* extern int Init3DBuff(int canvas_id); */
/* extern void Reset3Dclear(void); */
/* extern void ppmgr_vf_3d_tv( */
/* struct vframe_s *vf, */
/* struct ge2d_context_s *context, */
/* struct config_para_ex_s *ge2d_config); */
/* */
/* extern int get_tv_process_type(struct vframe_s *vf); */
/* #endif */
static struct task_struct *task;
/* extern struct vframe_s *get_cur_dispbuf(void); */
/* extern enum platform_type_t get_platform_type(void); */
static int ppmgr_task(void *data)
{
struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
int i;
struct vframe_s *vf_local = NULL;
struct ppframe_s *pp_local = NULL;
struct ge2d_context_s *context = create_ge2d_work_queue();
struct config_para_ex_s ge2d_config;
#ifdef PPMGR_TB_DETECT
bool first_frame = true;
int first_frame_type = 0;
unsigned int skip_picture = 0;
u8 cur_invert = 0;
u8 last_type = 0;
u32 last_width = 0;
u32 last_height = 0;
u8 reset_tb = 0;
u32 init_mute = 0;
#endif
memset(&ge2d_config, 0, sizeof(struct config_para_ex_s));
sched_setscheduler(current, SCHED_FIFO, &param);
allow_signal(SIGTERM);
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
Reset3Dclear();
#endif
while (down_interruptible(&thread_sem) == 0) {
struct vframe_s *vf = NULL;
if (kthread_should_stop() || ppmgr_quit_flag)
break;
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
if (get_scaler_pos_reset()) {
set_scaler_pos_reset(false);
scaler_w = 0;
scaler_h = 0;
scaler_x = 0;
scaler_y = 0;
}
if (scaler_pos_changed) {
scaler_pos_changed = 0;
vf = get_cur_dispbuf();
if (!is_valid_ppframe(to_ppframe(vf)))
continue;
if (vf && (vf->type & VIDTYPE_COMPRESS))
continue;
if (vf) {
if (process_vf_adjust(vf,
context,
&ge2d_config) >= 0)
EnableVideoLayer();
}
vf = vfq_peek(&q_ready);
while (vf) {
vf = vfq_pop(&q_ready);
ppmgr_vf_put(vf, NULL);
vf = vfq_peek(&q_ready);
}
up(&thread_sem);
continue;
}
if (still_picture_notify) {
still_picture_notify = 0;
/* DisableVideoLayer(); */
vf = get_cur_dispbuf();
if (!is_valid_ppframe(to_ppframe(vf)))
continue;
if (vf->type & VIDTYPE_COMPRESS)
continue;
process_vf_change(vf, context, &ge2d_config);
vf_notify_receiver(
PROVIDER_NAME,
VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED,
NULL);
vfq_lookup_start(&q_ready);
vf = vfq_peek(&q_ready);
while (vf) {
vf = vfq_pop(&q_ready);
process_vf_change(vf, context, &ge2d_config);
vf = vfq_peek(&q_ready);
}
vfq_lookup_end(&q_ready);
/* EnableVideoLayer(); */
up(&thread_sem);
continue;
}
#endif
/* process when we have both input and output space */
while (ppmgr_vf_peek_dec()
&& (!vfq_empty(&q_free))
&& (!ppmgr_blocking)) {
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
int process_type = TYPE_NONE;
enum platform_type_t platform_type;
vf = ppmgr_vf_get_dec();
if (!vf)
break;
if (vf && ppmgr_device.started) {
if (!(vf->type
& (VIDTYPE_VIU_422
| VIDTYPE_VIU_444
| VIDTYPE_VIU_NV21))
|| (vf->type & VIDTYPE_INTERLACE)
|| ppmgr_device.disable_prot
|| (vf->type & VIDTYPE_MVC)
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
|| amvideo_get_scaler_mode()
#endif
#ifdef CONFIG_V4L_AMLOGIC_VIDEO
|| ppmgr_device.receiver
#endif
) {
ppmgr_device.use_prot = 0;
set_video_angle(0);
ppmgr_device.videoangle =
(ppmgr_device.angle
+ ppmgr_device.orientation) % 4;
set_property_change(1);
} else {
ppmgr_device.use_prot = 1;
/*ppmgr_device.angle = 0;*/
ppmgr_device.videoangle =
(ppmgr_device.angle
+ ppmgr_device.orientation) % 4;
set_property_change(1);
}
ppmgr_device.started = 0;
}
vf->video_angle =
(ppmgr_device.angle
+ ppmgr_device.orientation
+ vf->orientation)%4;
platform_type = get_platform_type();
if (platform_type == PLATFORM_TV)
process_type = get_tv_process_type(vf);
else
process_type = get_mid_process_type(vf);
if (process_type == TYPE_NONE) {
int ret = 0;
if (platform_type != PLATFORM_TV)
ret = process_vf_deinterlace(vf,
context,
&ge2d_config);
process_vf_rotate(vf,
context,
&ge2d_config,
(ret > 0)?ret:0);
} else {
if (platform_type == PLATFORM_TV)
ppmgr_vf_3d_tv(vf,
context, &ge2d_config);
else
ppmgr_vf_3d(vf, context, &ge2d_config);
}
#else
int ret = 0;
vf = ppmgr_vf_get_dec();
if (!vf)
break;
if (vf && ppmgr_device.started) {
if (!(vf->type
& (VIDTYPE_VIU_422
| VIDTYPE_VIU_444
| VIDTYPE_VIU_NV21))
|| (vf->type & VIDTYPE_INTERLACE)
|| ppmgr_device.disable_prot
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
|| amvideo_get_scaler_mode()
#endif
#ifdef CONFIG_V4L_AMLOGIC_VIDEO
|| ppmgr_device.receiver
#endif
) {
ppmgr_device.use_prot = 0;
set_video_angle(0);
ppmgr_device.videoangle =
(ppmgr_device.angle
+ ppmgr_device.orientation) % 4;
set_property_change(1);
} else {
ppmgr_device.use_prot = 1;
set_video_angle(
ppmgr_device.global_angle);
ppmgr_device.videoangle =
(ppmgr_device.angle
+ ppmgr_device.orientation) % 4;
set_property_change(1);
}
ppmgr_device.started = 0;
}
vf->video_angle = (
ppmgr_device.angle
+ ppmgr_device.orientation
+ vf->orientation) % 4;
#ifdef PPMGR_TB_DETECT
if (vf->source_type !=
VFRAME_SOURCE_TYPE_OTHERS)
goto SKIP_DETECT;
if (first_frame) {
last_type = vf->type & VIDTYPE_TYPEMASK;
last_width = vf->width;
last_height = vf->height;
first_frame_type = last_type;
tb_first_frame_type = last_type;
first_frame = false;
reset_tb = 0;
skip_picture = 0;
cur_invert = 0;
init_mute = tb_init_mute;
atomic_set(&tb_skip_flag, 1);
atomic_set(&tb_reset_flag, 0);
if (ppmgr_device.tb_detect & 0xe)
PPMGRVPP_INFO(
"tb first frame type: %d\n",
last_type);
} else if ((last_type ==
(vf->type & VIDTYPE_TYPEMASK))
&& last_type) {
/* interlace seq changed */
first_frame_type =
vf->type & VIDTYPE_TYPEMASK;
tb_first_frame_type =
first_frame_type;
reset_tb = 1;
/* keep old invert */
if (ppmgr_device.tb_detect & 0xe)
PPMGRVPP_INFO(
"tb interlace seq change, old: %d, new: %d, invert: %d\n",
last_type,
first_frame_type,
cur_invert);
} else if ((last_type == 0) &&
((vf->type & VIDTYPE_TYPEMASK) != 0)) {
/* prog -> interlace changed */
first_frame_type =
vf->type & VIDTYPE_TYPEMASK;
tb_first_frame_type =
first_frame_type;
reset_tb = 1;
if (ppmgr_device.tb_detect & 0xe)
PPMGRVPP_INFO(
"tb prog -> interlace, new type: %d, invert: %d\n",
first_frame_type, cur_invert);
/* not invert */
cur_invert = 0;
} else if (((last_width != vf->width)
|| (last_height != vf->height))
&& ((vf->type & VIDTYPE_TYPEMASK) != 0)) {
/* size changed and next seq is interlace */
first_frame_type =
vf->type & VIDTYPE_TYPEMASK;
tb_first_frame_type =
first_frame_type;
reset_tb = 1;
/* keep old invert */
if (ppmgr_device.tb_detect & 0xe)
PPMGRVPP_INFO(
"tb size change new type: %d, invert: %d\n",
first_frame_type, cur_invert);
} else if ((last_type != 0) &&
((vf->type & VIDTYPE_TYPEMASK) == 0)) {
/* interlace -> prog changed */
if (ppmgr_device.tb_detect & 0xe)
PPMGRVPP_INFO(
"tb interlace -> prog, invert: %d\n",
cur_invert);
/* not invert */
cur_invert = 0;
}
last_type = vf->type & VIDTYPE_TYPEMASK;
last_width = vf->width;
last_height = vf->height;
if (ppmgr_device.tb_detect) {
ret = 0;
if (tb_buffer_status < 0)
goto SKIP_DETECT;
if (tb_buffer_status == 0)
if (tb_buffer_init() <= 0)
goto SKIP_DETECT;
ppmgr_device.tb_detect_buf_len = tb_buffer_len;
vf->type = (vf->type & ~TB_DETECT_MASK);
if (init_mute > 0) {
init_mute--;
atomic_set(&tb_skip_flag, 1);
goto SKIP_DETECT;
}
if (last_type == 0) {/* cur type is prog */
skip_picture++;
cur_invert = 0;
goto SKIP_DETECT;
}
vf->type |=
cur_invert <<
TB_DETECT_MASK_BIT;
if (reset_tb) {
/* wait tb task done */
while ((tb_buff_wptr >= 5)
&& (tb_buff_rptr
<= tb_buff_wptr - 5))
usleep_range(
4000, 5000);
atomic_set(&detect_status,
tb_idle);
tb_buff_wptr = 0;
tb_buff_rptr = 0;
atomic_set(
&tb_detect_flag,
TB_DETECT_NC);
atomic_set(&tb_reset_flag, 1);
atomic_set(&tb_skip_flag, 1);
skip_picture = 0;
reset_tb = 0;
if (ppmgr_device.tb_detect & 0xc)
PPMGRVPP_INFO(
"tb detect reset once\n");
}
if ((atomic_read(&detect_status) == tb_done)
&& (skip_picture >=
ppmgr_device.tb_detect_period)
&& (last_type == first_frame_type)) {
int tbf_flag =
atomic_read(&tb_detect_flag);
u8 old_invert = cur_invert;
atomic_set(&detect_status, tb_idle);
tb_buff_wptr = 0;
tb_buff_rptr = 0;
skip_picture = 0;
if ((tbf_flag == TB_DETECT_TBF)
&& (first_frame_type ==
VIDTYPE_INTERLACE_TOP)) {
/* TBF sams as BFF */
vf->type |=
TB_DETECT_INVERT
<< TB_DETECT_MASK_BIT;
cur_invert = 1;
} else if ((tbf_flag == TB_DETECT_BFF)
&& (first_frame_type ==
VIDTYPE_INTERLACE_TOP)) {
vf->type |=
TB_DETECT_INVERT
<< TB_DETECT_MASK_BIT;
cur_invert = 1;
} else if ((tbf_flag == TB_DETECT_TFF)
&& (first_frame_type ==
VIDTYPE_INTERLACE_BOTTOM)) {
vf->type |=
TB_DETECT_INVERT
<< TB_DETECT_MASK_BIT;
cur_invert = 1;
} else if (tbf_flag != TB_DETECT_NC) {
cur_invert = 0;
}
vf->type = (vf->type & ~TB_DETECT_MASK);
vf->type |=
cur_invert <<
TB_DETECT_MASK_BIT;
if ((old_invert != cur_invert)
&& (ppmgr_device.tb_detect
& 0xe))
PPMGRVPP_INFO(
"tb detect flag: %d->%d, invert: %d->%d\n",
tb_detect_last_flag,
tbf_flag,
old_invert,
cur_invert);
else if ((tb_detect_last_flag
!= tbf_flag)
&& (ppmgr_device.tb_detect
& 0xc))
PPMGRVPP_INFO(
"tb detect flag %d->%d, invert: %d\n",
tb_detect_last_flag,
tbf_flag,
cur_invert);
tb_detect_last_flag = tbf_flag;
atomic_set(&tb_detect_flag,
TB_DETECT_NC);
}
if ((tb_buff_wptr == 0) &&
(last_type != first_frame_type)) {
skip_picture++;
atomic_set(&tb_skip_flag, 1);
if (ppmgr_device.tb_detect & 0xc)
PPMGRVPP_INFO(
"tb detect skip case1\n");
goto SKIP_DETECT;
}
if (tb_buff_wptr < tb_buffer_len) {
ret = process_vf_tb_detect(
vf, context, &ge2d_config);
} else {
if (ppmgr_device.tb_detect & 0xc)
PPMGRVPP_INFO(
"tb detect skip case2\n");
atomic_set(&tb_skip_flag, 1);
skip_picture++;
}
if (ret > 0) {
tb_buff_wptr++;
if ((tb_buff_wptr >= 5) &&
(atomic_read(&detect_status)
== tb_idle))
atomic_set(
&detect_status,
tb_running);
if (tb_buff_wptr >= 5)
up(&tb_sem);
}
} else {
reset_tb = 1;
skip_picture++;
cur_invert = 0;
if (init_mute > 0)
init_mute--;
}
SKIP_DETECT:
if (skip_picture >
ppmgr_device.tb_detect_period)
skip_picture =
ppmgr_device.tb_detect_period;
#endif
ret = process_vf_deinterlace(vf, context, &ge2d_config);
process_vf_rotate(
vf, context,
&ge2d_config,
(ret > 0) ? ret : 0);
#endif
vf_notify_receiver(
PROVIDER_NAME,
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
}
if (ppmgr_blocking) {
#if 0
if (ppmgr_reset_type) {
vf_notify_provider(
PROVIDER_NAME,
VFRAME_EVENT_RECEIVER_RESET,
NULL);
ppmgr_reset_type = 0;
}
#endif
/***recycle buffer to decoder***/
if (0) {/*mark@1120a*/
for (i = 0; i < VF_POOL_SIZE; i++)
ppmgr_vf_video_put(&vfp_pool[i]);
vf_local = vfq_pop(&q_ready);
while (vf_local) {
pp_local = to_ppframe(vf_local);
if (pp_local->dec_frame) {
ppmgr_vf_put_dec(pp_local->dec_frame);
pp_local->dec_frame = NULL;
}
vf_local = vfq_pop(&q_ready);
}
for (i = 0; i < VF_POOL_SIZE; i++) {
if (vfp_pool[i].dec_frame) {
ppmgr_vf_put_dec(vfp_pool[i].dec_frame);
vfp_pool[i].dec_frame = NULL;
}
}
}
/***recycle buffer to decoder***/
vf_local_init();
vf_light_unreg_provider(&ppmgr_vf_prov);
msleep(30);
vf_light_reg_provider(&ppmgr_vf_prov);
ppmgr_blocking = false;
up(&thread_sem);
PPMGRVPP_WARN("ppmgr rebuild from light-unregister\n");
}
#ifdef DDD
PPMGRVPP_WARN("process paused, dec %p, free %d, avail %d\n",
ppmgr_vf_peek_dec(),
vfq_level(&q_free),
vfq_level(&q_ready));
#endif
}
destroy_ge2d_work_queue(context);
while (!kthread_should_stop()) {
/* may not call stop, wait..
* it is killed by SIGTERM,eixt on down_interruptible
* if not call stop,this thread may on do_exit and
* kthread_stop may not work good;
*/
/* msleep(10); */
usleep_range(9000, 10000);
}
return 0;
}
/************************************************
*
* init functions.
*
*************************************************/
static int vout_notify_callback(
struct notifier_block *block, unsigned long cmd,
void *para)
{
if (cmd == VOUT_EVENT_MODE_CHANGE)
ppmgr_device.vinfo = get_current_vinfo();
return 0;
}
static struct notifier_block vout_notifier = {.notifier_call =
vout_notify_callback, };
int ppmgr_register(void)
{
vf_ppmgr_init_provider();
vf_ppmgr_init_receiver();
vf_ppmgr_reg_receiver();
vout_register_client(&vout_notifier);
return 0;
}
int ppmgr_buffer_uninit(void)
{
if (!ppmgr_device.use_reserved &&
ppmgr_device.bmmu_box) {
int i;
for (i = 0; i < VF_POOL_SIZE; i++) {
if (bmmu_info[i].phy_addr) {
decoder_bmmu_box_free_idx(
ppmgr_device.bmmu_box, i);
bmmu_info[i].phy_addr = 0;
}
bmmu_info[i].mem_handle = NULL;
}
decoder_bmmu_box_free(ppmgr_device.bmmu_box);
ppmgr_device.bmmu_box = NULL;
}
ppmgr_buffer_status = 0;
return 0;
}
int ppmgr_buffer_init(int vout_mode)
{
int i;
u32 canvas_width, canvas_height;
u32 decbuf_size;
struct vinfo_s vinfo = {.width = 1280, .height = 720, };
#ifdef INTERLACE_DROP_MODE
mycount = 0;
#endif
switch (ppmgr_buffer_status) {
case 0:/*not config*/
break;
case 1:/*config before , return ok*/
return 0;
case 2:/*config fail, won't retry , return failure*/
return -1;
default:
return -1;
}
if (ppmgr_device.mirror_flag) {
PPMGRVPP_INFO("CMA memory force config fail\n");
ppmgr_buffer_status = 2;
return -1;
}
if (!ppmgr_device.use_reserved &&
!ppmgr_device.bmmu_box) {
int flags = CODEC_MM_FLAGS_CMA_CLEAR |
CODEC_MM_FLAGS_FOR_VDECODER;
PPMGRVPP_INFO("reserved memory config fail,use CMA.\n");
if (codec_mm_video_tvp_enabled()) {
pr_info("ppmgr buffer allocation from TVP.\n");
flags |= CODEC_MM_FLAGS_TVP;
}
ppmgr_device.bmmu_box = decoder_bmmu_box_alloc_box(
"ppmgr",
0,
VF_POOL_SIZE,
4 + PAGE_SHIFT,
flags);
if (!ppmgr_device.bmmu_box) {
ppmgr_buffer_status = 2;
PPMGRVPP_ERR("bmmu box fail\n");
return -1;
}
memset(bmmu_info, 0, sizeof(bmmu_info));
}
ppmgr_buffer_status = 1;
#ifdef CONFIG_V4L_AMLOGIC_VIDEO
if (ppmgr_device.receiver != 0) {
display_mode_change = VF_POOL_SIZE;
canvas_width = ppmgr_device.canvas_width;
canvas_height = ppmgr_device.canvas_height;
if ((ppmgr_device.receiver_format
== (GE2D_FORMAT_M24_NV21|GE2D_LITTLE_ENDIAN)) ||
(ppmgr_device.receiver_format
== (GE2D_FORMAT_M24_NV12|GE2D_LITTLE_ENDIAN))) {
decbuf_size = (canvas_width * canvas_height * 12)>>3;
decbuf_size = PAGE_ALIGN(decbuf_size);
for (i = 0; i < VF_POOL_SIZE; i++) {
canvas_config(PPMGR_CANVAS_INDEX + i,
(ulong)(buf_start + i * decbuf_size),
canvas_width, canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
canvas_config(PPMGR_CANVAS_INDEX
+ VF_POOL_SIZE + i,
(ulong)(buf_start + i * decbuf_size
+ (canvas_width * canvas_height)),
canvas_width, canvas_height/2,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
ppmgr_canvas_tab[i] = (PPMGR_CANVAS_INDEX + i)
| ((PPMGR_CANVAS_INDEX + i + VF_POOL_SIZE)<<8);
}
} else {
int bpp = 4;
if (ppmgr_device.receiver_format
== (GE2D_FORMAT_S32_ABGR|GE2D_LITTLE_ENDIAN))
bpp = 4;
else if (ppmgr_device.receiver_format
== (GE2D_FORMAT_S24_BGR|GE2D_LITTLE_ENDIAN))
bpp = 3;
else if (ppmgr_device.receiver_format
== (GE2D_FORMAT_S16_RGB_565|GE2D_LITTLE_ENDIAN))
bpp = 2;
decbuf_size = canvas_width * canvas_height * bpp;
/*decbuf_size = PAGE_ALIGN(decbuf_size);*/
for (i = 0; i < VF_POOL_SIZE; i++) {
canvas_config(PPMGR_CANVAS_INDEX + i,
(ulong)(buf_start + i * decbuf_size),
canvas_width * bpp, canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_LINEAR);
ppmgr_canvas_tab[i] = PPMGR_CANVAS_INDEX + i;
}
}
} else
#endif
if (vout_mode == 0) {
ppmgr_device.vinfo = get_current_vinfo();
if (ppmgr_device.vinfo == NULL) {
PPMGRVPP_ERR(
"failed to get_currnt_vinfo! Try to MAKE one!");
ppmgr_device.vinfo = &vinfo;
}
if (ppmgr_device.disp_width == 0) {
if (ppmgr_device.vinfo->width <= MAX_WIDTH)
ppmgr_device.disp_width =
ppmgr_device.vinfo->width;
else
ppmgr_device.disp_width = MAX_WIDTH;
}
if (ppmgr_device.disp_height == 0) {
if (ppmgr_device.vinfo->height <= MAX_HEIGHT)
ppmgr_device.disp_height =
ppmgr_device.vinfo->height;
else
ppmgr_device.disp_height = MAX_HEIGHT;
}
if (get_platform_type() == PLATFORM_MID_VERTICAL) {
int DISP_SIZE =
ppmgr_device.disp_width >
ppmgr_device.disp_height ?
ppmgr_device.disp_width :
ppmgr_device.disp_height;
canvas_width = (DISP_SIZE + 0x1f) & ~0x1f;
canvas_height = (DISP_SIZE + 0x1f) & ~0x1f;
} else {
canvas_width =
(ppmgr_device.disp_width + 0x1f) & ~0x1f;
canvas_height =
(ppmgr_device.disp_height + 0x1f) & ~0x1f;
}
decbuf_size = canvas_width * canvas_height * 3;
ppmgr_device.canvas_width = canvas_width;
ppmgr_device.canvas_height = canvas_height;
for (i = 0; i < VF_POOL_SIZE; i++) {
if (decoder_bmmu_box_alloc_buf_phy(
ppmgr_device.bmmu_box,
i, decbuf_size, "ppmgr",
&bmmu_info[i].phy_addr) < 0) {
PPMGRVPP_ERR("bmmu alloc fail idx:%d\n", i);
goto _error;
}
bmmu_info[i].mem_handle =
decoder_bmmu_box_get_mem_handle(
ppmgr_device.bmmu_box, i);
pr_debug("%s phy: %lu handle:%p\n", __func__,
bmmu_info[i].phy_addr,
bmmu_info[i].mem_handle);
canvas_config(PPMGR_CANVAS_INDEX + i,
(ulong)(bmmu_info[i].phy_addr),
canvas_width * 3,
canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
}
} else {
#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
canvas_width = 1920;
canvas_height = 1088;
decbuf_size = 0x600000;
if (decbuf_size * VF_POOL_SIZE > buf_size) {
PPMGRVPP_ERR(
"size of ppmgr memory resource too small.\n");
return -1;
}
for (i = 0; i < VF_POOL_SIZE; i++) {
canvas_config(PPMGR_CANVAS_INDEX + i/**3*/+ 0,
(ulong)(buf_start + i * decbuf_size),
canvas_width * 3,
canvas_height,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
canvas_config(PPMGR_DOUBLE_CANVAS_INDEX + i,
(ulong)(buf_start +
(2 * i) * decbuf_size / 2),
canvas_width * 3, canvas_height / 2,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
canvas_config(PPMGR_DOUBLE_CANVAS_INDEX + 4 + i,
(ulong)(buf_start +
(2 * i + 1) *
decbuf_size / 2),
canvas_width * 3, canvas_height / 2,
CANVAS_ADDR_NOWRAP,
CANVAS_BLKMODE_32X32);
}
#endif
}
ppmgr_blocking = false;
ppmgr_inited = true;
ppmgr_reset_type = 0;
set_buff_change(0);
//sema_init(&thread_sem, 1);
return 0;
_error:
ppmgr_buffer_uninit();
return -1;
}
int start_ppmgr_task(void)
{
enum platform_type_t platform_type;
platform_type = get_platform_type();
/* if (get_cpu_type()>= MESON_CPU_TYPE_MESON6)*/
/* switch_mod_gate_by_name("ge2d", 1);*/
/*#endif*/
#ifdef PPMGR_TB_DETECT
start_tb_task();
#endif
if (!task) {
vf_local_init();
ppmgr_blocking = false;
ppmgr_inited = true;
ppmgr_reset_type = 0;
set_buff_change(0);
ppmgr_buffer_status = 0;
ppmgr_quit_flag = false;
task = kthread_run(ppmgr_task, 0, "ppmgr");
if (IS_ERR(task)) {
int ret = PTR_ERR(task);
pr_err("%s: Failed to start ppmgr task (%d)\n",
__func__, ret);
task = NULL;
return -1;
}
}
task_running = 1;
return 0;
}
void stop_ppmgr_task(void)
{
#ifdef PPMGR_TB_DETECT
stop_tb_task();
#endif
if (task) {
/* send_sig(SIGTERM, task, 1); */
ppmgr_quit_flag = true;
up(&thread_sem);
kthread_stop(task);
ppmgr_quit_flag = false;
task = NULL;
}
task_running = 0;
vf_local_init();
/*#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6*/
/* switch_mod_gate_by_name("ge2d", 0);*/
/*#endif*/
}
#ifdef PPMGR_TB_DETECT
static int tb_buffer_init(void)
{
int i;
//int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR;
int flags = 0;
if (tb_buffer_status)
return tb_buffer_status;
if (tb_src_canvas == 0) {
if (canvas_pool_alloc_canvas_table(
"tb_detect_src",
&tb_src_canvas, 1,
CANVAS_MAP_TYPE_YUV)) {
pr_err(
"%s alloc tb src canvas error.\n",
__func__);
return -1;
}
pr_info("alloc tb src canvas 0x%x.\n",
tb_src_canvas);
}
if (tb_canvas < 0)
tb_canvas =
canvas_pool_map_alloc_canvas("tb_detect_dst");
if (tb_canvas < 0)
return -1;
if (tb_buffer_start == 0) {
if (!ppmgr_device.tb_detect_buf_len)
ppmgr_device.tb_detect_buf_len = 8;
tb_buffer_len = ppmgr_device.tb_detect_buf_len;
tb_buffer_size = TB_DETECT_H * TB_DETECT_W
* tb_buffer_len;
tb_buffer_size = PAGE_ALIGN(tb_buffer_size);
tb_buffer_start = codec_mm_alloc_for_dma(
"tb_detect",
tb_buffer_size/PAGE_SIZE, 0, flags);
PPMGRVPP_INFO("tb cma memory %x, size %x, item %d\n",
(unsigned int)tb_buffer_start,
(unsigned int)tb_buffer_size,
tb_buffer_len);
if (tb_buffer_start == 0) {
PPMGRVPP_ERR("tb cma memory config fail\n");
tb_buffer_status = -1;
return -1;
}
for (i = 0; i < tb_buffer_len; i++) {
detect_buf[i].paddr = tb_buffer_start +
TB_DETECT_H * TB_DETECT_W * i;
detect_buf[i].vaddr =
(ulong)codec_mm_vmap(detect_buf[i].paddr,
TB_DETECT_H * TB_DETECT_W);
if (ppmgr_device.tb_detect & 0xc) {
PPMGRVPP_INFO(
"detect buff(%d) paddr: %lx, vaddr: %lx\n",
i,
detect_buf[i].paddr,
detect_buf[i].vaddr);
}
}
}
tb_buffer_status = 1;
return 1;
}
static int tb_buffer_uninit(void)
{
int i;
if (tb_src_canvas) {
if (tb_src_canvas & 0xff)
canvas_pool_map_free_canvas(
tb_src_canvas & 0xff);
if ((tb_src_canvas >> 8) & 0xff)
canvas_pool_map_free_canvas(
(tb_src_canvas >> 8) & 0xff);
if ((tb_src_canvas >> 16) & 0xff)
canvas_pool_map_free_canvas(
(tb_src_canvas >> 16) & 0xff);
}
tb_src_canvas = 0;
if (tb_canvas >= 0)
canvas_pool_map_free_canvas(tb_canvas);
tb_canvas = -1;
if (tb_buffer_start) {
PPMGRVPP_INFO("tb cma free addr is %x, size is %x\n",
(unsigned int)tb_buffer_start,
(unsigned int)tb_buffer_size);
for (i = 0; i < tb_buffer_len; i++) {
if (detect_buf[i].vaddr) {
codec_mm_unmap_phyaddr(
(u8 *)detect_buf[i].vaddr);
detect_buf[i].vaddr = 0;
}
}
codec_mm_free_for_dma(
"tb_detect",
tb_buffer_start);
tb_buffer_start = 0;
tb_buffer_size = 0;
}
tb_buffer_status = 0;
return 0;
}
static void tb_detect_init(void)
{
int val = 0;
sema_init(&tb_sem, val);
memset(detect_buf, 0, sizeof(detect_buf));
atomic_set(&detect_status, tb_idle);
atomic_set(&tb_detect_flag, TB_DETECT_NC);
atomic_set(&tb_reset_flag, 0);
atomic_set(&tb_skip_flag, 0);
tb_detect_last_flag = TB_DETECT_NC;
tb_buff_wptr = 0;
tb_buff_rptr = 0;
tb_buffer_status = 0;
tb_buffer_start = 0;
tb_buffer_size = 0;
tb_first_frame_type = 0;
tb_quit_flag = false;
tb_init_mute =
ppmgr_device.tb_detect_init_mute;
}
static int tb_task(void *data)
{
int tbff_flag;
struct tbff_stats pReg;
ulong y5fld[5];
int is_top;
int inited = 0;
static const char * const detect_type[] = {"NC", "TFF", "BFF", "TBF"};
struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
sched_setscheduler(current, SCHED_FIFO, &param);
if (gfunc)
gfunc->stats_init((&pReg), TB_DETECT_H, TB_DETECT_W);
allow_signal(SIGTERM);
while (down_interruptible(&tb_sem) == 0) {
if (kthread_should_stop() || tb_quit_flag)
break;
if (tb_buff_rptr == 0) {
if (atomic_read(&tb_reset_flag) != 0)
inited = 0;
atomic_set(&tb_reset_flag, 0);
if (gfunc)
gfunc->fwalg_init(inited);
}
inited = 1;
is_top = (tb_buff_rptr & 1) ? 0 : 1;
/* new -> old */
y5fld[0] = detect_buf[tb_buff_rptr + 4].vaddr;
y5fld[1] = detect_buf[tb_buff_rptr + 3].vaddr;
y5fld[2] = detect_buf[tb_buff_rptr + 2].vaddr;
y5fld[3] = detect_buf[tb_buff_rptr + 1].vaddr;
y5fld[4] = detect_buf[tb_buff_rptr].vaddr;
if (gfunc)
gfunc->stats_get(y5fld, &pReg);
is_top = is_top ^ 1;
tbff_flag = -1;
if (gfunc)
tbff_flag = gfunc->fwalg_get(
&pReg, is_top,
(tb_first_frame_type == 3) ? 0 : 1,
tb_buff_rptr,
atomic_read(&tb_skip_flag),
(ppmgr_device.tb_detect & 0x8) ? 1 : 0);
if (tb_buff_rptr == 0)
atomic_set(&tb_skip_flag, 0);
if ((tbff_flag < -1) || (tbff_flag > 2)) {
PPMGRVPP_ERR(
"get tb detect flag error: %d\n",
tbff_flag);
}
if ((tbff_flag == -1) && (gfunc))
tbff_flag =
gfunc->majority_get();
if (tbff_flag == -1)
tbff_flag =
TB_DETECT_NC;
else if (tbff_flag == 0)
tbff_flag =
TB_DETECT_TFF;
else if (tbff_flag == 1)
tbff_flag =
TB_DETECT_BFF;
else if (tbff_flag == 2)
tbff_flag =
TB_DETECT_TBF;
else
tbff_flag =
TB_DETECT_NC;
tb_buff_rptr++;
if ((tb_buff_rptr > tb_buffer_len - 5)
&& (atomic_read(&detect_status) == tb_running)) {
atomic_set(
&tb_detect_flag,
tbff_flag);
if (ppmgr_device.tb_detect & 0xc)
PPMGRVPP_INFO("get tb detect final flag: %s\n",
detect_type[tbff_flag]);
atomic_set(&detect_status, tb_done);
}
}
while (!kthread_should_stop())
usleep_range(9000, 10000);
tb_buffer_uninit();
return 0;
}
int start_tb_task(void)
{
if (!tb_detect_task) {
tb_detect_init();
tb_detect_task = kthread_run(tb_task, 0, "tb_detect");
}
tb_task_running = 1;
return 0;
}
void stop_tb_task(void)
{
int val = 0;
if (tb_detect_task) {
tb_quit_flag = true;
up(&tb_sem);
/* send_sig(SIGTERM, tb_detect_task, 1); */
kthread_stop(tb_detect_task);
tb_quit_flag = false;
sema_init(&tb_sem, val);
tb_detect_task = NULL;
}
tb_task_running = 0;
}
#endif
void get_tb_detect_status(void)
{
#ifdef PPMGR_TB_DETECT
static const char * const tb_type[] = {"Prog", "Top", "N/C", "Bottom"};
static const char * const detect_type[] = {"NC", "TFF", "BFF", "TBF"};
static const char * const status_str[] = {"Idle", "Run", "Done", "N/C"};
u32 status = atomic_read(&detect_status);
u32 flag = atomic_read(&tb_detect_flag);
u32 reset_flag = atomic_read(&tb_reset_flag);
PPMGRVPP_INFO(
"T/B detect buffer addr: 0x%x, size: 0x%x\n",
(unsigned int)tb_buffer_start,
(unsigned int)tb_buffer_size);
PPMGRVPP_INFO(
"T/B detect canvas: %x, len: %d, buff status: %d\n",
(unsigned int)tb_canvas,
tb_buffer_len,
(unsigned int)tb_buffer_status);
PPMGRVPP_INFO(
"T/B detect buffer wptr: %d, rptr: %d, reset: %d\n",
tb_buff_wptr,
tb_buff_rptr,
reset_flag);
PPMGRVPP_INFO(
"T/B detect first frame type: %s, period: %d\n",
tb_type[tb_first_frame_type],
ppmgr_device.tb_detect_period);
PPMGRVPP_INFO(
"T/B detect status: %s, cur flag: %s, last flag: %s\n",
status_str[status],
detect_type[flag],
detect_type[tb_detect_last_flag]);
PPMGRVPP_INFO(
"T/B detect init mute is %d\n",
tb_init_mute);
PPMGRVPP_INFO(
"T/B detect tb_detect_task: %p, running: %d\n",
tb_detect_task,
tb_task_running);
PPMGRVPP_INFO(
"current T/B detect mode is %d\n",
ppmgr_device.tb_detect);
#endif
}
int RegisterTB_Function(struct TB_DetectFuncPtr *func, const char *ver)
{
int ret = -1;
#ifdef PPMGR_TB_DETECT
mutex_lock(&tb_mutex);
PPMGRVPP_INFO(
"RegisterTB_Function: gfunc %p, func: %p, ver:%s\n",
gfunc, func, ver);
if (!gfunc && func) {
gfunc = func;
ret = 0;
}
mutex_unlock(&tb_mutex);
#endif
return ret;
}
EXPORT_SYMBOL(RegisterTB_Function);
int UnRegisterTB_Function(struct TB_DetectFuncPtr *func)
{
int ret = -1;
#ifdef PPMGR_TB_DETECT
mutex_lock(&tb_mutex);
PPMGRVPP_INFO(
"UnRegisterTB_Function: gfunc %p, func: %p\n",
gfunc, func);
if (func && func == gfunc) {
gfunc = NULL;
ret = 0;
}
mutex_unlock(&tb_mutex);
#endif
return ret;
}
EXPORT_SYMBOL(UnRegisterTB_Function);