| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * 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>*/ |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRAME_SYNC |
| #include <linux/amlogic/media/frame_sync/timestamp.h> |
| #include <linux/amlogic/media/frame_sync/ptsserv.h> |
| #endif |
| #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> |
| /* media module used media/registers/cpu_version.h since kernel 5.4 */ |
| #include <linux/amlogic/media/registers/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"*/ |
| #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO |
| #include <linux/amlogic/media/video_sink/video.h> |
| #endif |
| /*#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 "../../common/vfm/vfm.h" |
| #include "ppmgr_vpp.h" |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| #include <linux/amlogic/media/codec_mm/codec_mm.h> |
| #endif |
| #include <linux/dma-mapping.h> |
| #include <linux/dma-contiguous.h> |
| #include <linux/amlogic/media/ppmgr/tbff.h> |
| #include <uapi/linux/sched/types.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 10 |
| |
| #define PPMGR_TB_DETECT |
| /* #define CANVAS_RESERVED */ |
| |
| #define RECEIVER_NAME "ppmgr" |
| #define PROVIDER_NAME "ppmgr" |
| |
| #define MM_ALLOC_SIZE (SZ_16M + SZ_4M + SZ_2M) |
| #define MAX_WIDTH 1024 |
| #define MAX_HEIGHT 576 |
| #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) |
| |
| static int ass_index = -1; |
| |
| static DEFINE_SPINLOCK(lock); |
| static bool ppmgr_blocking; |
| static bool ppmgr_inited; |
| 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; |
| //static struct semaphore thread_sem; |
| static DEFINE_MUTEX(ppmgr_mutex); |
| static bool ppmgr_quit_flag; |
| |
| #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_last_flag; |
| static u32 tb_buff_wptr; |
| static u32 tb_buff_rptr; |
| 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 atomic_t tb_run_flag; |
| static bool tb_quit_flag; |
| static struct TB_DetectFuncPtr *gfunc; |
| static int tb_buffer_init(void); |
| static int tb_buffer_uninit(void); |
| #endif |
| static s32 ppmgr_src_canvas[3] = {-1, -1, -1}; |
| static s32 ppmgr_dst_canvas[2] = {-1, -1}; |
| static s8 local_canvas_status; |
| static bool need_data_notify; |
| static int dumpfirstframe; |
| static int count_scr; |
| static int count_dst; |
| |
| static unsigned int ppmgr_color_format; |
| MODULE_PARM_DESC(ppmgr_color_format, "\n ppmgr_color_format\n"); |
| module_param(ppmgr_color_format, uint, 0664); |
| |
| 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); */ |
| |
| bool is_valid_ppframe(struct ppframe_s *pp_vf) |
| { |
| return ((pp_vf >= &vfp_pool[0]) && (pp_vf <= &vfp_pool[VF_POOL_SIZE - 1])); |
| } |
| |
| /* *********************************************** |
| * |
| * Canvas helpers. |
| * |
| * ************************************************ |
| */ |
| |
| #include "decontour.h" |
| |
| #define DCNTR_POOL_SIZE VF_POOL_SIZE |
| |
| static s8 ppmgr_check_tvp_state(void) |
| { |
| struct provider_state_req_s req; |
| s8 ret = -1; |
| char *provider_name = vf_get_provider_name(PROVIDER_NAME); |
| |
| while (provider_name) { |
| if (!vf_get_provider_name(provider_name)) |
| break; |
| provider_name = |
| vf_get_provider_name(provider_name); |
| } |
| if (provider_name) { |
| req.vf = NULL; |
| req.req_type = REQ_STATE_SECURE; |
| req.req_result[0] = 0xffffffff; |
| vf_notify_provider_by_name(provider_name, |
| VFRAME_EVENT_RECEIVER_REQ_STATE, |
| (void *)&req); |
| if (req.req_result[0] == 0) |
| ret = 0; |
| else if (req.req_result[0] != 0xffffffff) |
| ret = 1; |
| } |
| return ret; |
| } |
| |
| #define Rd(adr) aml_read_vcbus(adr) |
| #define Wr(adr, val) aml_write_vcbus(adr, val) |
| |
| struct dcntr_mem_s dcntr_mem_info[DCNTR_POOL_SIZE]; |
| struct dcntr_mem_s dcntr_mem_info_last; |
| |
| static struct completion isr_done; |
| static u32 last_w; |
| static u32 last_h; |
| static u32 last_type; |
| |
| #define DCT_PRINT_INFO 0X1 |
| #define DCT_BYPASS 0X2 |
| #define DCT_USE_DS_SCALE 0X4 |
| #define DCT_DUMP_REG 0X8 |
| #define DCT_PROCESS_I 0X10 |
| #define DCT_REWRITE_REG 0X20 |
| |
| void wr_bits(unsigned int adr, |
| unsigned int val, |
| unsigned int start, |
| unsigned int len) |
| { |
| unsigned int mask = ((1 << len) - 1) << start; |
| |
| return aml_vcbus_update_bits(adr, mask, val << start); |
| } |
| |
| int dc_print(const char *fmt, ...) |
| { |
| if (ppmgr_device.debug_decontour & DCT_PRINT_INFO) { |
| char buf[256]; |
| int len = 0; |
| va_list args; |
| |
| va_start(args, fmt); |
| len = sprintf(buf, "dc:[%d]", 0); |
| vsnprintf(buf + len, 256 - len, fmt, args); |
| pr_info("%s", buf); |
| va_end(args); |
| } |
| return 0; |
| } |
| |
| static bool is_decontour_supported(void) |
| { |
| bool ret = false; |
| |
| if (ppmgr_device.reg_dct_irq_success) |
| ret = true; |
| |
| return ret; |
| } |
| |
| static void decontour_init(void) |
| { |
| int mem_flags; |
| int grd_size = SZ_512K; /*(81*8*16 byte)*45 = 455K*/ |
| int yds_size = SZ_512K + SZ_32K; /*960 * 576 = 540K*/ |
| int cds_size = yds_size / 2; /*960 * 576 / 2= 270K*/ |
| int total_size = grd_size + yds_size + cds_size; |
| int buffer_count = DCNTR_POOL_SIZE; |
| int i; |
| bool is_tvp = false; |
| |
| if (ppmgr_device.decontour_addr) |
| return; |
| |
| mem_flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_CMA_CLEAR; |
| if (ppmgr_check_tvp_state() == 1) { |
| mem_flags |= CODEC_MM_FLAGS_TVP; |
| is_tvp = true; |
| } |
| ppmgr_device.decontour_addr = codec_mm_alloc_for_dma("ppmgr-decontour", |
| buffer_count * total_size / PAGE_SIZE, 0, mem_flags); |
| if (ppmgr_device.decontour_addr == 0) |
| pr_err("decontour: alloc fail\n"); |
| |
| dc_print("decontour:alloc success %d, is_tvp=%d\n", |
| ppmgr_device.decontour_addr, is_tvp); |
| |
| for (i = 0; i < DCNTR_POOL_SIZE; i++) { |
| dcntr_mem_info[i].index = i; |
| dcntr_mem_info[i].grd_addr = 0; |
| dcntr_mem_info[i].yds_addr = 0; |
| dcntr_mem_info[i].cds_addr = 0; |
| dcntr_mem_info[i].grd_size = 0; |
| dcntr_mem_info[i].yds_size = 0; |
| dcntr_mem_info[i].cds_size = 0; |
| dcntr_mem_info[i].yds_canvas_mode = 0; |
| dcntr_mem_info[i].yds_canvas_mode = 0; |
| dcntr_mem_info[i].ds_ratio = 0; |
| dcntr_mem_info[i].free = false; |
| dcntr_mem_info[i].use_org = true; |
| dcntr_mem_info[i].pre_out_fmt = VIDTYPE_VIU_NV21; |
| dcntr_mem_info[i].grd_swap_64bit = false; |
| dcntr_mem_info[i].yds_swap_64bit = false; |
| dcntr_mem_info[i].cds_swap_64bit = false; |
| dcntr_mem_info[i].grd_little_endian = true; |
| dcntr_mem_info[i].yds_little_endian = true; |
| dcntr_mem_info[i].cds_little_endian = true; |
| } |
| |
| for (i = 0; i < buffer_count; i++) { |
| dcntr_mem_info[i].grd_addr = ppmgr_device.decontour_addr + i * total_size; |
| dcntr_mem_info[i].yds_addr = dcntr_mem_info[i].grd_addr + grd_size; |
| dcntr_mem_info[i].cds_addr = dcntr_mem_info[i].yds_addr + yds_size; |
| dcntr_mem_info[i].grd_size = grd_size; |
| dcntr_mem_info[i].yds_size = yds_size; |
| dcntr_mem_info[i].cds_size = cds_size; |
| dcntr_mem_info[i].free = true; |
| |
| dc_print("i=%d, grd_addr=%lx, yds_addr=%lx,cds_addr=%lx, %d, %d, %d\n", |
| i, |
| dcntr_mem_info[i].grd_addr, |
| dcntr_mem_info[i].yds_addr, |
| dcntr_mem_info[i].cds_addr, |
| grd_size, |
| yds_size, |
| cds_size); |
| } |
| init_completion(&isr_done); |
| last_w = 0; |
| last_h = 0; |
| last_type = 0; |
| dc_print("decontour: init\n"); |
| } |
| |
| static void decontour_buf_reset(void) |
| { |
| int i; |
| |
| if (ppmgr_device.decontour_addr == 0) |
| return; |
| |
| pr_info("decontour buf reset\n"); |
| for (i = 0; i < DCNTR_POOL_SIZE; i++) |
| dcntr_mem_info[i].free = true; |
| } |
| |
| static void decontour_uninit(void) |
| { |
| if (ppmgr_device.decontour_addr) |
| codec_mm_free_for_dma("ppmgr-decontour", |
| ppmgr_device.decontour_addr); |
| ppmgr_device.decontour_addr = 0; |
| dc_print("decontour: uninit\n"); |
| } |
| |
| irqreturn_t decontour_pre_isr(int irq, void *dev_id) |
| { |
| complete(&isr_done); |
| dc_print("decontour: isr\n"); |
| return IRQ_HANDLED; |
| } |
| |
| static void decontour_dump_reg(void) |
| { |
| u32 value; |
| int i; |
| |
| for (i = 0x4a00; i < 0x4a12; i++) { |
| value = Rd(i); |
| pr_info("reg=%x, value= %x\n", i, value); |
| } |
| value = Rd(DCNTR_GRD_WMIF_CTRL1); |
| dc_print("cds: DCNTR_GRD_WMIF_CTRL1: %x\n", value); |
| value = Rd(DCNTR_GRD_WMIF_CTRL3); |
| dc_print("cds: DCNTR_GRD_WMIF_CTRL3: %x\n", value); |
| value = Rd(DCNTR_GRD_WMIF_CTRL4); |
| dc_print("cds: DCNTR_GRD_WMIF_CTRL4: %x\n", value); |
| value = Rd(DCNTR_GRD_WMIF_SCOPE_X); |
| dc_print("cds: DCNTR_GRD_WMIF_SCOPE_X: %x\n", value); |
| value = Rd(DCNTR_GRD_WMIF_SCOPE_Y); |
| dc_print("cds: DCNTR_GRD_WMIF_SCOPE_Y: %x\n", value); |
| |
| value = Rd(DCNTR_YDS_WMIF_CTRL1); |
| dc_print("grd: DCNTR_YDS_WMIF_CTRL1: %x\n", value); |
| value = Rd(DCNTR_YDS_WMIF_CTRL3); |
| dc_print("grd: DCNTR_YDS_WMIF_CTRL3: %x\n", value); |
| value = Rd(DCNTR_YDS_WMIF_CTRL4); |
| dc_print("grd: DCNTR_YDS_WMIF_CTRL4: %x\n", value); |
| value = Rd(DCNTR_YDS_WMIF_SCOPE_X); |
| dc_print("grd: DCNTR_YDS_WMIF_SCOPE_X: %x\n", value); |
| value = Rd(DCNTR_YDS_WMIF_SCOPE_Y); |
| dc_print("grd: DCNTR_YDS_WMIF_SCOPE_Y: %x\n", value); |
| |
| value = Rd(DCNTR_CDS_WMIF_CTRL1); |
| dc_print("yds: DCNTR_CDS_WMIF_CTRL1: %x\n", value); |
| value = Rd(DCNTR_CDS_WMIF_CTRL3); |
| dc_print("yds: DCNTR_CDS_WMIF_CTRL3: %x\n", value); |
| value = Rd(DCNTR_CDS_WMIF_CTRL4); |
| dc_print("yds: DCNTR_CDS_WMIF_CTRL4: %x\n", value); |
| value = Rd(DCNTR_CDS_WMIF_SCOPE_X); |
| dc_print("yds: DCNTR_CDS_WMIF_SCOPE_X: %x\n", value); |
| value = Rd(DCNTR_CDS_WMIF_SCOPE_Y); |
| dc_print("yds: DCNTR_CDS_WMIF_SCOPE_Y: %x\n", value); |
| |
| value = Rd(DCNTR_PRE_ARB_MODE); |
| dc_print("DCNTR_PRE_ARB_MODE: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_REQEN_SLV); |
| dc_print("DCNTR_PRE_ARB_REQEN_SLV: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_WEIGH0_SLV); |
| dc_print("DCNTR_PRE_ARB_WEIGH0_SLV: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_WEIGH1_SLV); |
| dc_print("DCNTR_PRE_ARB_WEIGH1_SLV: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_UGT); |
| dc_print("DCNTR_PRE_ARB_UGT: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_LIMT0); |
| dc_print("DCNTR_PRE_ARB_LIMT0: %x\n", value); |
| |
| value = Rd(DCNTR_PRE_ARB_STATUS); |
| dc_print("DCNTR_PRE_ARB_STATUS: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_DBG_CTRL); |
| dc_print("DCNTR_PRE_ARB_DBG_CTRL: %x\n", value); |
| value = Rd(DCNTR_PRE_ARB_PROT); |
| dc_print("DCNTR_PRE_ARB_PROT: %x\n", value); |
| |
| value = Rd(DCTR_BGRID_TOP_FSIZE); |
| dc_print("DCTR_BGRID_TOP_FSIZE: %x\n", value); |
| value = Rd(DCTR_BGRID_TOP_HDNUM); |
| dc_print("DCTR_BGRID_TOP_HDNUM: %x\n", value); |
| value = Rd(DCTR_BGRID_TOP_CTRL0); |
| dc_print("DCTR_BGRID_TOP_CTRL0: %x\n", value); |
| value = Rd(DCTR_BGRID_TOP_FMT); |
| dc_print("DCTR_BGRID_TOP_FMT: %x\n", value); |
| value = Rd(DCTR_BGRID_TOP_GCLK); |
| dc_print("DCTR_BGRID_TOP_GCLK: %x\n", value); |
| value = Rd(DCTR_BGRID_TOP_HOLD); |
| dc_print("DCTR_BGRID_TOP_HOLD: %x\n", value); |
| |
| value = Rd(DCNTR_GRID_GEN_REG); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_GEN_REG=%x\n", value); |
| value = Rd(DCNTR_GRID_GEN_REG2); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_GEN_REG2=%x\n", value); |
| value = Rd(DCNTR_GRID_CANVAS0); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_CANVAS0=%x\n", value); |
| value = Rd(DCNTR_GRID_LUMA_X0); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_LUMA_X0=%x\n", value); |
| value = Rd(DCNTR_GRID_LUMA_Y0); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_LUMA_Y0=%x\n", value); |
| value = Rd(DCNTR_GRID_RPT_LOOP); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_RPT_LOOP=%x\n", value); |
| value = Rd(DCNTR_GRID_LUMA0_RPT_PAT); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_LUMA0_RPT_PAT=%x\n", value); |
| value = Rd(DCNTR_GRID_CHROMA0_RPT_PAT); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_CHROMA0_RPT_PAT=%x\n", value); |
| value = Rd(DCNTR_GRID_DUMMY_PIXEL); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_DUMMY_PIXEL=%x\n", value); |
| |
| value = Rd(DCNTR_GRID_LUMA_FIFO_SIZE); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_LUMA_FIFO_SIZE=%x\n", value); |
| |
| value = Rd(DCNTR_GRID_RANGE_MAP_Y); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_RANGE_MAP_Y=%x\n", value); |
| value = Rd(DCNTR_GRID_RANGE_MAP_CB); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_RANGE_MAP_CB=%x\n", value); |
| value = Rd(DCNTR_GRID_RANGE_MAP_CR); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_RANGE_MAP_CR=%x\n", value); |
| value = Rd(DCNTR_GRID_URGENT_CTRL); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_URGENT_CTRL=%x\n", value); |
| |
| value = Rd(DCNTR_GRID_GEN_REG3); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_GEN_REG3=%x\n", value); |
| value = Rd(DCNTR_GRID_AXI_CMD_CNT); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_AXI_CMD_CNT=%x\n", value); |
| value = Rd(DCNTR_GRID_AXI_RDAT_CNT); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_AXI_RDAT_CNT=%x\n", value); |
| value = Rd(DCNTR_GRID_FMT_CTRL); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_FMT_CTRL=%x\n", value); |
| value = Rd(DCNTR_GRID_FMT_W); //grd_num_use |
| dc_print("decontour: DCNTR_GRID_FMT_W=%x\n", value); |
| |
| if (get_cpu_type() <= MESON_CPU_MAJOR_ID_T5) |
| return; |
| |
| value = Rd(DCNTR_GRID_BADDR_Y); |
| dc_print("decontour: DCNTR_GRID_BADDR_Y=%x\n", value); |
| value = Rd(DCNTR_GRID_BADDR_CB); |
| dc_print("decontour: DCNTR_GRID_BADDR_CB=%x\n", value); |
| value = Rd(DCNTR_GRID_BADDR_CR); |
| dc_print("decontour: DCNTR_GRID_BADDR_CR=%x\n", value); |
| |
| value = Rd(DCNTR_GRID_STRIDE_0); |
| dc_print("decontour: DCNTR_GRID_STRIDE_0=%x\n", value); |
| value = Rd(DCNTR_GRID_STRIDE_1); |
| dc_print("decontour: DCNTR_GRID_STRIDE_1=%x\n", value); |
| |
| value = Rd(DCNTR_GRID_BADDR_Y_F1); |
| dc_print("decontour: DCNTR_GRID_BADDR_Y_F1=%x\n", value); |
| value = Rd(DCNTR_GRID_BADDR_CB_F1); |
| dc_print("decontour: DCNTR_GRID_BADDR_CB_F1=%x\n", value); |
| value = Rd(DCNTR_GRID_BADDR_CR_F1); |
| dc_print("decontour: DCNTR_GRID_BADDR_CR_F1=%x\n", value); |
| value = Rd(DCNTR_GRID_STRIDE_0_F1); |
| dc_print("decontour: DCNTR_GRID_STRIDE_0_F1=%x\n", value); |
| value = Rd(DCNTR_GRID_STRIDE_1_F1); |
| dc_print("decontour: DCNTR_GRID_STRIDE_1_F1=%x\n", value); |
| } |
| |
| static void decontour_print_parm(struct dcntr_mem_s *dcntr_mem) |
| { |
| dc_print("i=%d,grd_addr=%lx,y_addr=%lx,c_addr=%lx,g_size=%d,y_size=%d,c_size=%d,ratio=%d\n", |
| dcntr_mem->index, |
| dcntr_mem->grd_addr, |
| dcntr_mem->yds_addr, |
| dcntr_mem->cds_addr, |
| dcntr_mem->grd_size, |
| dcntr_mem->yds_size, |
| dcntr_mem->cds_size, |
| dcntr_mem->ds_ratio); |
| dc_print("pre_out_fmt=%d,yflt_wrmif_length=%d,cflt_wrmif_length=%d,use_org=%d\n", |
| dcntr_mem->pre_out_fmt, |
| dcntr_mem->yflt_wrmif_length, |
| dcntr_mem->cflt_wrmif_length, |
| dcntr_mem->use_org); |
| |
| dc_print("grd_swap=%d,yds_swap=%x,cds_swap=%x,grd_endian=%x,yds_endian=%d,cds_endian=%dn", |
| dcntr_mem->grd_swap_64bit, |
| dcntr_mem->yds_swap_64bit, |
| dcntr_mem->cds_swap_64bit, |
| dcntr_mem->grd_little_endian, |
| dcntr_mem->yds_little_endian, |
| dcntr_mem->cds_little_endian); |
| |
| dc_print("yds_canvas_mode=%d,cds_canvas_mode=%d\n", |
| dcntr_mem->yds_canvas_mode, |
| dcntr_mem->cds_canvas_mode); |
| } |
| |
| static int decontour_dump_output(u32 w, u32 h, struct dcntr_mem_s *dcntr_mem, int skip) |
| { |
| struct file *fp; |
| mm_segment_t fs; |
| loff_t pos; |
| char name_buf[32]; |
| int write_size; |
| u8 *data; |
| |
| if (w == 0 || h == 0) |
| return -7; |
| write_size = dcntr_mem->grd_size; |
| dc_print("addr =%lx, size=%d\n", dcntr_mem->grd_addr, write_size); |
| snprintf(name_buf, sizeof(name_buf), "/data/tmp/%d-%d.grid", |
| w, h); |
| fp = filp_open(name_buf, O_CREAT | O_RDWR, 0644); |
| |
| if (IS_ERR(fp)) |
| return -1; |
| dc_print("decontour:dump_2: name_buf=%s\n", name_buf); |
| data = codec_mm_vmap(dcntr_mem->grd_addr, write_size); |
| dc_print("(ulong)data =%lx\n", (ulong)data); |
| if (!data) |
| return -2; |
| fs = get_fs(); |
| set_fs(KERNEL_DS); |
| pos = 0; |
| vfs_write(fp, (const char *)data, write_size, &pos); |
| vfs_fsync(fp, 0); |
| dc_print("decontour: write %u size to addr%p\n", write_size, data); |
| codec_mm_unmap_phyaddr(data); |
| filp_close(fp, NULL); |
| set_fs(fs); |
| |
| dc_print("decontour:dump_2.0/2"); |
| write_size = w * h; |
| dc_print("decontour:dump_4:yds_addr =%lx, write_size=%d\n", |
| dcntr_mem->yds_addr, write_size); |
| dc_print("decontour:dump_4:cds_addr =%lx\n", dcntr_mem->cds_addr); |
| snprintf(name_buf, sizeof(name_buf), "/data/tmp/ds_out.yuv"); |
| |
| fp = filp_open(name_buf, O_CREAT | O_RDWR, 0644); |
| if (IS_ERR(fp)) { |
| pr_err("decontour: create %s fail.\n", name_buf); |
| return -4; |
| } |
| dc_print("decontour:dump_4: name_buf=%s\n", name_buf); |
| |
| data = codec_mm_vmap(dcntr_mem->yds_addr, dcntr_mem->yds_size); |
| dc_print("decontour:dump_3\n"); |
| if (!data) |
| return -5; |
| fs = get_fs(); |
| set_fs(KERNEL_DS); |
| pos = 0; |
| vfs_write(fp, (const char *)data, write_size, &pos); |
| vfs_fsync(fp, 0); |
| dc_print("decontour: write %u size to file.addr%p\n", write_size, data); |
| codec_mm_unmap_phyaddr(data); |
| pos = write_size; |
| |
| write_size = w * h / 2; |
| data = codec_mm_vmap(dcntr_mem->cds_addr, dcntr_mem->cds_size); |
| dc_print("decontour:dump_4\n"); |
| if (!data) |
| return -6; |
| vfs_write(fp, (const char *)data, write_size, &pos); |
| vfs_fsync(fp, 0); |
| dc_print("decontour: write %u size to file.addr%p\n", write_size, data); |
| codec_mm_unmap_phyaddr(data); |
| filp_close(fp, NULL); |
| set_fs(fs); |
| return 0; |
| } |
| |
| static int decontour_pre_process(struct vframe_s *vf) |
| { |
| int mif_read_width; /*grid read mif input*/ |
| int mif_read_height; |
| int mif_out_width; /*grid read mif output; also dct input*/ |
| int mif_out_height; |
| u32 ds_out_width = 0; /*dct ds output*/ |
| u32 ds_out_height = 0; |
| int canvas_width; |
| int canvas_height; |
| u32 vf_org_width; |
| u32 vf_org_height; |
| u32 grd_num; |
| u32 reg_grd_xnum; |
| u32 reg_grd_ynum; |
| u32 grd_xsize; |
| u32 grd_ysize; |
| /* u32 grid_wrmif_length; */ |
| u32 yflt_wrmif_length; |
| u32 cflt_wrmif_length; |
| int ds_ratio = 0;/*0:(1:1) 1:(1:2) 2:(1:4)*/ |
| u32 phy_addr_0, phy_addr_1, phy_addr_2; |
| struct canvas_s src_cs0, src_cs1, src_cs2; |
| int canvas_id_0, canvas_id_1, canvas_id_2; |
| int src_fmt = 2; /*default 420*/ |
| struct dcntr_mem_s *dcntr_mem; |
| int timeout = 0; |
| int i; |
| int mif_reverse; |
| int swap_64bit; |
| int ret; |
| int skip = 0; |
| u32 pic_struct; |
| u32 h_avg; |
| u32 bit_mode; |
| bool need_ds = false; |
| u32 burst_len = 2; |
| bool format_changed = false; |
| bool unsupported_resolution = false; |
| u32 is_interlace = 0; |
| u32 block_mode; |
| u32 endian; |
| u32 pic_32byte_aligned = 0; |
| bool support_canvas = false; |
| int src_hsize; |
| int src_vsize; |
| |
| if (!vf) |
| return -1; |
| |
| vf->decontour_pre = NULL; |
| |
| if (ppmgr_device.bypass_decontour == 1) |
| return 0; |
| |
| if (get_cpu_type() <= MESON_CPU_MAJOR_ID_T5) |
| support_canvas = true; |
| |
| if (vf->type & VIDTYPE_INTERLACE) |
| if (!ppmgr_device.i_do_decontour) |
| return 0; |
| |
| if (vf->type & VIDTYPE_COMPRESS) { |
| if ((vf->type & VIDTYPE_NO_DW) || vf->canvas0Addr == 0) { |
| dc_print("is afbc, but no dw\n"); |
| return 0; |
| } |
| } |
| |
| if (vf->width == 0 || vf->height == 0) { |
| dc_print("w*h =%d*%d\n", vf->width, vf->height); |
| return 0; |
| } |
| |
| if ((vf->width * vf->height) < (160 * 120)) |
| return 0; |
| |
| if ((vf->type & VIDTYPE_VIU_422) && !(vf->type & 0x10000000)) { |
| src_fmt = 0; |
| need_ds = true;/*422 is one plane, post not support, need pre out nv21*/ |
| } else if ((vf->type & VIDTYPE_VIU_NV21) || |
| (vf->type & 0x10000000)) {/*hdmi in dw is nv21 VIDTYPE_DW_NV21*/ |
| src_fmt = 2; |
| } else { |
| dc_print("not support format vf->type =%x\n", vf->type); |
| return 0; /*current one support 422 nv21*/ |
| } |
| |
| if (vf->type & VIDTYPE_COMPRESS) { |
| vf_org_width = vf->compWidth; |
| vf_org_height = vf->compHeight; |
| } else { |
| vf_org_width = vf->width; |
| vf_org_height = vf->height; |
| } |
| |
| if (ppmgr_device.decontour_addr == 0) |
| decontour_init(); |
| |
| if (ppmgr_device.decontour_addr == 0) |
| return 0; |
| |
| pic_struct = 0; |
| h_avg = 0; |
| mif_out_width = vf->width; |
| mif_out_height = vf->height; |
| mif_read_width = vf->width; |
| mif_read_height = vf->height; |
| |
| if (vf->type & VIDTYPE_INTERLACE) { |
| is_interlace = 1; |
| if (src_fmt == 2) {/*decoder output, top in odd rows*/ |
| if ((vf->type & VIDTYPE_INTERLACE_BOTTOM) == 0x3) |
| pic_struct = 6;/*4 line read 1*/ |
| else |
| pic_struct = 5;/*4 line read 1*/ |
| h_avg = 1; |
| skip = 1; |
| mif_out_width = vf->width >> 1; |
| mif_out_height = vf->height >> 2; |
| } else if (src_fmt == 0) {/*hdmiin output, In the first half of the line*/ |
| mif_out_width = vf->width; |
| mif_out_height = vf->height >> 1; |
| mif_read_height = vf->height >> 1; |
| need_ds = 1; |
| if (mif_out_width > 960 || mif_out_height > 540) |
| ds_ratio = 1; |
| } |
| } else { |
| if (vf->width > 1920 || vf->height > 1080) { |
| ds_ratio = 1; |
| skip = 1; |
| mif_out_width = vf->width >> 1; |
| mif_out_height = vf->height >> 1; |
| } else if (vf->width > 960 || vf->height > 540) { |
| if ((ppmgr_device.debug_decontour & DCT_USE_DS_SCALE) || |
| src_fmt == 0) { /*hdmi in always use ds*/ |
| ds_ratio = 1; |
| } else { |
| ds_ratio = 0; /*decoder use mif skip for save ddr*/ |
| skip = 1; |
| dc_print("1080p use mif skip\n"); |
| mif_out_width = vf->width >> 1; |
| mif_out_height = vf->height >> 1; |
| } |
| } |
| |
| if (skip && src_fmt == 2) { |
| pic_struct = 4; |
| h_avg = 1; |
| } |
| } |
| |
| ds_out_width = mif_out_width >> ds_ratio; |
| ds_out_height = mif_out_height >> ds_ratio; |
| |
| if (ds_out_width < 16 || ds_out_height < 120) { |
| dc_print("not supported: vf:%d * %d", vf->width, vf->height); |
| return 0; |
| } |
| |
| dc_print("src_fmt=%d, pic_struct=%d, h_avg =%d, bitdepth=%x\n", |
| src_fmt, pic_struct, h_avg, vf->bitdepth); |
| |
| dc_print("vf:%d * %d; mif_read:%d*%d;mif_out:%d * %d; ds_ratio=%d, skip=%d;ds_out:%d*%d\n", |
| vf->width, vf->height, |
| mif_read_width, mif_read_height, |
| mif_out_width, mif_out_height, |
| ds_ratio, skip, |
| ds_out_width, ds_out_height); |
| |
| for (i = 0; i < DCNTR_POOL_SIZE; i++) { |
| if (dcntr_mem_info[i].free) { |
| dcntr_mem_info[i].free = false; |
| break; |
| } |
| } |
| if (i == DCNTR_POOL_SIZE) { |
| pr_err("decontour: no free mem\n"); |
| return -1; |
| } |
| dcntr_mem = &dcntr_mem_info[i]; |
| |
| dcntr_mem->use_org = true; |
| dcntr_mem->ds_ratio = 0; |
| |
| if (ds_ratio || skip || need_ds) |
| dcntr_mem->use_org = false; |
| |
| if (!dcntr_mem->use_org) { |
| dcntr_mem->ds_ratio = ds_ratio; |
| if (skip) |
| dcntr_mem->ds_ratio = dcntr_mem->ds_ratio + 1; |
| |
| if (need_ds && (vf->type & VIDTYPE_COMPRESS)) |
| dcntr_mem->ds_ratio = (vf->compWidth / vf->width) >> 1; |
| } |
| |
| if (dcntr_mem->use_org) { |
| if (vf->type & VIDTYPE_COMPRESS) { |
| if ((vf->compWidth / vf->width) * vf->width != vf->compWidth) |
| unsupported_resolution = true; |
| if ((vf->compHeight / vf->height) * vf->height != vf->compHeight) |
| unsupported_resolution = true; |
| } |
| } else { |
| if ((ds_out_width << dcntr_mem->ds_ratio) != vf_org_width) |
| unsupported_resolution = true; |
| if ((ds_out_height << dcntr_mem->ds_ratio) != (vf_org_height >> is_interlace)) |
| unsupported_resolution = true; |
| } |
| if (unsupported_resolution) { |
| dcntr_mem->free = true; |
| dc_print("unsupported resolution %d*%d, com %d*%d, ds_ratio=%d\n", |
| vf->width, vf->height, |
| vf->compWidth, vf->compHeight, |
| dcntr_mem->ds_ratio); |
| return 0; |
| } |
| |
| vf->decontour_pre = (void *)dcntr_mem; |
| |
| if (vf->canvas0Addr == (u32)-1) { |
| phy_addr_0 = vf->canvas0_config[0].phy_addr; |
| phy_addr_1 = vf->canvas0_config[1].phy_addr; |
| phy_addr_2 = vf->canvas0_config[2].phy_addr; |
| canvas_config_config(ppmgr_src_canvas[0], |
| &vf->canvas0_config[0]); |
| canvas_config_config(ppmgr_src_canvas[1], |
| &vf->canvas0_config[1]); |
| canvas_config_config(ppmgr_src_canvas[2], |
| &vf->canvas0_config[2]); |
| canvas_id_0 = ppmgr_src_canvas[0]; |
| canvas_id_1 = ppmgr_src_canvas[1]; |
| canvas_id_2 = ppmgr_src_canvas[2]; |
| canvas_width = vf->canvas0_config[0].width; |
| canvas_height = vf->canvas0_config[0].height; |
| block_mode = vf->canvas0_config[0].block_mode; |
| endian = vf->canvas0_config[0].endian; |
| } else { |
| dc_print("source is canvas\n"); |
| canvas_read(vf->canvas0Addr & 0xff, &src_cs0); |
| canvas_read(vf->canvas0Addr >> 8 & 0xff, &src_cs1); |
| canvas_read(vf->canvas0Addr >> 16 & 0xff, &src_cs2); |
| phy_addr_0 = src_cs0.addr; |
| phy_addr_1 = src_cs1.addr; |
| phy_addr_2 = src_cs2.addr; |
| canvas_id_0 = vf->canvas0Addr & 0xff; |
| canvas_id_1 = vf->canvas0Addr >> 8 & 0xff; |
| canvas_id_2 = vf->canvas0Addr >> 16 & 0xff; |
| canvas_width = src_cs0.width; |
| canvas_height = src_cs0.height; |
| block_mode = src_cs0.blkmode; |
| endian = src_cs0.endian; |
| } |
| dc_print("block_mode=%d, endian=%d\n", block_mode, endian); |
| |
| if (last_w != vf->width || |
| last_h != vf->height || |
| last_type != vf->type || |
| (ppmgr_device.debug_decontour & DCT_REWRITE_REG)) |
| format_changed = true; |
| |
| if (!format_changed) { |
| dcntr_mem->grd_swap_64bit = dcntr_mem_info_last.grd_swap_64bit; |
| dcntr_mem->yds_swap_64bit = dcntr_mem_info_last.yds_swap_64bit; |
| dcntr_mem->cds_swap_64bit = dcntr_mem_info_last.cds_swap_64bit; |
| dcntr_mem->grd_little_endian = dcntr_mem_info_last.grd_little_endian; |
| dcntr_mem->yds_little_endian = dcntr_mem_info_last.yds_little_endian; |
| dcntr_mem->cds_little_endian = dcntr_mem_info_last.cds_little_endian; |
| dcntr_mem->yflt_wrmif_length = dcntr_mem_info_last.yflt_wrmif_length; |
| dcntr_mem->cflt_wrmif_length = dcntr_mem_info_last.cflt_wrmif_length; |
| goto SET_ADDR; |
| } |
| last_w = vf->width; |
| last_h = vf->height; |
| last_type = vf->type; |
| |
| if (src_fmt == 0) { |
| src_hsize = canvas_width >> 1; |
| src_vsize = canvas_height; |
| } else { |
| src_hsize = canvas_width; |
| src_vsize = canvas_height; |
| } |
| ini_dcntr_pre(mif_out_width, mif_out_height, 2, ds_ratio); |
| grd_num = Rd(DCTR_BGRID_PARAM3_PRE); |
| reg_grd_xnum = (grd_num >> 16) & (0x3ff); |
| reg_grd_ynum = grd_num & (0x3ff); |
| |
| grd_xsize = reg_grd_xnum << 3; |
| grd_ysize = reg_grd_ynum; |
| |
| /* grid_wrmif_length = 81 * 46 * 8; */ |
| yflt_wrmif_length = ds_out_width; |
| cflt_wrmif_length = ds_out_width; |
| |
| dc_print("canvas_width=%d, canvas_height=%d, src_hsize=%d, src_vsize=%d\n", |
| canvas_width, canvas_height, |
| src_hsize, src_vsize); |
| |
| if (canvas_width % 32) |
| burst_len = 0; |
| else if (canvas_width % 64) |
| burst_len = 1; |
| |
| if (block_mode && !support_canvas) |
| burst_len = block_mode; |
| |
| dcntr_grid_rdmif(canvas_id_0, /*int canvas_id0,*/ |
| canvas_id_1, /*int canvas_id1,*/ |
| canvas_id_2, /*int canvas_id2,*/ |
| phy_addr_0, /*int canvas_baddr0,*/ |
| phy_addr_1, /*int canvas_baddr1,*/ |
| phy_addr_2, /*int canvas_baddr2,*/ |
| src_hsize, /*int src_hsize,*/ |
| src_vsize, /*int src_vsize,*/ |
| src_fmt, /*1 = RGB/YCBCR(3 bytes/pixel), 0=422 (2 bytes/pixel) 2:420 (two canvas)*/ |
| 0, /*int mif_x_start,*/ |
| mif_read_width - 1, /*int mif_x_end ,*/ |
| 0, /*int mif_y_start,*/ |
| mif_read_height - 1, /*int mif_y_end ,*/ |
| 0, /*int mif_reverse // 0 : no reverse*/ |
| pic_struct,/*0 : frame; 2:top_field; 3:bot_field; 4:y skip, uv no skip;*/ |
| /*5:top_field 1/4; 6 bot_field 1/4*/ |
| h_avg); /*0 : no avg 1:y_avg 2:c_avg 3:y&c avg*/ |
| |
| mif_reverse = 1; |
| swap_64bit = 0; |
| if (mif_reverse == 1) { |
| dcntr_mem->grd_swap_64bit = false; |
| dcntr_mem->yds_swap_64bit = false; |
| dcntr_mem->cds_swap_64bit = false; |
| dcntr_mem->grd_little_endian = true; |
| dcntr_mem->yds_little_endian = true; |
| dcntr_mem->cds_little_endian = true; |
| } |
| dcntr_grid_wrmif(1, /*int mif_index, //0:cds 1:grd 2:yds*/ |
| 0, /*int mem_mode, //0:linear address mode 1:canvas mode*/ |
| 5, /*int src_fmt , //0:4bit 1:8bit 2:16bit 3:32bit 4:64bit 5:128bit*/ |
| ass_index, /*int canvas_id*/ |
| 0, /*int mif_x_start*/ |
| grd_xsize - 1, /*int mif_x_end*/ |
| 0, /*int mif_y_start*/ |
| grd_ysize - 1, /*int mif_y_end*/ |
| swap_64bit, |
| mif_reverse, /*int mif_reverse, /0 : no reverse*/ |
| dcntr_mem->grd_addr, /*int linear_baddr*/ |
| grd_xsize); /*int linear_length // DDR read length = linear_length*128 bits*/ |
| |
| if (ds_ratio || skip || need_ds) { |
| yflt_wrmif_length = yflt_wrmif_length * 8 / 128; |
| cflt_wrmif_length = cflt_wrmif_length * 8 / 128; |
| dcntr_mem->yflt_wrmif_length = yflt_wrmif_length; |
| dcntr_mem->cflt_wrmif_length = cflt_wrmif_length; |
| |
| dcntr_grid_wrmif(2, /*int mif_index, //0:cds 1:grd 2:yds*/ |
| 0, /*int mem_mode, //0:linear address mode 1:canvas mode*/ |
| 1, /*int src_fmt, //0:4bit 1:8bit 2:16bit 3:32bit 4:64bit 5:128bit*/ |
| ppmgr_dst_canvas[0], /*int canvas_id*/ |
| 0, /*int mif_x_start*/ |
| ds_out_width - 1, /*int mif_x_end*/ |
| 0, /*int mif_y_start*/ |
| ds_out_height - 1, /*int mif_y_end*/ |
| swap_64bit, |
| mif_reverse, /*int mif_reverse , //0 : no reverse*/ |
| dcntr_mem->yds_addr, /*int linear_baddr*/ |
| yflt_wrmif_length); /*DDR read length = linear_length*128 bits*/ |
| |
| dcntr_grid_wrmif(0, /*int mif_index, //0:cds 1:grd 2:yds*/ |
| 0, /*int mem_mode, //0:linear address mode 1:canvas mode*/ |
| 2, /*int src_fmt, //0:4bit 1:8bit 2:16bit 3:32bit 4:64bit 5:128bit*/ |
| ppmgr_dst_canvas[1], /*int canvas_id*/ |
| 0, /*int mif_x_start*/ |
| (ds_out_width >> 1) - 1, /*int mif_x_end*/ |
| 0, /*int mif_y_start*/ |
| (ds_out_height >> 1) - 1, /*int mif_y_end*/ |
| swap_64bit, |
| mif_reverse, /*int mif_reverse , //0 : no reverse*/ |
| dcntr_mem->cds_addr, /*int linear_baddr*/ |
| cflt_wrmif_length); /*DDR read length = linear_length*128 bits*/ |
| } |
| |
| wr_bits(DCTR_BGRID_TOP_CTRL0, 1, 2, 2);/*reg_din_sel: 1:dos 2:vdin 0/3:disable*/ |
| |
| if (ds_ratio || skip || need_ds) { |
| wr_bits(DCTR_BGRID_TOP_CTRL0, 1, 1, 1);/*reg_ds_mif_en: 1=on 0=off*/ |
| wr_bits(DCTR_BGRID_TOP_FMT, 2, 19, 2); /*reg_fmt_mode, 2=420, 1=422, 0=444*/ |
| |
| if (ds_ratio == 0) |
| wr_bits(DCTR_BGRID_PATH_PRE, 1, 4, 1); /*reg_grd_path 0=ds 1=ori*/ |
| else |
| wr_bits(DCTR_BGRID_PATH_PRE, 0, 4, 1); /*reg_grd_path 0=ds 1=ori*/ |
| |
| if (ds_ratio == 1) |
| wr_bits(DCTR_DS_PRE, 0x5, 0, 4); /*reg_ds_rate_xy*/ |
| else if (ds_ratio == 0) |
| wr_bits(DCTR_DS_PRE, 0x0, 0, 4); /*reg_ds_rate_xy*/ |
| } else { |
| wr_bits(DCTR_BGRID_TOP_CTRL0, 0, 1, 1); /*reg_ds_mif_en: 1=on 0=off*/ |
| wr_bits(DCTR_BGRID_PATH_PRE, 1, 4, 1); /*reg_grd_path 0=ds 1=ori*/ |
| wr_bits(DCTR_DS_PRE, 0x0, 0, 4); /*reg_ds_rate_xy*/ |
| } |
| |
| if (src_fmt == 0 && (vf->bitdepth & BITDEPTH_Y10) && |
| ((vf->type & VIDTYPE_COMPRESS) == 0)) {/*all dw is 8bit*/ |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| bit_mode = 3; |
| else |
| bit_mode = 1; |
| wr_bits(DCNTR_GRID_GEN_REG3, bit_mode, 8, 2);/*0->8bit; 1->10bit422; 2->10bit444*/ |
| wr_bits(DCNTR_GRID_GEN_REG3, 0x3, 4, 3); /*cntl_blk_len: vd1 default is 3*/ |
| } |
| wr_bits(DCNTR_GRID_GEN_REG3, (burst_len & 0x3), 1, 2); |
| dcntr_mem_info_last = *dcntr_mem; |
| |
| SET_ADDR: |
| if (support_canvas) { |
| Wr(DCNTR_GRID_CANVAS0, |
| (canvas_id_2 << 16) | |
| (canvas_id_1 << 8) | |
| (canvas_id_0 << 0)); |
| Wr(DCNTR_GRD_WMIF_CTRL4, dcntr_mem->grd_addr); |
| Wr(DCNTR_YDS_WMIF_CTRL4, dcntr_mem->yds_addr); |
| Wr(DCNTR_CDS_WMIF_CTRL4, dcntr_mem->cds_addr); |
| } else { |
| Wr(DCNTR_GRID_BADDR_Y, phy_addr_0 >> 4); |
| Wr(DCNTR_GRID_BADDR_CB, phy_addr_1 >> 4); |
| Wr(DCNTR_GRID_BADDR_CR, phy_addr_2 >> 4); |
| |
| Wr(DCNTR_GRD_WMIF_CTRL4, dcntr_mem->grd_addr >> 4); |
| Wr(DCNTR_YDS_WMIF_CTRL4, dcntr_mem->yds_addr >> 4); |
| Wr(DCNTR_CDS_WMIF_CTRL4, dcntr_mem->cds_addr >> 4); |
| |
| wr_bits(DCNTR_GRID_GEN_REG3, block_mode, 12, 2); |
| wr_bits(DCNTR_GRID_GEN_REG3, block_mode, 14, 2); |
| if (block_mode) |
| pic_32byte_aligned = 7; |
| wr_bits(DCNTR_GRID_GEN_REG3, |
| (pic_32byte_aligned << 7) | |
| (block_mode << 4) | |
| (block_mode << 2) | |
| (block_mode << 0), |
| 18, 9); |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) { |
| wr_bits(DCNTR_GRID_GEN_REG3, 0, 0, 1); |
| dc_print("LINEAR:flag=%x\n", vf->flag); |
| } else { |
| wr_bits(DCNTR_GRID_GEN_REG3, 1, 0, 1); |
| dc_print("block_mode:flag=%x\n", vf->flag); |
| } |
| } |
| |
| if (ppmgr_device.debug_decontour & DCT_DUMP_REG) |
| decontour_dump_reg(); |
| |
| dc_print("decontour:start_1\n"); |
| wr_bits(DCTR_BGRID_TOP_CTRL0, 1, 31, 1); |
| dc_print("decontour:start_2\n"); |
| |
| timeout = wait_for_completion_timeout(&isr_done, |
| msecs_to_jiffies(200)); |
| if (!timeout) |
| pr_err("decontour:wait isr timeout\n"); |
| |
| if (ppmgr_device.dump_grid) { |
| ret = decontour_dump_output(ds_out_width, ds_out_height, |
| dcntr_mem, skip); |
| if (ret) |
| pr_err("decontour_dump_output error, ret=%d\n", ret); |
| ppmgr_device.dump_grid = 0; |
| } |
| |
| if (ppmgr_device.debug_decontour & DCT_PRINT_INFO) |
| decontour_print_parm(dcntr_mem); |
| |
| dc_print("decontour:ok index=%d\n", vf->omx_index); |
| return 0; |
| } |
| |
| /************************************************ |
| * |
| * 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) |
| { |
| struct vframe_s *vf; |
| |
| if (ppmgr_blocking) |
| return NULL; |
| vf = vfq_pop(&q_ready); |
| if (vf) |
| ppmgr_device.get_count++; |
| return vf; |
| } |
| |
| 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) { |
| pr_info("%s: ppmgr_blocking is 1\n", __func__); |
| return; |
| } |
| ppmgr_device.put_count++; |
| |
| 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) { |
| pr_err("ppmgr put error1 %d\n", 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) { |
| pr_err("ppmgr put error2 %d\n", 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 = NULL; |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vfp = vf_get_provider(RECEIVER_NAME); |
| #endif |
| 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_source_type(struct vframe_s *vf) |
| { |
| enum ppmgr_source_type ret; |
| int interlace_mode; |
| |
| interlace_mode = vf->type & VIDTYPE_TYPEMASK; |
| if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI || |
| vf->source_type == VFRAME_SOURCE_TYPE_CVBS) { |
| if ((vf->bitdepth & BITDEPTH_Y10) && |
| (!(vf->type & VIDTYPE_COMPRESS)) && |
| (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL)) |
| ret = VDIN_10BIT_NORMAL; |
| else |
| ret = VDIN_8BIT_NORMAL; |
| } else { |
| if ((vf->bitdepth & BITDEPTH_Y10) && |
| (!(vf->type & VIDTYPE_COMPRESS)) && |
| (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL)) { |
| if (interlace_mode == VIDTYPE_INTERLACE_TOP) |
| ret = DECODER_10BIT_TOP; |
| else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM) |
| ret = DECODER_10BIT_BOTTOM; |
| else |
| ret = DECODER_10BIT_NORMAL; |
| } else { |
| if (interlace_mode == VIDTYPE_INTERLACE_TOP) |
| ret = DECODER_8BIT_TOP; |
| else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM) |
| ret = DECODER_8BIT_BOTTOM; |
| else |
| ret = DECODER_8BIT_NORMAL; |
| } |
| } |
| return ret; |
| } |
| |
| static int get_input_format(struct vframe_s *vf) |
| { |
| int format = GE2D_FORMAT_M24_YUV420; |
| enum ppmgr_source_type soure_type; |
| |
| soure_type = (enum ppmgr_source_type)get_source_type(vf); |
| switch (soure_type) { |
| case DECODER_8BIT_NORMAL: |
| if (vf->type & VIDTYPE_VIU_422) |
| format = GE2D_FORMAT_S16_YUV422; |
| else if (vf->type & VIDTYPE_VIU_NV21) |
| format = GE2D_FORMAT_M24_NV21; |
| else if (vf->type & VIDTYPE_VIU_444) |
| format = GE2D_FORMAT_S24_YUV444; |
| else |
| format = GE2D_FORMAT_M24_YUV420; |
| break; |
| case DECODER_8BIT_BOTTOM: |
| if (vf->type & VIDTYPE_VIU_422) |
| format = GE2D_FORMAT_S16_YUV422 |
| | (GE2D_FORMAT_S16_YUV422B & (3 << 3)); |
| else if (vf->type & VIDTYPE_VIU_NV21) |
| format = GE2D_FORMAT_M24_NV21 |
| | (GE2D_FORMAT_M24_NV21B & (3 << 3)); |
| else if (vf->type & VIDTYPE_VIU_444) |
| format = GE2D_FORMAT_S24_YUV444 |
| | (GE2D_FORMAT_S24_YUV444B & (3 << 3)); |
| else |
| format = GE2D_FORMAT_M24_YUV420 |
| | (GE2D_FMT_M24_YUV420B & (3 << 3)); |
| break; |
| case DECODER_8BIT_TOP: |
| if (vf->type & VIDTYPE_VIU_422) |
| format = GE2D_FORMAT_S16_YUV422 |
| | (GE2D_FORMAT_S16_YUV422T & (3 << 3)); |
| else if (vf->type & VIDTYPE_VIU_NV21) |
| format = GE2D_FORMAT_M24_NV21 |
| | (GE2D_FORMAT_M24_NV21T & (3 << 3)); |
| else if (vf->type & VIDTYPE_VIU_444) |
| format = GE2D_FORMAT_S24_YUV444 |
| | (GE2D_FORMAT_S24_YUV444T & (3 << 3)); |
| else |
| format = GE2D_FORMAT_M24_YUV420 |
| | (GE2D_FMT_M24_YUV420T & (3 << 3)); |
| break; |
| case DECODER_10BIT_NORMAL: |
| if (vf->type & VIDTYPE_VIU_422) { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| format = GE2D_FORMAT_S16_10BIT_YUV422; |
| else |
| format = GE2D_FORMAT_S16_12BIT_YUV422; |
| } |
| break; |
| case DECODER_10BIT_BOTTOM: |
| if (vf->type & VIDTYPE_VIU_422) { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| format = GE2D_FORMAT_S16_10BIT_YUV422 |
| | (GE2D_FORMAT_S16_10BIT_YUV422B |
| & (3 << 3)); |
| else |
| format = GE2D_FORMAT_S16_12BIT_YUV422 |
| | (GE2D_FORMAT_S16_12BIT_YUV422B |
| & (3 << 3)); |
| } |
| break; |
| case DECODER_10BIT_TOP: |
| if (vf->type & VIDTYPE_VIU_422) { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| format = GE2D_FORMAT_S16_10BIT_YUV422 |
| | (GE2D_FORMAT_S16_10BIT_YUV422T |
| & (3 << 3)); |
| else |
| format = GE2D_FORMAT_S16_12BIT_YUV422 |
| | (GE2D_FORMAT_S16_12BIT_YUV422T |
| & (3 << 3)); |
| } |
| break; |
| case VDIN_8BIT_NORMAL: |
| if (vf->type & VIDTYPE_VIU_422) { |
| format = GE2D_FORMAT_S16_YUV422; |
| } else if (vf->type & VIDTYPE_VIU_NV21) { |
| format = GE2D_FORMAT_M24_NV21; |
| } else if (vf->type & VIDTYPE_VIU_444) { |
| format = GE2D_FORMAT_S24_YUV444; |
| } else if (vf->type & VIDTYPE_RGB_444) { |
| format = GE2D_FORMAT_S24_RGB; |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| ; |
| else |
| format &= (~GE2D_LITTLE_ENDIAN); |
| } else { |
| format = GE2D_FORMAT_M24_YUV420; |
| } |
| break; |
| case VDIN_10BIT_NORMAL: |
| if (vf->type & VIDTYPE_VIU_422) { |
| if (vf->bitdepth & FULL_PACK_422_MODE) |
| format = GE2D_FORMAT_S16_10BIT_YUV422; |
| else |
| format = GE2D_FORMAT_S16_12BIT_YUV422; |
| } else if (vf->type & VIDTYPE_VIU_444) { |
| format = GE2D_FORMAT_S24_10BIT_YUV444; |
| } else if (vf->type & VIDTYPE_RGB_444) { |
| format = GE2D_FORMAT_S24_10BIT_RGB888; |
| if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR) |
| format |= GE2D_LITTLE_ENDIAN; |
| } |
| break; |
| default: |
| format = GE2D_FORMAT_M24_YUV420; |
| } |
| |
| return format; |
| } |
| |
| /* extern int get_property_change(void); */ |
| /* extern void set_property_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(&ppmgr_device.ppmgr_sem); |
| } |
| if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) { |
| if (task_running) { |
| #ifdef CONFIG_AMLOGIC_MEDIA_FRAME_SYNC |
| if (timestamp_pcrscr_enable_state()) |
| return 0; |
| #endif |
| if (get_property_change()) { |
| /*printk("--ppmgr: get angle changed msg.\n");*/ |
| set_property_change(0); |
| still_picture_notify = 1; |
| up(&ppmgr_device.ppmgr_sem); |
| } else { |
| up(&ppmgr_device.ppmgr_sem); |
| } |
| } |
| } |
| 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, }; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| static struct vframe_provider_s ppmgr_vf_prov; |
| #endif |
| /************************************************ |
| * |
| * 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}; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| static struct vframe_receiver_s ppmgr_vf_recv; |
| #endif |
| 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(&ppmgr_device.ppmgr_sem); |
| break; |
| case VFRAME_EVENT_PROVIDER_QUREY_STATE: |
| ppmgr_vf_states(&states, NULL); |
| if (states.buf_avail_num > 0) |
| return RECEIVER_ACTIVE; |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| if (vf_notify_receiver(PROVIDER_NAME, |
| VFRAME_EVENT_PROVIDER_QUREY_STATE, |
| NULL) == RECEIVER_ACTIVE) |
| return RECEIVER_ACTIVE; |
| #endif |
| return RECEIVER_INACTIVE; |
| case VFRAME_EVENT_PROVIDER_START: |
| #ifdef DDD |
| PPMGRVPP_WARN("register now\n"); |
| #endif |
| up(&ppmgr_device.ppmgr_sem); |
| vf_ppmgr_reg_provider(); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_notify_receiver(PROVIDER_NAME, |
| VFRAME_EVENT_PROVIDER_START, |
| NULL); |
| #endif |
| 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); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_notify_receiver(PROVIDER_NAME, |
| VFRAME_EVENT_PROVIDER_RESET, |
| NULL); |
| #endif |
| break; |
| case VFRAME_EVENT_PROVIDER_FR_HINT: |
| case VFRAME_EVENT_PROVIDER_FR_END_HINT: |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_notify_receiver(PROVIDER_NAME, type, data); |
| #endif |
| break; |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| void vf_local_init(void) |
| { |
| int i; |
| |
| set_property_change(0); |
| still_picture_notify = 0; |
| vfq_init(&q_free, VF_POOL_SIZE + 1, &vfp_pool_free[0]); |
| vfq_init(&q_ready, VF_POOL_SIZE + 1, &vfp_pool_ready[0]); |
| ppmgr_device.get_count = 0; |
| ppmgr_device.put_count = 0; |
| ppmgr_device.get_dec_count = 0; |
| ppmgr_device.put_dec_count = 0; |
| need_data_notify = true; |
| pr_info("ppmgr local_init\n"); |
| 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 = -1; /* ppmgr_canvas_tab[i]; */ |
| buf_status[i].dirty = 1; |
| } |
| //up(&ppmgr_device.ppmgr_sem); |
| } |
| |
| static void local_canvas_uninit(void) |
| { |
| int i; |
| |
| #ifdef CANVAS_RESERVED |
| for (i = 0; i < 3; i++) |
| ppmgr_src_canvas[i] = -1; |
| for (i = 0; i < 2; i++) |
| ppmgr_dst_canvas[i] = -1; |
| ass_index = -1; |
| #else |
| for (i = 0; i < 3; i++) { |
| if (ppmgr_src_canvas[i] >= 0) |
| canvas_pool_map_free_canvas(ppmgr_src_canvas[i]); |
| ppmgr_src_canvas[i] = -1; |
| } |
| |
| for (i = 0; i < 2; i++) { |
| if (ppmgr_dst_canvas[i] >= 0) |
| canvas_pool_map_free_canvas(ppmgr_dst_canvas[i]); |
| ppmgr_dst_canvas[i] = -1; |
| } |
| |
| if (ass_index >= 0) |
| canvas_pool_map_free_canvas(ass_index); |
| ass_index = -1; |
| #endif |
| local_canvas_status = 0; |
| } |
| |
| static int local_canvas_init(void) |
| { |
| int i; |
| bool alloc_fail = false; |
| |
| if (local_canvas_status) |
| return local_canvas_status; |
| |
| #ifdef CANVAS_RESERVED |
| for (i = 0; i < 3; i++) |
| ppmgr_src_canvas[i] = PPMGR_CANVAS_INDEX + i; |
| for (i = 0; i < 2; i++) |
| ppmgr_src_canvas[i] = PPMGR_CANVAS_INDEX + i + 3; |
| ass_index = PPMGR_CANVAS_INDEX + 5; |
| #else |
| for (i = 0; i < 3; i++) { |
| if (ppmgr_src_canvas[i] < 0) |
| ppmgr_src_canvas[i] = |
| canvas_pool_map_alloc_canvas("ppmgr_src"); |
| |
| if (ppmgr_src_canvas[i] < 0) { |
| PPMGRVPP_INFO("%s ppmgr_src_canvas[%d] alloc failed\n", |
| __func__, i); |
| alloc_fail = true; |
| break; |
| } |
| } |
| |
| for (i = 0; i < 2; i++) { |
| if (ppmgr_dst_canvas[i] < 0) |
| ppmgr_dst_canvas[i] = |
| canvas_pool_map_alloc_canvas("ppmgr_dst"); |
| |
| if (ppmgr_dst_canvas[i] < 0) { |
| PPMGRVPP_INFO("%s ppmgr_dst_canvas[%d] alloc failed\n", |
| __func__, i); |
| alloc_fail = true; |
| break; |
| } |
| } |
| |
| if (ass_index < 0) |
| ass_index = canvas_pool_map_alloc_canvas("ppmgr_temp"); |
| |
| if (ass_index < 0) { |
| PPMGRVPP_INFO("%s ass_index alloc failed\n", __func__); |
| alloc_fail = true; |
| } |
| #endif |
| if (alloc_fail) |
| local_canvas_uninit(); |
| else |
| local_canvas_status = 1; |
| return local_canvas_status; |
| } |
| |
| const struct vframe_receiver_op_s *vf_ppmgr_reg_provider(void) |
| { |
| const struct vframe_receiver_op_s *r = NULL; |
| |
| ppmgr_device.is_used = true; |
| |
| if (ppmgr_device.debug_first_frame == 1) { |
| dumpfirstframe = 1; |
| count_scr = 0; |
| count_dst = 0; |
| PPMGRVPP_INFO("need dump first frame!\n"); |
| } |
| |
| mutex_lock(&ppmgr_mutex); |
| |
| vf_local_init(); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_reg_provider(&ppmgr_vf_prov); |
| #endif |
| 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); |
| |
| #ifdef PPMGR_TB_DETECT |
| tb_buffer_uninit(); |
| #endif |
| ppmgr_buffer_uninit(); |
| |
| ppmgr_device.started = 0; |
| |
| mutex_unlock(&ppmgr_mutex); |
| |
| if (is_decontour_supported()) |
| decontour_uninit(); |
| ppmgr_device.is_used = false; |
| } |
| |
| /*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; |
| up(&ppmgr_device.ppmgr_sem); |
| |
| last_reset_time = current_reset_time; |
| } |
| } |
| |
| void vf_ppmgr_init_receiver(void) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_receiver_init(&ppmgr_vf_recv, RECEIVER_NAME, |
| &ppmgr_vf_receiver, NULL); |
| #endif |
| } |
| |
| void vf_ppmgr_reg_receiver(void) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_reg_receiver(&ppmgr_vf_recv); |
| #endif |
| } |
| |
| void vf_ppmgr_init_provider(void) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_provider_init(&ppmgr_vf_prov, PROVIDER_NAME, |
| &ppmgr_vf_provider, NULL); |
| #endif |
| } |
| |
| static inline struct vframe_s *ppmgr_vf_peek_dec(void) |
| { |
| struct vframe_s *vf = NULL; |
| #ifdef DDD |
| 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 |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf = vf_peek(RECEIVER_NAME); |
| #endif |
| return vf; |
| #endif |
| } |
| |
| static inline struct vframe_s *ppmgr_vf_get_dec(void) |
| { |
| struct vframe_s *vf = NULL; |
| #ifdef DDD |
| 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 |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf = vf_get(RECEIVER_NAME); |
| #endif |
| if (vf) { |
| ppmgr_device.get_dec_count++; |
| vf->decontour_pre = NULL; |
| } |
| return vf; |
| #endif |
| } |
| |
| void ppmgr_vf_put_dec(struct vframe_s *vf) |
| { |
| struct dcntr_mem_s *dcntr_mem; |
| #ifdef DDD |
| 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 |
| if (vf->decontour_pre) { |
| dcntr_mem = (struct dcntr_mem_s *)vf->decontour_pre; |
| dcntr_mem->free = true; |
| vf->decontour_pre = NULL; |
| } |
| vf_put(vf, RECEIVER_NAME); |
| ppmgr_device.put_dec_count++; |
| |
| #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 input_height = 0, input_width = 0; |
| int scale_down_value = 1; |
| int interlace_mode = 0; |
| |
| disp_w = ppmgr_device.disp_width / scale_down_value; |
| disp_h = ppmgr_device.disp_height / scale_down_value; |
| interlace_mode = vf->type & VIDTYPE_TYPEMASK; |
| input_width = vf->width; |
| if (interlace_mode) |
| input_height = vf->height * 2; |
| else |
| input_height = vf->height; |
| if (ppmgr_device.ppmgr_debug & 1) { |
| PPMGRVPP_INFO("disp_width: %d, disp_height: %d\n", |
| disp_w, disp_h); |
| PPMGRVPP_INFO("input_width: %d, input_height: %d\n", |
| input_width, input_height); |
| } |
| if (angle & 1) { |
| int ar = (vf->ratio_control |
| >> DISP_RATIO_ASPECT_RATIO_BIT) & 0x3ff; |
| if (ppmgr_device.ppmgr_debug == 2) |
| ar = 0; |
| |
| if (input_width > input_height) { |
| h = min_t(int, input_width, disp_h); |
| |
| if (ar == 0 || ar == 0x3ff) |
| w = input_height * h / input_width; |
| else |
| w = (ar * h) >> 8; |
| |
| if (w > disp_w) { |
| h = (h * disp_w) / w; |
| w = disp_w; |
| } |
| } else { |
| w = min_t(int, input_height, disp_w); |
| |
| if (ar == 0 || ar == 0x3ff) |
| h = input_width * w / input_height; |
| else |
| h = (w << 8) / ar; |
| |
| if (h > disp_h) { |
| w = (w * disp_h) / h; |
| h = disp_h; |
| } |
| } |
| if (ppmgr_device.ppmgr_debug & 1) |
| PPMGRVPP_INFO("width: %d, height: %d, ar: %d\n", |
| w, h, ar); |
| 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 (input_width < disp_w && input_height < disp_h) { |
| w = input_width; |
| h = input_height; |
| } else { |
| if ((input_width * disp_h) > (disp_w * input_height)) { |
| w = disp_w; |
| h = disp_w * input_height / input_width; |
| } else { |
| h = disp_h; |
| w = disp_h * input_width / input_height; |
| } |
| } |
| |
| new_vf->ratio_control = vf->ratio_control; |
| } |
| |
| if (h > 1280) { |
| w = w * 1280 / h; |
| h = 1280; |
| } |
| |
| new_vf->width = (w + 0x1f) & ~0x1f; |
| new_vf->height = h; |
| } |
| |
| #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; |
| u32 canvas_id; |
| 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) || !context) |
| 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(ppmgr_dst_canvas[0], |
| 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; |
| |
| if (vf->canvas0Addr == (u32)-1) { |
| canvas_config_config(ppmgr_src_canvas[0] & 0xff, |
| &vf->canvas0_config[0]); |
| ge2d_config->src_planes[0].addr = |
| vf->canvas0_config[0].phy_addr; |
| ge2d_config->src_planes[0].w = vf->canvas0_config[0].width; |
| ge2d_config->src_planes[0].h = vf->canvas0_config[0].height; |
| |
| if (vf->plane_num > 1) { |
| canvas_config_config(ppmgr_src_canvas[1] & 0xff, |
| &vf->canvas0_config[1]); |
| ge2d_config->src_planes[1].addr = |
| vf->canvas0_config[1].phy_addr; |
| ge2d_config->src_planes[1].w = |
| vf->canvas0_config[1].width; |
| ge2d_config->src_planes[1].h = |
| vf->canvas0_config[1].height; |
| } |
| if (vf->plane_num > 2) { |
| canvas_config_config(ppmgr_src_canvas[2] & 0xff, |
| &vf->canvas0_config[2]); |
| ge2d_config->src_planes[2].addr = |
| vf->canvas0_config[2].phy_addr; |
| ge2d_config->src_planes[2].w = |
| vf->canvas0_config[2].width; |
| ge2d_config->src_planes[2].h = |
| vf->canvas0_config[2].height; |
| } |
| canvas_id = |
| (ppmgr_src_canvas[0] & 0xff) |
| | ((ppmgr_src_canvas[1] & 0xff) << 8) |
| | ((ppmgr_src_canvas[2] & 0xff) << 16); |
| ge2d_config->src_para.canvas_index = canvas_id; |
| |
| } 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; |
| ge2d_config->src_para.canvas_index = vf->canvas0Addr; |
| } |
| canvas_read(ppmgr_dst_canvas[0] & 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; |
| 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 = ppmgr_dst_canvas[0]; |
| |
| 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; |
| |
| 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); |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| codec_mm_dma_flush((void *)detect_buf[tb_buff_wptr].vaddr, |
| TB_DETECT_W * TB_DETECT_H, |
| DMA_FROM_DEVICE); |
| #endif |
| context->config.h_scale_coef_type = |
| h_scale_coef_type; |
| context->config.v_scale_coef_type = |
| v_scale_coef_type; |
| return 1; |
| } |
| #endif |
| |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| static int copy_phybuf_to_file(ulong phys, u32 size, |
| struct file *fp, loff_t pos) |
| { |
| u32 span = SZ_1M; |
| u8 *p; |
| int remain_size = 0; |
| ssize_t ret; |
| |
| remain_size = size; |
| while (remain_size > 0) { |
| if (remain_size < span) |
| span = remain_size; |
| p = codec_mm_vmap(phys, PAGE_ALIGN(span)); |
| if (!p) { |
| PPMGRVPP_INFO("vmap failed\n"); |
| return -1; |
| } |
| codec_mm_dma_flush(p, span, DMA_FROM_DEVICE); |
| ret = vfs_write(fp, (char *)p, span, &pos); |
| if (ret <= 0) |
| PPMGRVPP_INFO("vfs write failed!\n"); |
| phys += span; |
| codec_mm_unmap_phyaddr(p); |
| remain_size -= span; |
| |
| PPMGRVPP_INFO("pos: %lld, phys: %lx, remain_size: %d\n", |
| pos, phys, remain_size); |
| } |
| return 0; |
| } |
| |
| /* |
| * 1: yuv |
| * 0: afbc |
| */ |
| static void notify_data(u32 format) |
| { |
| char *provider_name = vf_get_provider_name(RECEIVER_NAME); |
| |
| while (provider_name) { |
| if (!vf_get_provider_name(provider_name)) |
| break; |
| provider_name = |
| vf_get_provider_name(provider_name); |
| } |
| if (provider_name) |
| vf_notify_provider_by_name(provider_name, |
| VFRAME_EVENT_RECEIVER_NEED_NO_COMP, |
| (void *)&format); |
| if (ppmgr_device.ppmgr_debug & 1) |
| PPMGRVPP_INFO("%s provider_name: %s, data: %d\n", |
| __func__, provider_name, format); |
| } |
| |
| #endif |
| |
| static void process_vf_rotate(struct vframe_s *vf, |
| struct ge2d_context_s *context, |
| struct config_para_ex_s *ge2d_config) |
| { |
| struct vframe_s *new_vf; |
| struct ppframe_s *pp_vf; |
| u32 canvas_id; |
| u32 dst_canvas_id; |
| u32 buf_start, buf_start_ref, buf_end; |
| u32 buf_size; |
| int ret = 0; |
| unsigned int cur_angle = 0; |
| int interlace_mode; |
| struct file *filp_scr = NULL; |
| struct file *filp_dst = NULL; |
| char source_path[64]; |
| char dst_path[64]; |
| int count; |
| int result = 0; |
| mm_segment_t old_fs; |
| |
| if (ppmgr_device.debug_ppmgr_flag) |
| pr_info("ppmgr:rotate\n"); |
| |
| if (!context) { |
| pr_info("ppmgr:rotate but no ge2d context\n"); |
| return; |
| } |
| |
| new_vf = vfq_pop(&q_free); |
| |
| if (unlikely(!new_vf || !vf)) { |
| pr_info("ppmgr:rotate null, %p, %p\n", new_vf, vf); |
| return; |
| } |
| |
| memset(new_vf, 0, sizeof(struct vframe_s)); |
| |
| interlace_mode = vf->type & VIDTYPE_TYPEMASK; |
| |
| pp_vf = to_ppframe(new_vf); |
| pp_vf->angle = 0; |
| cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4; |
| pp_vf->dec_frame = (ppmgr_device.bypass || |
| (cur_angle == 0 && |
| ppmgr_device.mirror_flag == 0)) ? vf : NULL; |
| |
| if (ppmgr_device.ppmgr_debug & 4) |
| need_data_notify = true; |
| |
| if (vf->type & VIDTYPE_MVC) |
| pp_vf->dec_frame = vf; |
| |
| if (vf->type & VIDTYPE_PIC) |
| pp_vf->dec_frame = vf; |
| |
| /* canvas invalid, force bypass */ |
| if (!local_canvas_status) |
| pp_vf->dec_frame = vf; |
| |
| if (vf->type & VIDTYPE_COMPRESS) { |
| if (cur_angle != 0 && (vf->type & VIDTYPE_NO_DW)) { |
| vf->type &= ~VIDTYPE_SUPPORT_COMPRESS; |
| vf->type_original &= ~VIDTYPE_SUPPORT_COMPRESS; |
| if (need_data_notify) { |
| need_data_notify = false; |
| notify_data(1); |
| PPMGRVPP_INFO("notify need yuv data\n"); |
| } |
| } |
| if (vf->canvas0Addr == (u32)-1 && vf->plane_num == 0) { |
| pp_vf->dec_frame = vf; |
| if (ppmgr_device.ppmgr_debug & 1) |
| PPMGRVPP_INFO("vframe is compress!\n"); |
| } |
| if (dumpfirstframe == 1) |
| dumpfirstframe = 2; |
| } |
| |
| if (pp_vf->dec_frame) { |
| if (is_decontour_supported() && local_canvas_status) { |
| ret = decontour_pre_process(vf); |
| if (ret != 0) |
| dc_print("pre process fail ret=%d\n", ret); |
| } |
| /* bypass mode */ |
| *new_vf = *vf; |
| vfq_push(&q_ready, new_vf); |
| return; |
| } |
| |
| if (!(ppmgr_device.ppmgr_debug & 8)) { |
| if (vf->width > vf->height) { |
| if (cur_angle % 2) { |
| ppmgr_device.disp_width = MAX_HEIGHT; |
| ppmgr_device.disp_height = MAX_WIDTH; |
| } else { |
| ppmgr_device.disp_width = MAX_WIDTH; |
| ppmgr_device.disp_height = MAX_HEIGHT; |
| } |
| } else { |
| if (cur_angle % 2) { |
| ppmgr_device.disp_width = MAX_WIDTH; |
| ppmgr_device.disp_height = MAX_HEIGHT; |
| } else { |
| ppmgr_device.disp_width = MAX_HEIGHT; |
| ppmgr_device.disp_height = MAX_WIDTH; |
| } |
| } |
| } |
| |
| ret = ppmgr_buffer_init(vf->mem_sec); |
| |
| if (ret < 0) { |
| pp_vf->dec_frame = vf; |
| *new_vf = *vf; |
| vfq_push(&q_ready, new_vf); |
| return; |
| } |
| if (vf->type & VIDTYPE_V4L_EOS) { |
| new_vf->type |= VIDTYPE_V4L_EOS; |
| goto rotate_done; |
| } |
| #ifdef INTERLACE_DROP_MODE |
| if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM) { |
| 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->duration_pulldown = vf->duration_pulldown; |
| new_vf->mem_sec = vf->mem_sec; |
| new_vf->pts = vf->pts; |
| new_vf->pts_us64 = vf->pts_us64; |
| new_vf->bitdepth = BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; |
| new_vf->signal_type = vf->signal_type; |
| new_vf->omx_index = vf->omx_index; |
| new_vf->type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE |
| | VIDTYPE_VIU_FIELD; |
| new_vf->canvas0Addr = -1; |
| new_vf->canvas1Addr = -1; |
| new_vf->plane_num = 1; |
| dst_canvas_id = ppmgr_dst_canvas[0]; |
| new_vf->orientation = vf->orientation; |
| new_vf->flag = vf->flag; |
| |
| if (interlace_mode == VIDTYPE_INTERLACE_TOP || |
| interlace_mode == VIDTYPE_INTERLACE_BOTTOM) |
| vf->height >>= 1; |
| |
| vf_rotate_adjust(vf, new_vf, cur_angle); |
| |
| get_ppmgr_buf_info(&buf_start_ref, &buf_size); |
| buf_start = buf_start_ref; |
| buf_start += pp_vf->index * ppmgr_device.disp_width |
| * ppmgr_device.disp_height * 3; |
| buf_end = buf_start; |
| buf_end += ppmgr_device.disp_width * ppmgr_device.disp_height * 3; |
| if (buf_end > buf_start_ref + buf_size) { |
| PPMGRVPP_INFO |
| ("%s dst overflow, pool:%x %x, buf:%x %x, id:%d\n", |
| __func__, |
| buf_start_ref, buf_size, |
| buf_start, buf_end - buf_start, |
| pp_vf->index); |
| buf_start = buf_start_ref; |
| } |
| new_vf->canvas0_config[0].phy_addr = buf_start; |
| new_vf->canvas0_config[0].width = new_vf->width * 3; |
| new_vf->canvas0_config[0].height = new_vf->height; |
| new_vf->canvas0_config[0].block_mode = 0; |
| new_vf->canvas0_config[0].endian = 0; |
| |
| canvas_config(dst_canvas_id, |
| (ulong)buf_start, |
| new_vf->width * 3, |
| new_vf->height, |
| CANVAS_ADDR_NOWRAP, |
| CANVAS_BLKMODE_LINEAR); |
| |
| memset(ge2d_config, 0, sizeof(struct config_para_ex_s)); |
| |
| if (pp_vf->index < VF_POOL_SIZE && |
| buf_status[pp_vf->index].dirty == 1) { |
| buf_status[pp_vf->index].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; |
| |
| 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 = dst_canvas_id; |
| 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 = dst_canvas_id; |
| 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)); |
| } |
| |
| /* 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; |
| |
| 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 (vf->canvas0Addr != (u32)-1) { |
| canvas_copy(vf->canvas0Addr & 0xff, |
| ppmgr_src_canvas[0]); |
| canvas_copy((vf->canvas0Addr >> 8) & 0xff, |
| ppmgr_src_canvas[1]); |
| canvas_copy((vf->canvas0Addr >> 16) & 0xff, |
| ppmgr_src_canvas[2]); |
| } else if (vf->plane_num > 0) { |
| canvas_config_config(ppmgr_src_canvas[0], |
| &vf->canvas0_config[0]); |
| if (vf->plane_num > 1) |
| canvas_config_config(ppmgr_src_canvas[1], |
| &vf->canvas0_config[1]); |
| if (vf->plane_num > 2) |
| canvas_config_config(ppmgr_src_canvas[2], |
| &vf->canvas0_config[2]); |
| } |
| canvas_id = ppmgr_src_canvas[0] |
| | (ppmgr_src_canvas[1] << 8) |
| | (ppmgr_src_canvas[2] << 16); |
| |
| ge2d_config->src_para.canvas_index = canvas_id; |
| if (ppmgr_color_format == 0) |
| ge2d_config->src_para.format = get_input_format(vf); |
| else |
| ge2d_config->src_para.format = ppmgr_color_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; |
| |
| ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID; |
| |
| ge2d_config->dst_para.canvas_index = dst_canvas_id; |
| 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; |
| stretchblt_noalpha(context, 0, 0, vf->width, vf->height, |
| 0, 0, new_vf->width, new_vf->height); |
| |
| if (strstr(ppmgr_device.dump_path, "scr") && dumpfirstframe == 2) { |
| old_fs = get_fs(); |
| set_fs(KERNEL_DS); |
| count = strlen(ppmgr_device.dump_path); |
| ppmgr_device.dump_path[count] = count_scr; |
| sprintf(source_path, "%s_scr", ppmgr_device.dump_path); |
| count_scr++; |
| filp_scr = filp_open(source_path, O_RDWR | O_CREAT, 0666); |
| if (IS_ERR(filp_scr)) { |
| PPMGRVPP_INFO("open %s failed\n", source_path); |
| } else { |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| result = copy_phybuf_to_file(vf->canvas0_config[0] |
| .phy_addr, |
| vf->canvas0_config[0] |
| .width |
| * vf->canvas0_config[0] |
| .height, |
| filp_scr, 0); |
| #endif |
| if (result < 0) |
| PPMGRVPP_INFO("write %s failed\n", |
| source_path); |
| PPMGRVPP_INFO("scr addr: %lx, width: %d, height: %d\n", |
| vf->canvas0_config[0].phy_addr, |
| vf->canvas0_config[0].width, |
| vf->canvas0_config[0].height); |
| PPMGRVPP_INFO("dump source type: %d\n", |
| get_input_format(vf)); |
| vfs_fsync(filp_scr, 0); |
| filp_close(filp_scr, NULL); |
| set_fs(old_fs); |
| } |
| } |
| rotate_done: |
| ppmgr_vf_put_dec(vf); |
| new_vf->source_type = VFRAME_SOURCE_TYPE_PPMGR; |
| if (dumpfirstframe != 2) |
| vfq_push(&q_ready, new_vf); |
| |
| if (strstr(ppmgr_device.dump_path, "dst") && dumpfirstframe == 2) { |
| old_fs = get_fs(); |
| set_fs(KERNEL_DS); |
| count = strlen(ppmgr_device.dump_path); |
| ppmgr_device.dump_path[count] = count_dst; |
| sprintf(dst_path, "%s_dst", ppmgr_device.dump_path); |
| count_dst++; |
| filp_dst = filp_open(dst_path, O_RDWR | O_CREAT, 0666); |
| if (IS_ERR(filp_dst)) { |
| PPMGRVPP_INFO("open %s failed\n", dst_path); |
| } else { |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| ulong phy_addr = new_vf->canvas0_config[0].phy_addr; |
| u32 copy_size = new_vf->canvas0_config[0].width * |
| new_vf->canvas0_config[0].height; |
| |
| result = copy_phybuf_to_file |
| (phy_addr, copy_size, filp_dst, 0); |
| PPMGRVPP_INFO("dst addr: %lx, width: %d, height: %d\n", |
| phy_addr, new_vf->canvas0_config[0].width, |
| new_vf->canvas0_config[0].height); |
| PPMGRVPP_INFO("dump dst type: %d\n", |
| get_input_format(new_vf)); |
| #endif |
| if (result < 0) |
| PPMGRVPP_INFO("write %s failed\n", dst_path); |
| vfs_fsync(filp_dst, 0); |
| filp_close(filp_dst, NULL); |
| set_fs(old_fs); |
| } |
| if (count_dst >= ppmgr_device.ppmgr_debug) |
| dumpfirstframe = 0; |
| } |
| |
| #ifdef DDD |
| PPMGRVPP_WARN("rotate avail=%d, free=%d\n", |
| vfq_level(&q_ready), vfq_level(&q_free)); |
| #endif |
| } |
| |
| static void process_vf_change(struct vframe_s *vf, |
| struct ge2d_context_s *context, |
| struct config_para_ex_s *ge2d_config) |
| { |
| static struct vframe_s temp_vf; |
| struct ppframe_s *pp_vf = to_ppframe(vf); |
| struct canvas_s cs0, cs1, cs2, cd; |
| u32 canvas_id; |
| u32 dst_canvas_id; |
| int interlace_mode; |
| unsigned int temp_angle = 0; |
| unsigned int cur_angle = 0; |
| int ret = 0; |
| u32 buf_start, buf_start_ref, buf_end; |
| u32 buf_size; |
| |
| if (!context || !vf || !local_canvas_status) |
| return; |
| |
| cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4; |
| if (cur_angle == 0 || ppmgr_device.bypass) |
| return; |
| |
| ret = ppmgr_buffer_init(vf->mem_sec); |
| |
| if (ret < 0) |
| return; |
| if (vf->type & VIDTYPE_V4L_EOS) |
| goto change_done; |
| 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.bitdepth = BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8; |
| temp_vf.signal_type = vf->signal_type; |
| temp_vf.omx_index = vf->omx_index; |
| temp_vf.type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE |
| | VIDTYPE_VIU_FIELD; |
| temp_vf.canvas0Addr = ass_index; |
| temp_vf.canvas1Addr = ass_index; |
| 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); |
| |
| get_ppmgr_buf_info(&buf_start_ref, &buf_size); |
| buf_start = buf_start_ref; |
| buf_start += VF_POOL_SIZE * ppmgr_device.disp_width |
| * ppmgr_device.disp_height * 3; |
| buf_end = buf_start; |
| buf_end += ppmgr_device.disp_width * ppmgr_device.disp_height * 3; |
| if (buf_end > buf_start_ref + buf_size) { |
| PPMGRVPP_INFO("%s tmp overflow, pool:%x %x, buf:%x %x\n", |
| __func__, |
| buf_start_ref, buf_size, |
| buf_start, buf_end - buf_start); |
| return; |
| } |
| |
| canvas_config(ass_index, |
| (ulong)buf_start, |
| temp_vf.width * 3, |
| temp_vf.height, |
| CANVAS_ADDR_NOWRAP, |
| CANVAS_BLKMODE_LINEAR); |
| |
| interlace_mode = vf->type & VIDTYPE_TYPEMASK; |
| |
| if (interlace_mode == VIDTYPE_INTERLACE_TOP || |
| interlace_mode == VIDTYPE_INTERLACE_BOTTOM) |
| vf->height >>= 1; |
| |
| if (vf->canvas0Addr != (u32)-1) { |
| canvas_copy(vf->canvas0Addr & 0xff, |
| ppmgr_src_canvas[0]); |
| canvas_copy((vf->canvas0Addr >> 8) & 0xff, |
| ppmgr_src_canvas[1]); |
| canvas_copy((vf->canvas0Addr >> 16) & 0xff, |
| ppmgr_src_canvas[2]); |
| } else if (vf->plane_num > 0) { |
| canvas_config_config(ppmgr_src_canvas[0], |
| &vf->canvas0_config[0]); |
| if (vf->plane_num > 1) |
| canvas_config_config(ppmgr_src_canvas[1], |
| &vf->canvas0_config[1]); |
| if (vf->plane_num > 2) |
| canvas_config_config(ppmgr_src_canvas[2], |
| &vf->canvas0_config[2]); |
| } |
| canvas_id = ppmgr_src_canvas[0] |
| | (ppmgr_src_canvas[1] << 8) |
| | (ppmgr_src_canvas[2] << 16); |
| |
| 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) { |
| canvas_read(canvas_id & 0xff, &cs0); |
| canvas_read((canvas_id >> 8) & 0xff, &cs1); |
| canvas_read((canvas_id >> 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; |
| ge2d_config->src_para.format = get_input_format(vf); |
| } else { |
| canvas_read(canvas_id & 0xff, &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.format = get_input_format(vf); |
| } |
| |
| 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 = canvas_id; |
| 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 = 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, |
| vf->height, |
| 0, 0, temp_vf.width, |
| temp_vf.height); |
| |
| vf->type = VIDTYPE_VIU_444 |
| | VIDTYPE_VIU_SINGLE_PLANE |
| | VIDTYPE_VIU_FIELD; |
| |
| vf->canvas0Addr = -1; |
| vf->canvas1Addr = -1; |
| vf->plane_num = 1; |
| dst_canvas_id = ppmgr_dst_canvas[0]; |
| |
| get_ppmgr_buf_info(&buf_start_ref, &buf_size); |
| buf_start = buf_start_ref; |
| buf_start += pp_vf->index * ppmgr_device.disp_width |
| * ppmgr_device.disp_height * 3; |
| buf_end = buf_start; |
| buf_end += ppmgr_device.disp_width * ppmgr_device.disp_height * 3; |
| if (buf_end > buf_start_ref + buf_size) { |
| PPMGRVPP_INFO |
| ("%s dst overflow, pool:%x %x, buf:%x %x, id:%d\n", |
| __func__, |
| buf_start_ref, buf_size, |
| buf_start, buf_end - buf_start, |
| pp_vf->index); |
| buf_start = buf_start_ref; |
| } |
| vf->canvas0_config[0].phy_addr = buf_start; |
| vf->canvas0_config[0].width = temp_vf.width * 3; |
| vf->canvas0_config[0].height = temp_vf.height; |
| vf->canvas0_config[0].block_mode = 0; |
| vf->canvas0_config[0].endian = 0; |
| |
| canvas_config(dst_canvas_id, |
| (ulong)buf_start, |
| temp_vf.width * 3, |
| temp_vf.height, |
| CANVAS_ADDR_NOWRAP, |
| CANVAS_BLKMODE_LINEAR); |
| |
| 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(dst_canvas_id & 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 = dst_canvas_id; |
| 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 ;*/ |
| change_done: |
| if (pp_vf->dec_frame) { |
| ppmgr_vf_put_dec(pp_vf->dec_frame); |
| pp_vf->dec_frame = 0; |
| } |
| vf->ratio_control = 0; |
| } |
| |
| static struct task_struct *task; |
| |
| void ppmgr_vf_peek_dec_debug(void) |
| { |
| struct vframe_s *vf; |
| |
| vf = ppmgr_vf_peek_dec(); |
| PPMGRVPP_INFO("peek vf=%p\n", vf); |
| } |
| |
| static int ppmgr_task(void *data) |
| { |
| struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; |
| 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, ¶m); |
| allow_signal(SIGTERM); |
| |
| while (down_interruptible(&ppmgr_device.ppmgr_sem) == 0) { |
| struct vframe_s *vf = NULL; |
| |
| if (ppmgr_device.debug_ppmgr_flag) |
| PPMGRVPP_INFO("task_1, dec %p, free %d, avail %d\n", |
| ppmgr_vf_peek_dec(), |
| vfq_level(&q_free), |
| vfq_level(&q_ready)); |
| |
| if (kthread_should_stop() || ppmgr_quit_flag) { |
| PPMGRVPP_INFO("task: quit\n"); |
| break; |
| } |
| |
| local_canvas_init(); |
| |
| if (still_picture_notify) { |
| still_picture_notify = 0; |
| /* disableVideoLayer(); */ |
| #ifdef CONFIG_AMLOGIC_MEDIA_VIDEO |
| vf = get_cur_dispbuf(); |
| #endif |
| if (!is_valid_ppframe(to_ppframe(vf))) |
| continue; |
| if ((vf->type & VIDTYPE_COMPRESS) && |
| vf->plane_num < 1 && |
| vf->canvas0Addr == (u32)-1) { |
| continue; |
| } |
| process_vf_change(vf, context, &ge2d_config); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_notify_receiver(PROVIDER_NAME, |
| VFRAME_EVENT_PROVIDER_PROPERTY_CHANGED, |
| NULL); |
| #endif |
| 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(&ppmgr_device.ppmgr_sem); |
| continue; |
| } |
| |
| /* process when we have both input and output space */ |
| while (ppmgr_vf_peek_dec() && |
| !vfq_empty(&q_free) && (!ppmgr_blocking)) { |
| int ret = 0; |
| |
| vf = ppmgr_vf_get_dec(); |
| if (!vf) |
| break; |
| if (ppmgr_secure_debug) |
| vf->mem_sec = ppmgr_secure_mode; |
| if (vf && ppmgr_device.started) { |
| 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 ((vf->width * vf->height) |
| > (1920 * 1088) || vf->mem_sec == 1) { |
| /* greater than (1920 * 1088) or secure mode, |
| * do not detect |
| */ |
| goto SKIP_DETECT; |
| } |
| if (vf->type & VIDTYPE_V4L_EOS) |
| 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 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) |
| pr_info("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) |
| pr_info("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) |
| pr_info("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) |
| pr_info("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) && |
| atomic_read(&tb_run_flag) == 1) |
| 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 reset\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)) |
| pr_info("PPMGRVPP: info: tb detect flag: %d->%d, invert: %d->%d\n", |
| tb_last_flag, |
| tbf_flag, |
| old_invert, |
| cur_invert); |
| else if (tb_last_flag != tbf_flag && |
| (ppmgr_device.tb_detect |
| & 0xc)) |
| pr_info("PPMGRVPP: info: tb detect flag %d->%d, invert: %d\n", |
| tb_last_flag, |
| tbf_flag, |
| cur_invert); |
| tb_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) |
| pr_info("PPMGRVPP: info: tb detect skip case1\n"); |
| goto SKIP_DETECT; |
| } |
| if (tb_buff_wptr < tb_buffer_len && |
| atomic_read(&tb_run_flag) == 1) { |
| ret = process_vf_tb_detect(vf, context, |
| &ge2d_config |
| ); |
| } else { |
| if (ppmgr_device.tb_detect & 0xc) |
| pr_info("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(&ppmgr_device.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 |
| process_vf_rotate(vf, context, &ge2d_config); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_notify_receiver(PROVIDER_NAME, |
| VFRAME_EVENT_PROVIDER_VFRAME_READY, |
| NULL); |
| #endif |
| } |
| |
| if (ppmgr_blocking) { |
| /***recycle buffer to decoder***/ |
| vf_local_init(); |
| #ifdef CONFIG_AMLOGIC_MEDIA_VFM |
| vf_light_unreg_provider(&ppmgr_vf_prov); |
| #endif |
| PPMGRVPP_WARN("ppmgr rebuild light-unregister_1\n"); |
| vf_unreg_provider(&ppmgr_vf_prov); |
| omx_cur_session = 0xffffffff; |
| usleep_range(4000, 5000); |
| vf_reg_provider(&ppmgr_vf_prov); |
| vf_local_init(); |
| if (is_decontour_supported()) |
| decontour_buf_reset(); |
| ppmgr_blocking = false; |
| up(&ppmgr_device.ppmgr_sem); |
| PPMGRVPP_WARN("ppmgr rebuild light-unregister_2\n"); |
| PPMGRVPP_WARN("ppmgr, reset, free %d, avail %d\n", |
| vfq_level(&q_free), |
| vfq_level(&q_ready)); |
| } |
| if (ppmgr_device.debug_ppmgr_flag) |
| PPMGRVPP_WARN("ppmgr, dec %p, free %d, avail %d\n", |
| ppmgr_vf_peek_dec(), |
| vfq_level(&q_free), |
| vfq_level(&q_ready)); |
| |
| #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); |
| local_canvas_uninit(); |
| |
| 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.buffer_start) { |
| PPMGRVPP_INFO("cma free addr is %x , size is %x\n", |
| (unsigned int)ppmgr_device.buffer_start, |
| (unsigned int)ppmgr_device.buffer_size); |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| codec_mm_free_for_dma("ppmgr", ppmgr_device.buffer_start); |
| #endif |
| ppmgr_device.buffer_start = 0; |
| ppmgr_device.buffer_size = 0; |
| } |
| |
| ppmgr_buffer_status = 0; |
| return 0; |
| } |
| |
| int ppmgr_buffer_init(int secure_mode) |
| { |
| u32 canvas_width, canvas_height; |
| int mem_sec_flag; |
| int flags; |
| struct vinfo_s vinfo = {.width = 1280, .height = 720, }; |
| |
| mem_sec_flag = secure_mode == 1 ? CODEC_MM_FLAGS_TVP : |
| CODEC_MM_FLAGS_CMA_CLEAR; |
| /* int flags = CODEC_MM_FLAGS_DMA; */ |
| flags = CODEC_MM_FLAGS_DMA | mem_sec_flag; |
| |
| 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.buffer_start == 0) { |
| PPMGRVPP_INFO("reserved memory config fail,use CMA.\n"); |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| ppmgr_device.buffer_start = |
| codec_mm_alloc_for_dma("ppmgr", |
| MM_ALLOC_SIZE / PAGE_SIZE, |
| 0, flags); |
| ppmgr_device.buffer_size = MM_ALLOC_SIZE; |
| PPMGRVPP_INFO("cma memory is %x , size is %x\n", |
| (unsigned int)ppmgr_device.buffer_start, |
| (unsigned int)ppmgr_device.buffer_size); |
| #endif |
| if (ppmgr_device.buffer_start == 0) { |
| ppmgr_buffer_status = 2; |
| PPMGRVPP_ERR("cma memory config fail\n"); |
| return -1; |
| } |
| } |
| |
| ppmgr_buffer_status = 1; |
| ppmgr_device.vinfo = get_current_vinfo(); |
| if (IS_ERR_OR_NULL(ppmgr_device.vinfo)) { |
| pr_info("PPMGRVPP: info: 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; |
| } |
| ppmgr_device.canvas_width = canvas_width; |
| ppmgr_device.canvas_height = canvas_height; |
| |
| ppmgr_blocking = false; |
| ppmgr_inited = true; |
| //up(&ppmgr_device.ppmgr_sem); |
| return 0; |
| } |
| |
| int start_ppmgr_task(void) |
| { |
| /* 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_buffer_status = 0; |
| ppmgr_quit_flag = false; |
| task = kthread_run(ppmgr_task, 0, "ppmgr"); |
| } |
| if (!IS_ERR_OR_NULL(task)) |
| task_running = 1; |
| else |
| task = NULL; |
| return 0; |
| } |
| |
| void stop_ppmgr_task(void) |
| { |
| #ifdef PPMGR_TB_DETECT |
| stop_tb_task(); |
| #endif |
| if (!IS_ERR_OR_NULL(task)) { |
| /* send_sig(SIGTERM, task, 1); */ |
| ppmgr_quit_flag = true; |
| up(&ppmgr_device.ppmgr_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) |
| { |
| ulong i; |
| //int flags = CODEC_MM_FLAGS_DMA_CPU | CODEC_MM_FLAGS_CMA_CLEAR; |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| int flags = 0; |
| #endif |
| |
| if (tb_buffer_status) |
| return tb_buffer_status; |
| |
| if (ppmgr_src_canvas[0] < 0 || ppmgr_src_canvas[1] < 0 || |
| ppmgr_src_canvas[2] < 0 || |
| ppmgr_dst_canvas[0] < 0 || ppmgr_dst_canvas[1] < 0) { |
| PPMGRVPP_INFO("%s canvas check fail\n", __func__); |
| 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); |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| 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); |
| #endif |
| 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; |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| 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(%ld)", i); |
| PPMGRVPP_INFO(" paddr: %lx, vaddr: %lx\n", |
| detect_buf[i].paddr, |
| detect_buf[i].vaddr); |
| } |
| #endif |
| } |
| } |
| tb_buffer_status = 1; |
| return 1; |
| } |
| |
| static int tb_buffer_uninit(void) |
| { |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| int i; |
| #endif |
| |
| if (tb_buffer_start) { |
| #ifdef CONFIG_AMLOGIC_MEDIA_CODEC_MM |
| 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); |
| #endif |
| tb_buffer_start = 0; |
| tb_buffer_size = 0; |
| } |
| tb_buffer_status = 0; |
| return 0; |
| } |
| |
| static void tb_detect_init(void) |
| { |
| 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); |
| atomic_set(&tb_run_flag, 1); |
| tb_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 *tb_reg = NULL; |
| ulong y5fld[5]; |
| int is_top; |
| int inited = 0; |
| int i; |
| int inter_flag; |
| 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, ¶m); |
| |
| inter_flag = 0; |
| tb_reg = kmalloc(sizeof(*tb_reg), GFP_KERNEL); |
| if (!tb_reg) { |
| PPMGRVPP_INFO("tb_reg malloc fail\n"); |
| return 0; |
| } |
| memset(tb_reg, 0, sizeof(struct tbff_stats)); |
| |
| if (gfunc) |
| gfunc->stats_init(tb_reg, TB_DETECT_H, TB_DETECT_W); |
| allow_signal(SIGTERM); |
| while (down_interruptible(&ppmgr_device.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) { |
| if (IS_ERR_OR_NULL(tb_reg)) { |
| kfree(tb_reg); |
| PPMGRVPP_INFO("tb_reg is NULL!\n"); |
| return 0; |
| } |
| for (i = 0; i < 5; i++) { |
| if (IS_ERR_OR_NULL((void *)y5fld[i])) { |
| PPMGRVPP_INFO("y5fld[%d] is NULL!\n", |
| i); |
| inter_flag = 1; |
| break; |
| } |
| } |
| if (inter_flag) { |
| inter_flag = 0; |
| continue; |
| } |
| gfunc->stats_get(y5fld, tb_reg); |
| } |
| is_top = is_top ^ 1; |
| tbff_flag = -1; |
| if (gfunc) |
| tbff_flag = gfunc->fwalg_get(tb_reg, 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); |
| } |
| } |
| atomic_set(&tb_run_flag, 0); |
| kfree(tb_reg); |
| while (!kthread_should_stop()) |
| usleep_range(9000, 10000); |
| return 0; |
| } |
| |
| int start_tb_task(void) |
| { |
| if (!tb_detect_task) { |
| tb_detect_init(); |
| tb_detect_task = kthread_run(tb_task, 0, "tb_detect"); |
| } |
| if (!IS_ERR_OR_NULL(tb_detect_task)) |
| tb_task_running = 1; |
| else |
| tb_detect_task = NULL; |
| return 0; |
| } |
| |
| void stop_tb_task(void) |
| { |
| if (!IS_ERR_OR_NULL(tb_detect_task)) { |
| tb_quit_flag = true; |
| up(&ppmgr_device.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)ppmgr_dst_canvas[0], |
| 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_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("%s: gfunc %p, func: %p, ver:%s\n", |
| __func__, 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("%s: gfunc %p, func: %p\n", |
| __func__, gfunc, func); |
| if (func && func == gfunc) { |
| gfunc = NULL; |
| ret = 0; |
| } |
| mutex_unlock(&tb_mutex); |
| #endif |
| return ret; |
| } |
| EXPORT_SYMBOL(UnRegisterTB_Function); |
| |