| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| #include <linux/types.h> |
| #include <linux/init.h> |
| #include <linux/module.h> |
| #include <linux/kernel.h> |
| #include <linux/fs.h> |
| #include <linux/device.h> |
| #include <linux/cdev.h> |
| #include <linux/platform_device.h> |
| #include <linux/of.h> |
| #include <linux/of_device.h> |
| #include <linux/of_fdt.h> |
| #include <linux/of_reserved_mem.h> |
| #include <linux/of_irq.h> |
| #include <linux/string.h> |
| #include <linux/time.h> |
| #include <linux/mm.h> |
| #include <linux/slab.h> |
| #include <linux/stat.h> |
| #include <linux/errno.h> |
| #include <linux/uaccess.h> |
| #include <linux/of.h> |
| #include <linux/of_device.h> |
| #include <linux/ctype.h> |
| #include <linux/vmalloc.h> |
| #include <linux/interrupt.h> |
| #include <linux/delay.h> |
| #include <linux/time.h> |
| #include <asm/div64.h> |
| #include <linux/sched/clock.h> |
| #include <linux/amlogic/media/utils/am_com.h> |
| |
| #include <linux/amlogic/media/vout/vout_notify.h> |
| #include <linux/amlogic/media/vpu/vpu.h> |
| #include <linux/amlogic/media/vfm/vframe.h> |
| #include <linux/amlogic/media/vfm/vframe_provider.h> |
| #include <linux/amlogic/media/vfm/vframe_receiver.h> |
| #include <linux/amlogic/media/frame_sync/timestamp.h> |
| #include <linux/amlogic/media/frame_sync/tsync.h> |
| #include <linux/amlogic/media/frc/frc_reg.h> |
| #include <linux/amlogic/media/frc/frc_common.h> |
| #include <linux/amlogic/tee.h> |
| #include <linux/clk.h> |
| #include <linux/amlogic/media/video_sink/video.h> |
| |
| #include "frc_drv.h" |
| #include "frc_proc.h" |
| #include "frc_hw.h" |
| #include "frc_rdma.h" |
| #include "frc_dbg.h" |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| #include <linux/amlogic/aml_iotrace.h> |
| #endif |
| |
| int frc_enable_cnt = 1; |
| int frc_disable_cnt = 1; |
| int frc_re_cfg_cnt = 3;/*need bigger than frc_disable_cnt 3, 15*/ |
| |
| u32 secure_tee_handle; |
| |
| static int char_flash_check; |
| |
| void frc_fw_initial(struct frc_dev_s *devp) |
| { |
| if (!devp) |
| return; |
| |
| devp->in_sts.vs_cnt = 0; |
| devp->in_sts.vs_tsk_cnt = 0; |
| devp->in_sts.lost_tsk_cnt = 0; |
| devp->in_sts.vs_timestamp = sched_clock(); |
| devp->in_sts.vf_repeat_cnt = 0; |
| devp->in_sts.vf_null_cnt = 0; |
| |
| devp->out_sts.vs_cnt = 0; |
| devp->out_sts.vs_tsk_cnt = 0; |
| devp->out_sts.lost_tsk_cnt = 0; |
| devp->out_sts.vs_timestamp = sched_clock(); |
| devp->in_sts.vf = NULL; |
| // devp->frc_sts.vs_cnt = 0; |
| devp->vs_timestamp = sched_clock(); |
| |
| devp->frc_sts.inp_undone_cnt = 0; |
| devp->frc_sts.me_undone_cnt = 0; |
| devp->frc_sts.mc_undone_cnt = 0; |
| devp->frc_sts.vp_undone_cnt = 0; |
| devp->little_win = 0; |
| } |
| |
| static void frc_mute_config(void) |
| { |
| struct frc_dev_s *devp; |
| |
| devp = get_frc_devp(); |
| /*if not receive vpu mute information, frc doesn't open mute function*/ |
| if (devp->in_sts.in_hsize < WIDTH_2K || |
| devp->in_sts.in_vsize < HEIGHT_1K || |
| !get_video_mute()) |
| devp->in_sts.enable_mute_flag = 0; |
| else |
| devp->in_sts.enable_mute_flag = 1; |
| |
| if (devp->in_sts.duration > 4005) |
| devp->in_sts.mute_vsync_cnt = 45; |
| else if (devp->in_sts.duration > 1605) |
| devp->in_sts.mute_vsync_cnt = 15; |
| else |
| devp->in_sts.mute_vsync_cnt = 55; |
| |
| pr_frc(2, "enable_mute_flag = %d,mute_vsync_cnt = %d\n", |
| devp->in_sts.enable_mute_flag, devp->in_sts.mute_vsync_cnt); |
| } |
| |
| void frc_hw_initial(struct frc_dev_s *devp) |
| { |
| frc_fw_initial(devp); |
| frc_mtx_set(devp); |
| frc_rdma_rd_table_init(devp); |
| frc_top_init(devp); |
| t3x_verB_set_cfg(0, devp); |
| frc_input_size_align_check(devp); |
| if (devp->test2) |
| frc_mute_config(); |
| frc_pattern_dbg_ctrl(devp); |
| return; |
| } |
| |
| void frc_in_reg_monitor(struct frc_dev_s *devp) |
| { |
| u32 i; |
| u32 reg; |
| //char *buf = devp->dbg_buf; |
| |
| for (i = 0; i < MONITOR_REG_MAX; i++) { |
| reg = devp->dbg_in_reg[i]; |
| if (reg != 0 && reg < 0x3fff) { |
| if (devp->dbg_buf_len > 300) { |
| devp->dbg_reg_monitor_i = 0; |
| devp->dbg_buf_len = 0; |
| return; |
| } |
| devp->dbg_buf_len++; |
| pr_info("ivs:%d 0x%x=0x%08x\n", devp->in_sts.vs_cnt, |
| reg, READ_FRC_REG(reg)); |
| } |
| } |
| } |
| |
| void frc_vf_monitor(struct frc_dev_s *devp) |
| { |
| if (devp->dbg_buf_len > 300) { |
| devp->dbg_vf_monitor = 0; |
| return; |
| } |
| devp->dbg_buf_len++; |
| pr_info("ivs:%d 0x%lx\n", devp->frc_sts.vs_cnt, (ulong)devp->in_sts.vf); |
| } |
| |
| void frc_out_reg_monitor(struct frc_dev_s *devp) |
| { |
| u32 i; |
| u32 reg; |
| |
| for (i = 0; i < MONITOR_REG_MAX; i++) { |
| reg = devp->dbg_out_reg[i]; |
| if (reg != 0 && reg < 0x3fff) { |
| if (devp->dbg_buf_len > 300) { |
| devp->dbg_reg_monitor_o = 0; |
| devp->dbg_buf_len = 0; |
| return; |
| } |
| devp->dbg_buf_len++; |
| pr_info("ovs:%d 0x%x=0x%08x\n", devp->out_sts.vs_cnt, |
| reg, READ_FRC_REG(reg)); |
| } |
| } |
| } |
| |
| void frc_dump_monitor_data(struct frc_dev_s *devp) |
| { |
| //char *buf = devp->dbg_buf; |
| //pr_info("%d, %s\n", devp->dbg_buf_len, buf); |
| devp->dbg_buf_len = 0; |
| } |
| |
| /*frc-fw input task execution time*/ |
| void frc_in_task_print(u64 timer) |
| { |
| static u64 in_tsk_inx, in_tsk_min, in_tsk_max, in_tsk_sum; |
| |
| in_tsk_inx++; |
| in_tsk_sum += timer; |
| if (in_tsk_min > timer) |
| in_tsk_min = timer; |
| if (in_tsk_max < timer) |
| in_tsk_max = timer; |
| |
| if (in_tsk_inx == 60) { |
| pr_frc(0, "in_tsk_time min = %lld max = %lld avg = %lld\n", |
| in_tsk_min, in_tsk_max, div64_u64(in_tsk_sum, 60)); |
| in_tsk_min = in_tsk_max; |
| in_tsk_inx = 0; |
| in_tsk_sum = 0; |
| in_tsk_max = 0; |
| } |
| } |
| |
| /*frc-fw output task execution time*/ |
| void frc_out_task_print(u64 timer) |
| { |
| static u64 out_tsk_inx, out_tsk_min, out_tsk_max, out_tsk_sum; |
| |
| out_tsk_inx++; |
| out_tsk_sum += timer; |
| if (out_tsk_min > timer) |
| out_tsk_min = timer; |
| if (out_tsk_max < timer) |
| out_tsk_max = timer; |
| |
| if (out_tsk_inx == 60) { |
| pr_frc(0, "out_tsk_time min = %lld max = %lld avg = %lld\n", |
| out_tsk_min, out_tsk_max, div64_u64(out_tsk_sum, 60)); |
| out_tsk_min = out_tsk_max; |
| out_tsk_inx = 0; |
| out_tsk_sum = 0; |
| out_tsk_max = 0; |
| } |
| } |
| |
| /*use to frc "status" debug*/ |
| void frc_isr_print_zero(struct frc_dev_s *devp) |
| { |
| if (devp->frc_sts.changed_flag == 0) |
| return; |
| devp->in_sts.vs_duration = 0; |
| devp->in_sts.vs_timestamp = 0; |
| devp->in_sts.vs_cnt = 0; |
| devp->in_sts.vs_tsk_cnt = 0; |
| devp->in_sts.lost_tsk_cnt = 0; |
| |
| devp->out_sts.vs_duration = 0; |
| devp->out_sts.vs_timestamp = 0; |
| devp->out_sts.vs_cnt = 0; |
| devp->out_sts.vs_tsk_cnt = 0; |
| devp->out_sts.lost_tsk_cnt = 0; |
| |
| devp->frc_sts.vs_cnt = 0; |
| devp->frc_sts.video_mute_cnt = 0; |
| devp->frc_sts.vs_data_cnt = 0; |
| WRITE_FRC_REG_BY_CPU(0x6d, 0x0); |
| WRITE_FRC_REG_BY_CPU(0x6e, 0x0); |
| |
| devp->frc_sts.changed_flag = 0; |
| devp->ud_dbg.align_dbg_en = 0; |
| } |
| |
| void frc_rd_reg_by_drv(struct frc_dev_s *devp) |
| { |
| u8 i, en; |
| u16 log = 7; |
| struct frc_fw_data_s *fw_data; |
| |
| en = devp->timer_dbg.timer_en; |
| fw_data = (struct frc_fw_data_s *)devp->fw_data; |
| |
| if (!en && devp->timer_dbg.timer_level) |
| log = devp->timer_dbg.timer_level; |
| |
| for (i = 0; i < RD_REG_MAX; i++) { |
| if (!fw_data->reg_val[i].addr || fw_data->reg_val[i].addr > 0x3fff) |
| break; |
| fw_data->reg_val[i].val = READ_FRC_REG(fw_data->reg_val[i].addr); |
| // pr_frc(600, "reg:%04x val0x%08x %10d\n", |
| // fw_data->reg_val[i].addr, |
| // fw_data->reg_val[i].val, |
| // fw_data->reg_val[i].val); |
| } |
| } |
| |
| irqreturn_t frc_input_isr(int irq, void *dev_id) |
| { |
| struct frc_fw_data_s *pfw_data; |
| struct frc_dev_s *devp = (struct frc_dev_s *)dev_id; |
| |
| u64 timestamp = sched_clock(); |
| |
| |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return IRQ_HANDLED; |
| if (devp->clk_state == FRC_CLOCK_OFF) |
| return IRQ_HANDLED; |
| |
| if (devp->in_sts.vs_cnt - devp->in_sts.vs_tsk_cnt > |
| devp->in_sts.lost_tsk_cnt) { |
| devp->in_sts.lost_tsk_cnt = |
| devp->in_sts.vs_cnt - devp->in_sts.vs_tsk_cnt; |
| pr_frc(2, "in_isr_task was missing\n"); |
| } |
| devp->in_sts.vs_cnt++; |
| |
| /*update vs time*/ |
| timestamp = div64_u64(timestamp, 1000); |
| devp->in_sts.vs_duration = timestamp - devp->in_sts.vs_timestamp; |
| devp->in_sts.vs_timestamp = timestamp; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| if (!pfw_data) |
| return IRQ_HANDLED; |
| if (pfw_data->frc_top_type.motion_ctrl == RD_MOTION_BY_INP_ISR) |
| frc_rd_reg_by_drv(devp); |
| |
| inp_undone_read(devp); |
| if (devp->dbg_reg_monitor_i) |
| frc_in_reg_monitor(devp); |
| if (devp->in_sts.vs_cnt == devp->dbg_mvrd_mode) |
| if ((READ_FRC_REG(FRC_MC_MVRD_CTRL) & BIT_0) == BIT_0) |
| WRITE_FRC_REG_BY_CPU(FRC_MC_MVRD_CTRL, 0x100); |
| |
| if (devp->task_run_method == MEMC_RUN_IN_IRQ) { |
| if (!devp->frc_fw_pause) { |
| timestamp = sched_clock(); |
| if (pfw_data->memc_in_irq_handler) |
| pfw_data->memc_in_irq_handler(pfw_data); |
| if (devp->ud_dbg.inud_time_en) |
| frc_in_task_print(sched_clock() - timestamp); |
| } |
| } |
| if (devp->in_sts.hi_en) |
| tasklet_hi_schedule(&devp->input_tasklet); |
| else |
| tasklet_schedule(&devp->input_tasklet); |
| |
| FRC_RDMA_WR_REG_IN(FRC_REG_TOP_RESERVE13, devp->in_sts.vs_cnt); |
| frc_rdma_config(1, 0); |
| |
| return IRQ_HANDLED; |
| } |
| |
| void frc_input_tasklet_pro(unsigned long arg) |
| { |
| struct frc_dev_s *devp = (struct frc_dev_s *)arg; |
| struct frc_fw_data_s *pfw_data; |
| u64 timestamp; |
| |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return; |
| if (devp->clk_state == FRC_CLOCK_OFF) |
| return; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| if (!pfw_data) |
| return; |
| |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_FRC_INPUT_IN, 0, 0, 0); |
| #endif |
| devp->in_sts.vs_tsk_cnt++; |
| if (devp->task_run_method == MEMC_RUN_IN_TASK) { |
| if (!devp->frc_fw_pause) { |
| timestamp = sched_clock(); |
| if (pfw_data->memc_in_irq_handler) |
| pfw_data->memc_in_irq_handler(pfw_data); |
| if (devp->ud_dbg.inud_time_en) |
| frc_in_task_print(sched_clock() - timestamp); |
| } |
| } |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_FRC_INPUT_OUT, 0, 0, 0); |
| #endif |
| } |
| |
| irqreturn_t frc_output_isr(int irq, void *dev_id) |
| { |
| struct frc_dev_s *devp = (struct frc_dev_s *)dev_id; |
| struct frc_fw_data_s *pfw_data; |
| u32 tmpreg_value; |
| u64 timestamp = sched_clock(); |
| |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return IRQ_HANDLED; |
| if (devp->clk_state == FRC_CLOCK_OFF) |
| return IRQ_HANDLED; |
| |
| if (devp->out_sts.vs_cnt - devp->out_sts.vs_tsk_cnt > |
| devp->out_sts.lost_tsk_cnt) { |
| devp->out_sts.lost_tsk_cnt = |
| devp->out_sts.vs_cnt - devp->out_sts.vs_tsk_cnt; |
| pr_frc(2, "out_isr_task was missing\n"); |
| } |
| devp->out_sts.vs_cnt++; |
| /*update vs time*/ |
| timestamp = div64_u64(timestamp, 1000); |
| devp->out_sts.vs_duration = timestamp - devp->out_sts.vs_timestamp; |
| devp->out_sts.vs_timestamp = timestamp; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| if (!pfw_data) |
| return IRQ_HANDLED; |
| |
| if (devp->in_sts.vs_cnt == 1) { |
| tmpreg_value = READ_FRC_REG(FRC_REG_OUT_FID); |
| if ((tmpreg_value >> 8 & 0xFFF) != 0) { |
| PR_ERR("output buf error! 0x113:0x%8X, 0x102:0x%8X, ctl_7:0x%8X\n", |
| tmpreg_value, |
| READ_FRC_REG(FRC_REG_PAT_POINTER), |
| READ_FRC_REG(FRC_REG_TOP_CTRL7)); |
| } |
| } |
| me_undone_read(devp); |
| mc_undone_read(devp); |
| vp_undone_read(devp); |
| if (devp->task_run_method == MEMC_RUN_IN_IRQ) { |
| if (!devp->frc_fw_pause) { |
| timestamp = sched_clock(); |
| if (pfw_data->memc_out_irq_handler) |
| pfw_data->memc_out_irq_handler(pfw_data); |
| if (pfw_data->frc_fw_ctrl_if) |
| pfw_data->frc_fw_ctrl_if(pfw_data); |
| if (devp->ud_dbg.outud_time_en) |
| frc_out_task_print(sched_clock() - timestamp); |
| } |
| } |
| get_vout_info(devp); |
| |
| if (devp->dbg_reg_monitor_o) |
| frc_out_reg_monitor(devp); |
| if (devp->out_sts.hi_en) |
| tasklet_hi_schedule(&devp->output_tasklet); |
| else |
| tasklet_schedule(&devp->output_tasklet); |
| |
| // frc_rdma->rdma_item_count = 0; |
| // rdma trigger 0 manual, 1-7 auto path |
| FRC_RDMA_WR_REG_OUT(FRC_REG_TOP_RESERVE14, devp->out_sts.vs_cnt); |
| frc_rdma_config(2, 0); |
| |
| if (devp->ud_dbg.pr_dbg) |
| frc_debug_print(devp); |
| |
| return IRQ_HANDLED; |
| } |
| |
| void frc_output_tasklet_pro(unsigned long arg) |
| { |
| struct frc_dev_s *devp = (struct frc_dev_s *)arg; |
| struct frc_fw_data_s *pfw_data; |
| u64 timestamp; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| if (!pfw_data) |
| return; |
| if (!devp->probe_ok) |
| return; |
| if (!devp->power_on_flag) |
| return; |
| if (devp->clk_state == FRC_CLOCK_OFF) |
| return; |
| |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_FRC_OUTPUT_IN, 0, 0, 0); |
| #endif |
| devp->out_sts.vs_tsk_cnt++; |
| if (devp->in_sts.enable_mute_flag == 1 && |
| // devp->frc_sts.vs_data_cnt == devp->in_sts.mute_vsync_cnt) { |
| devp->out_sts.vs_cnt == devp->in_sts.mute_vsync_cnt) { |
| frc_set_output_pattern(0); // unmute |
| pr_frc(1, "%s: unmute after enable wait %d(%d) frames", |
| __func__, devp->out_sts.vs_cnt, |
| devp->frc_sts.vs_data_cnt); |
| } |
| if (devp->task_run_method == MEMC_RUN_IN_TASK) { |
| if (!devp->frc_fw_pause) { |
| timestamp = sched_clock(); |
| if (pfw_data->memc_out_irq_handler) |
| pfw_data->memc_out_irq_handler(pfw_data); |
| if (pfw_data->frc_fw_ctrl_if) |
| pfw_data->frc_fw_ctrl_if(pfw_data); |
| if (devp->ud_dbg.outud_time_en) |
| frc_out_task_print(sched_clock() - timestamp); |
| } |
| } |
| frc_dbg_frame_show(devp); |
| #if IS_ENABLED(CONFIG_AMLOGIC_DEBUG_IOTRACE) |
| iotrace_misc_record_write(RECORD_TYPE_FRC_OUTPUT_OUT, 0, 0, 0); |
| #endif |
| } |
| |
| irqreturn_t frc_axi_crash_isr(int irq, void *dev_id) |
| { |
| struct frc_dev_s *devp = (struct frc_dev_s *)dev_id; |
| u32 tmp1, tmp2; |
| |
| pr_frc(0, "%s: crash occur!", __func__); |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return IRQ_HANDLED; |
| if (devp->clk_state == FRC_CLOCK_OFF) |
| return IRQ_HANDLED; |
| |
| pr_frc(1, "apb_crash_addr:%X, axi_stats:0x%X,0x%X\n", |
| READ_FRC_REG(FRC_APB_CRASH_ADDR), |
| READ_FRC_REG(FRC_RDAXI0_PROT_STAT), |
| READ_FRC_REG(FRC_WRAXI0_PROT_STAT)); |
| tmp1 = READ_FRC_REG(FRC_RDAXI0_PROT_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI0_PROT_CTRL, tmp1 & 0xFFFFFFFD); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI0_PROT_CTRL, tmp1 | 0x02); |
| |
| tmp1 = READ_FRC_REG(FRC_RDAXI1_PROT_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI1_PROT_CTRL, tmp1 & 0xFFFFFFFD); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI1_PROT_CTRL, tmp1 | 0x02); |
| |
| tmp1 = READ_FRC_REG(FRC_RDAXI2_PROT_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI2_PROT_CTRL, tmp1 & 0xFFFFFFFD); |
| WRITE_FRC_REG_BY_CPU(FRC_RDAXI2_PROT_CTRL, tmp1 | 0x02); |
| |
| tmp1 = READ_FRC_REG(FRC_WRAXI0_PROT_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_WRAXI0_PROT_CTRL, tmp1 & 0xFFFFFFFD); |
| WRITE_FRC_REG_BY_CPU(FRC_WRAXI0_PROT_CTRL, tmp1 | 0x02); |
| |
| tmp1 = READ_FRC_REG(FRC_WRAXI1_PROT_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_WRAXI1_PROT_CTRL, tmp1 & 0xFFFFFFFD); |
| WRITE_FRC_REG_BY_CPU(FRC_WRAXI1_PROT_CTRL, tmp1 | 0x02); |
| |
| tmp2 = READ_FRC_REG(FRC_ARB_BAK_CTRL); |
| WRITE_FRC_REG_BY_CPU(FRC_ARB_BAK_CTRL, tmp2 & 0xFFFFFFDF); |
| WRITE_FRC_REG_BY_CPU(FRC_ARB_BAK_CTRL, tmp2 | 0x20); |
| |
| pr_frc(0, "%s: try to clear!", __func__); |
| return IRQ_HANDLED; |
| } |
| |
| void frc_change_to_state(enum frc_state_e state) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| |
| if (devp->in_sts.vf_sts == 0 && state == FRC_STATE_ENABLE) { |
| devp->frc_sts.frame_cnt = 0; |
| devp->frc_sts.state_transing = false; |
| pr_frc(0, "%s %d->%d, no video, can't change\n", __func__, |
| devp->frc_sts.state, state); |
| } else if (devp->frc_sts.state_transing) { |
| pr_frc(0, "%s state_transing busy(%d:%d->%d,frm:%d)!\n", __func__, |
| devp->frc_sts.state, devp->frc_sts.new_state, |
| state, devp->frc_sts.frame_cnt); |
| if (state != devp->frc_sts.new_state) { |
| devp->frc_sts.state = devp->frc_sts.new_state; |
| devp->frc_sts.new_state = state; |
| devp->frc_sts.frame_cnt = 0; |
| devp->frc_sts.state_transing = false; |
| pr_frc(0, "busy broken:%s %d->%d\n", __func__, |
| devp->frc_sts.state, state); |
| } |
| } else if (devp->frc_sts.state != state) { |
| devp->frc_sts.new_state = state; |
| devp->frc_sts.state_transing = true; |
| pr_frc(2, "%s %d->%d(frm=%d)\n", __func__, devp->frc_sts.state, |
| state, devp->frc_sts.frame_cnt); |
| } |
| } |
| |
| static bool frc_osd_window_en(struct st_frc_in_sts *cur_in_sts) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| if (get_chip_type() != ID_T3X) |
| return false; |
| |
| if ((cur_in_sts->in_hsize < HSIZE_MAX_4K && cur_in_sts->in_hsize > HSIZE_MIN_4K) || |
| (cur_in_sts->in_vsize < VSIZE_MAX_2K && cur_in_sts->in_vsize > VSIZE_MIN_2K)) |
| return true; |
| else if ((devp->out_sts.vout_width == WIDTH_2K && devp->out_sts.vout_height == HEIGHT_1K) && |
| ((cur_in_sts->in_hsize < HSIZE_MAX_2K && cur_in_sts->in_hsize > HSIZE_MIN_2K) || |
| (cur_in_sts->in_vsize < VSIZE_MAX_1K && cur_in_sts->in_vsize > VSIZE_MIN_1K))) |
| return true; |
| |
| return false; |
| } |
| |
| static void frc_fast_disable_process(void) |
| { |
| struct frc_dev_s *devp; |
| |
| devp = get_frc_devp(); |
| devp->in_sts.vf_sts = 0; |
| devp->in_sts.no_vf_cnt = 0; |
| devp->in_sts.have_vf_cnt = 0; |
| devp->frc_sts.out_put_mode_changed = FRC_EVENT_VF_CHG_IN_SIZE; |
| |
| set_frc_enable(false); |
| frc_change_to_state(FRC_STATE_BYPASS); |
| devp->st_change = 0; |
| devp->next_frame = 1; |
| set_frc_bypass(true); |
| frc_clr_badedit_effect_before_enable(); |
| frc_state_change_finish(devp); |
| pr_frc(2, "0x3217 = %x 0x35 = %x\n", vpu_reg_read(0x3217), |
| READ_FRC_REG(FRC_REG_OUT_INT_FLAG)); |
| } |
| |
| static void frc_disable_deal_diff_win(void) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| |
| if (devp->out_sts.out_framerate > 60 && |
| (devp->st_change == 1 || devp->st_change == 2)) { |
| return; |
| } else if (devp->frc_sts.state == FRC_STATE_ENABLE || |
| devp->frc_sts.new_state == FRC_STATE_ENABLE) { |
| pr_frc(2, "start disable frc\n"); |
| frc_fast_disable_process(); |
| } |
| } |
| |
| static void frc_disable_deal_n2m_change(void) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| |
| if (devp->in_sts.vc_set_n2m_change && |
| (devp->frc_sts.state == FRC_STATE_ENABLE || |
| devp->frc_sts.new_state == FRC_STATE_ENABLE)) { |
| pr_frc(2, "n2m change, start disable frc\n"); |
| set_frc_enable(false); |
| set_frc_bypass(true); |
| // frc_change_to_state(FRC_STATE_DISABLE); |
| frc_change_to_state(FRC_STATE_BYPASS); |
| frc_state_change_finish(devp); |
| } |
| } |
| |
| const char * const frc_state_ary[] = { |
| "FRC_STATE_DISABLE", |
| "FRC_STATE_ENABLE", |
| "FRC_STATE_BYPASS", |
| }; |
| |
| int frc_update_in_sts(struct frc_dev_s *devp, struct st_frc_in_sts *frc_in_sts, |
| struct vframe_s *vf, struct vpp_frame_par_s *cur_video_sts) |
| { |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!vf || !cur_video_sts) { |
| frc_in_sts->in_hsize = 0; |
| frc_in_sts->in_vsize = 0; |
| return -1; |
| } |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| frc_in_sts->vf_type = vf->type; |
| frc_in_sts->duration = vf->duration; |
| frc_in_sts->signal_type = vf->signal_type; |
| frc_in_sts->source_type = vf->source_type; |
| frc_in_sts->vf = vf; |
| frc_in_sts->vf_index = vf->frame_index; |
| |
| if (frc_in_sts->duration > 0 && devp->in_out_ratio != FRC_RATIO_1_1) { |
| pfw_data->frc_top_type.frc_in_frm_rate = |
| (1000000 / devp->in_sts.vs_duration); |
| pfw_data->frc_top_type.video_duration = (u16)(frc_in_sts->duration); |
| } else if (frc_in_sts->duration > 0 && |
| devp->in_out_ratio == FRC_RATIO_1_1) { |
| pfw_data->frc_top_type.frc_in_frm_rate = |
| pfw_data->frc_top_type.frc_out_frm_rate; |
| } else { |
| pfw_data->frc_top_type.frc_in_frm_rate = 0; |
| } |
| |
| if (!frc_in_sts->vf_sts) { |
| frc_in_sts->in_hsize = 0; |
| frc_in_sts->in_vsize = 0; |
| } else if (devp->dbg_force_en && devp->dbg_input_hsize && |
| devp->dbg_input_vsize) { |
| frc_in_sts->in_hsize = devp->dbg_input_hsize; |
| frc_in_sts->in_vsize = devp->dbg_input_vsize; |
| } else { |
| if (devp->frc_hw_pos == FRC_POS_AFTER_POSTBLEND) { |
| frc_in_sts->in_hsize = devp->out_sts.vout_width; |
| frc_in_sts->in_vsize = devp->out_sts.vout_height; |
| } else { |
| //frc_in_sts->in_hsize = cur_video_sts->nnhf_input_w; |
| //frc_in_sts->in_vsize = cur_video_sts->nnhf_input_h; |
| frc_in_sts->in_hsize = cur_video_sts->frc_h_size; |
| frc_in_sts->in_vsize = cur_video_sts->frc_v_size; |
| } |
| } |
| // if (devp->frc_sts.vs_cnt < 100) |
| // pr_frc(2, "vs_cnt %d: get in size(%d,%d) vd_sr_out(%d,%d)\n", |
| // devp->frc_sts.vs_cnt, |
| // frc_in_sts->in_hsize, frc_in_sts->in_vsize, |
| // cur_video_sts->frc_h_size, cur_video_sts->frc_v_size); |
| |
| if (frc_in_sts->frc_hd_start_lines != cur_video_sts->VPP_hd_start_lines_ || |
| frc_in_sts->frc_hd_end_lines != cur_video_sts->VPP_hd_end_lines_) { |
| frc_in_sts->frc_hd_start_lines = cur_video_sts->VPP_hd_start_lines_; |
| frc_in_sts->frc_hd_end_lines = cur_video_sts->VPP_hd_end_lines_; |
| } |
| if (frc_in_sts->frc_vd_start_lines != cur_video_sts->VPP_vd_start_lines_ || |
| frc_in_sts->frc_vd_end_lines != cur_video_sts->VPP_vd_end_lines_) { |
| frc_in_sts->frc_vd_start_lines = cur_video_sts->VPP_vd_start_lines_; |
| frc_in_sts->frc_vd_end_lines = cur_video_sts->VPP_vd_end_lines_; |
| } |
| |
| if (frc_in_sts->frc_vsc_startp != cur_video_sts->VPP_vsc_startp || |
| frc_in_sts->frc_hsc_startp != cur_video_sts->VPP_hsc_startp) { |
| frc_in_sts->frc_vsc_startp = cur_video_sts->VPP_vsc_startp; |
| frc_in_sts->frc_hsc_startp = cur_video_sts->VPP_hsc_startp; |
| } |
| return 0; |
| } |
| |
| enum efrc_event frc_input_sts_check(struct frc_dev_s *devp, |
| struct st_frc_in_sts *cur_in_sts) |
| { |
| /* check change */ |
| enum efrc_event sts_change = FRC_EVENT_NO_EVENT; |
| //enum frc_state_e cur_state = devp->frc_sts.state; |
| u32 cur_sig_in; |
| u32 tmpvalue; |
| bool is_osd_window; |
| struct frc_fw_data_s *pfw_data; |
| struct frc_top_type_s *frc_top; |
| struct vinfo_s *vinfo = get_current_vinfo(); |
| static u16 seamless_cnt; |
| |
| is_osd_window = frc_osd_window_en(cur_in_sts); |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| frc_top = &pfw_data->frc_top_type; |
| |
| /*back up*/ |
| devp->in_sts.vf_type = cur_in_sts->vf_type; |
| devp->in_sts.duration = cur_in_sts->duration; |
| devp->in_sts.signal_type = cur_in_sts->signal_type; |
| devp->in_sts.source_type = cur_in_sts->source_type; |
| devp->in_sts.frc_vsc_startp = cur_in_sts->frc_vsc_startp; |
| devp->in_sts.frc_hsc_startp = cur_in_sts->frc_hsc_startp; |
| devp->in_sts.vf_index = cur_in_sts->vf_index; |
| devp->in_sts.vf = cur_in_sts->vf; |
| frc_top->inp_padding_xofst = devp->in_sts.frc_hsc_startp; |
| frc_top->inp_padding_yofst = devp->in_sts.frc_vsc_startp; |
| if (cur_in_sts->vf && cur_in_sts->vf->vc_private && |
| devp->in_sts.vc_set_n2m_mode != cur_in_sts->vf->vc_private->frc_operation_mode) { |
| devp->in_sts.vc_set_n2m_mode = cur_in_sts->vf->vc_private->frc_operation_mode; |
| devp->in_sts.vc_set_n2m_change = 1; |
| pr_frc(2, "ready to change n2m[%d]\n", devp->in_sts.vc_set_n2m_mode); |
| frc_disable_deal_n2m_change(); |
| } else { |
| devp->in_sts.vc_set_n2m_change = 0; |
| } |
| |
| if (devp->next_frame == 1) { |
| devp->need_bypass = 0; |
| devp->next_frame++; |
| pr_frc(2, "0x3217 = %x 0x35 = %x\n", vpu_reg_read(0x3217), |
| READ_FRC_REG(FRC_REG_OUT_INT_FLAG)); |
| } else if (devp->next_frame == 2) { |
| devp->next_frame = 0; |
| pr_frc(2, "0x3217 = %x 0x35 = %x\n", vpu_reg_read(0x3217), |
| READ_FRC_REG(FRC_REG_OUT_INT_FLAG)); |
| } |
| |
| /* check h size change */ |
| devp->in_sts.size_chged = 0; |
| devp->in_sts.t3x_proc_size_chg = 0; |
| if (devp->in_sts.in_hsize != cur_in_sts->in_hsize) { |
| pr_frc(1, "hsize change (%d - %d)\n", |
| devp->in_sts.in_hsize, cur_in_sts->in_hsize); |
| devp->in_sts.in_hsize = cur_in_sts->in_hsize; |
| devp->in_sts.t3x_proc_size_chg = 1; |
| if (get_chip_type() == ID_T3X) { |
| frc_disable_deal_diff_win(); |
| } else if (devp->frc_sts.state == FRC_STATE_ENABLE && get_chip_type() == ID_T5M) { |
| pr_frc(2, "%s start disable frc", __func__); |
| set_frc_enable(false); |
| set_frc_bypass(true); |
| // frc_change_to_state(FRC_STATE_DISABLE); |
| frc_change_to_state(FRC_STATE_BYPASS); |
| frc_state_change_finish(devp); |
| } |
| if (devp->in_sts.frc_seamless_en) { |
| if (devp->in_sts.in_hsize == 0) { |
| /*need reconfig*/ |
| devp->frc_sts.re_cfg_cnt = frc_re_cfg_cnt; |
| sts_change |= FRC_EVENT_VF_CHG_IN_SIZE; |
| } else if (devp->frc_sts.state == FRC_STATE_ENABLE) { |
| devp->in_sts.size_chged = 1; |
| } |
| } else { |
| /*need reconfig*/ |
| devp->frc_sts.re_cfg_cnt = frc_re_cfg_cnt; |
| sts_change |= FRC_EVENT_VF_CHG_IN_SIZE; |
| } |
| } |
| /* check v size change */ |
| if (devp->in_sts.in_vsize != cur_in_sts->in_vsize) { |
| pr_frc(1, "vsize change (%d - %d)\n", |
| devp->in_sts.in_vsize, cur_in_sts->in_vsize); |
| devp->in_sts.in_vsize = cur_in_sts->in_vsize; |
| devp->in_sts.t3x_proc_size_chg = 1; |
| if (get_chip_type() == ID_T3X && cur_in_sts->vf_sts) { |
| frc_disable_deal_diff_win(); |
| } else if (devp->frc_sts.state == FRC_STATE_ENABLE && get_chip_type() == ID_T5M) { |
| pr_frc(2, "%s start disable frc", __func__); |
| set_frc_enable(false); |
| set_frc_bypass(true); |
| // frc_change_to_state(FRC_STATE_DISABLE); |
| frc_change_to_state(FRC_STATE_BYPASS); |
| frc_state_change_finish(devp); |
| } |
| if (devp->in_sts.frc_seamless_en) { |
| if (devp->in_sts.in_vsize == 0) { |
| /*need reconfig*/ |
| devp->frc_sts.re_cfg_cnt = frc_re_cfg_cnt; |
| sts_change |= FRC_EVENT_VF_CHG_IN_SIZE; |
| } else if (devp->frc_sts.state == FRC_STATE_ENABLE) { |
| devp->in_sts.size_chged = 1; |
| } |
| } else { |
| /*need reconfig*/ |
| devp->frc_sts.re_cfg_cnt = frc_re_cfg_cnt; |
| sts_change |= FRC_EVENT_VF_CHG_IN_SIZE; |
| } |
| } |
| if (devp->in_sts.frc_seamless_en && !devp->in_sts.frc_is_tvin) { |
| if (seamless_cnt == 1) { |
| frc_input_init(devp, frc_top); |
| if (get_chip_type() == ID_T3X) { |
| if (frc_top->frc_ratio_mode == FRC_RATIO_1_2) |
| tmpvalue = (frc_top->hsize + 15) & 0xFFF0; |
| else |
| tmpvalue = frc_top->hsize; |
| tmpvalue |= (frc_top->vsize) << 16; |
| WRITE_FRC_REG_BY_CPU(FRC_FRAME_SIZE, tmpvalue); |
| } else { |
| tmpvalue = frc_top->hsize; |
| tmpvalue |= (frc_top->vsize) << 16; |
| WRITE_FRC_REG_BY_CPU(FRC_FRAME_SIZE, tmpvalue); |
| } |
| frc_top->is_me1mc4 = 1;/*me:mc 1:4*/ |
| WRITE_FRC_REG_BY_CPU(FRC_INPUT_SIZE_ALIGN, 0x3); //16*16 align |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, |
| (cur_in_sts->frc_hsc_startp) << 13 | |
| (cur_in_sts->frc_vsc_startp)); |
| |
| pr_frc(2, "manual set frc size:v(x):0x%x, h(y)0x%x\n", |
| cur_in_sts->frc_hd_start_lines, cur_in_sts->frc_vd_start_lines); |
| |
| if (pfw_data->frc_input_cfg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| devp->in_sts.size_chged = 0; |
| pr_frc(2, " %s size changed, frc not reopen\n", __func__); |
| |
| seamless_cnt = 0; |
| pr_frc(2, "seamless frm 2\n"); |
| return sts_change; |
| } else if (devp->in_sts.size_chged) { |
| if (!seamless_cnt || seamless_cnt > 1) |
| seamless_cnt = 1; // frame cnt 1 |
| pr_frc(2, "seamless frm 1 seamless_cnt:%d\n", seamless_cnt); |
| } else if (!devp->in_sts.size_chged) { |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, |
| (cur_in_sts->frc_hsc_startp) << 13 | |
| (cur_in_sts->frc_vsc_startp)); |
| seamless_cnt = 0; |
| // pr_frc(2, "seamless frm 3\n"); |
| } |
| } else { |
| frc_top->inp_padding_xofst = 0; |
| frc_top->inp_padding_yofst = 0; |
| } |
| |
| if (devp->frc_sts.out_put_mode_changed || devp->frc_sts.re_config) { |
| pr_frc(1, "out_put_mode_changed 0x%x re_config:%d\n", |
| devp->frc_sts.out_put_mode_changed, |
| devp->frc_sts.re_config); |
| if (devp->frc_sts.out_put_mode_changed == |
| FRC_EVENT_VF_CHG_IN_SIZE) { |
| devp->frc_sts.re_cfg_cnt = 5; |
| } else if (devp->frc_sts.out_put_mode_changed == |
| FRC_EVENT_VOUT_CHG) { |
| if (devp->out_sts.vout_width != vinfo->width || |
| devp->out_sts.vout_height != vinfo->height) |
| devp->frc_sts.re_cfg_cnt = 3; |
| pr_frc(1, "out_chg-w(%d->%d)-h(%d->%d)-d(%d->%d)\n", |
| devp->out_sts.vout_width, vinfo->width, |
| devp->out_sts.vout_height, vinfo->height, |
| devp->out_sts.out_framerate, |
| (vinfo->sync_duration_num * 100 / vinfo->sync_duration_den) / 100); |
| if (devp->out_sts.vout_width == vinfo->width && |
| devp->out_sts.vout_height == vinfo->height && |
| devp->frc_sts.state == FRC_STATE_ENABLE && |
| !devp->in_sts.size_chged) { |
| devp->frc_sts.re_cfg_cnt = 0; |
| pr_frc(1, "%s rate chg\n", __func__); |
| } |
| //devp->out_sts.vout_height = vinfo->height; |
| //devp->out_sts.vout_width = vinfo->width; |
| } else { |
| devp->frc_sts.re_cfg_cnt = frc_re_cfg_cnt; |
| } |
| sts_change |= FRC_EVENT_VOUT_CHG; |
| devp->frc_sts.out_put_mode_changed = 0; |
| devp->frc_sts.re_config = 0; |
| } |
| |
| /* check is same vframe */ |
| pr_frc(dbg_sts, "vf (0x%lx, 0x%lx)\n", (ulong)devp->in_sts.vf, (ulong)cur_in_sts->vf); |
| if (devp->in_sts.vf == cur_in_sts->vf && cur_in_sts->vf_sts) |
| devp->in_sts.vf_repeat_cnt++; |
| |
| devp->in_sts.vf = cur_in_sts->vf; |
| |
| if (devp->frc_sts.re_cfg_cnt) { |
| devp->frc_sts.re_cfg_cnt--; |
| cur_sig_in = false; |
| } else if (devp->in_sts.in_hsize < FRC_H_LIMIT || |
| devp->in_sts.in_vsize < FRC_V_LIMIT) { |
| cur_sig_in = false; |
| } else { |
| cur_sig_in = cur_in_sts->vf_sts; |
| } |
| |
| pr_frc(dbg_sts, "vf_sts: %d, cur_sig_in:0x%x have_cnt:%d no_cnt:%d re_cfg_cnt:%d\n", |
| devp->in_sts.vf_sts, cur_sig_in, |
| devp->in_sts.have_vf_cnt, devp->in_sts.no_vf_cnt, devp->frc_sts.re_cfg_cnt); |
| |
| switch (devp->in_sts.vf_sts) { |
| case VFRAME_NO: |
| if (cur_sig_in == VFRAME_HAVE) { |
| if (devp->in_sts.have_vf_cnt++ >= |
| (frc_enable_cnt + (is_osd_window ? WINDOW_DELAY_CNT : 0))) { |
| devp->in_sts.vf_sts = cur_sig_in; |
| //if (FRC_EVENT_VF_IS_GAME) |
| sts_change |= FRC_EVENT_VF_CHG_TO_HAVE; |
| devp->in_sts.have_vf_cnt = 0; |
| pr_frc(1, "FRC_EVENT_VF_CHG_TO_HAVE\n"); |
| } |
| } else { |
| devp->in_sts.have_vf_cnt = 0; |
| if (devp->frc_sts.state == FRC_STATE_DISABLE && |
| devp->in_sts.vf_null_cnt == 200) { |
| devp->frc_sts.retrycnt = 0; |
| frc_change_to_state(FRC_STATE_BYPASS); |
| pr_frc(1, "no_frm->chg bypass\n"); |
| } else if (devp->frc_sts.state == FRC_STATE_BYPASS && |
| devp->in_sts.vf_null_cnt == 1200 && |
| devp->clk_state == FRC_CLOCK_NOR) { |
| devp->clk_state = FRC_CLOCK_NOR2XXX; |
| schedule_work(&devp->frc_clk_work); |
| pr_frc(1, "no_frm->disable clk\n"); |
| } |
| } |
| break; |
| case VFRAME_HAVE: |
| if (cur_sig_in == VFRAME_NO) { |
| if (devp->in_sts.no_vf_cnt++ >= frc_disable_cnt) { |
| devp->in_sts.vf_sts = cur_sig_in; |
| devp->in_sts.no_vf_cnt = 0; |
| pr_frc(1, "FRC_EVENT_VF_CHG_TO_NO\n"); |
| sts_change |= FRC_EVENT_VF_CHG_TO_NO; |
| } |
| } else { |
| devp->in_sts.no_vf_cnt = 0; |
| } |
| break; |
| } |
| |
| /* even attach , mode change */ |
| if (devp->frc_sts.auto_ctrl && sts_change) { |
| if (sts_change & FRC_EVENT_VF_CHG_TO_NO) |
| //frc_change_to_state(FRC_STATE_DISABLE); |
| frc_change_to_state(FRC_STATE_BYPASS); |
| else if (sts_change & FRC_EVENT_VF_CHG_TO_HAVE) |
| frc_change_to_state(FRC_STATE_ENABLE); |
| } |
| if (devp->dbg_vf_monitor) |
| frc_vf_monitor(devp); |
| |
| return sts_change; |
| } |
| |
| /*video_input_w |
| * input vframe and display mode handle |
| * |
| */ |
| void frc_input_vframe_handle(struct frc_dev_s *devp, struct vframe_s *vf, |
| struct vpp_frame_par_s *cur_video_sts) |
| { |
| struct st_frc_in_sts cur_in_sts; |
| struct frc_fw_data_s *pfw_data; |
| u32 no_input = false, vd_en_flag;// vd_regval; |
| u32 in_size = 0; |
| enum efrc_event frc_event = FRC_EVENT_NO_EVENT; |
| |
| if (!devp) |
| return; |
| |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| frc_in_sts_init(&cur_in_sts); |
| vd_en_flag = get_video_enabled(0); |
| // vd_regval = vpu_reg_read(0x1dfb); |
| if (devp->ud_dbg.res1_dbg_en == 1) |
| pr_frc(1, "get_vd_en=%2d\n", vd_en_flag); |
| if (!vf || !cur_video_sts || vd_en_flag == 0) { |
| devp->in_sts.vf_null_cnt++; |
| no_input = true; |
| } else { |
| in_size = (cur_video_sts->nnhf_input_w << 16) + cur_video_sts->nnhf_input_h; |
| } |
| //} else if ((vd_regval & (BIT_0 | BIT_8)) == 0) { |
| //devp->in_sts.vf_null_cnt++; |
| //no_input = true; |
| //} |
| |
| if (vf) { |
| if ((vf->flag & VFRAME_FLAG_GAME_MODE) == |
| VFRAME_FLAG_GAME_MODE) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_GAME_MODE) != |
| FRC_FLAG_GAME_MODE) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_GAME_MODE; |
| pr_frc(1, "video = game_mode size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else if ((vf->flag & VFRAME_FLAG_PC_MODE) == |
| VFRAME_FLAG_PC_MODE) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_PC_MODE) != |
| FRC_FLAG_PC_MODE) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_PC_MODE; |
| pr_frc(1, "video = pc_mode size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else if ((vf->flag & VFRAME_FLAG_HIGH_BANDWIDTH) == |
| VFRAME_FLAG_HIGH_BANDWIDTH) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_HIGH_BW) != |
| FRC_FLAG_HIGH_BW) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_HIGH_BW; |
| pr_frc(1, "video = high_bw size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & |
| (~(FRC_FLAG_GAME_MODE + |
| FRC_FLAG_HIGH_BW + |
| FRC_FLAG_PC_MODE)); |
| } |
| |
| if ((vf->type & VIDTYPE_PIC) == VIDTYPE_PIC) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_PIC_MODE) != |
| FRC_FLAG_PIC_MODE) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_PIC_MODE; |
| pr_frc(1, "video = pic_mode size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_PIC_MODE); |
| } |
| |
| if (!cur_video_sts) { |
| pr_frc(1, "vpp_frame_par_s is NULL"); |
| no_input = true; |
| } else if (cur_video_sts->frc_h_size < FRC_H_LIMIT || |
| cur_video_sts->frc_v_size < FRC_V_LIMIT) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_INSIZE_ERR) != |
| FRC_FLAG_INSIZE_ERR) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_INSIZE_ERR; |
| pr_frc(1, "video = err_insize size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else if (cur_video_sts->frc_h_size > 3840 + 8 || |
| cur_video_sts->frc_v_size > 2160 + 8) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_INSIZE_ERR) != |
| FRC_FLAG_INSIZE_ERR) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_INSIZE_ERR; |
| pr_frc(1, "video = err_insize size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_INSIZE_ERR); |
| } |
| |
| if (devp->out_sts.out_framerate == FRC_VD_FPS_144 || |
| devp->out_sts.out_framerate == FRC_VD_FPS_288) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_LIMIT_FREQ) != |
| FRC_FLAG_LIMIT_FREQ) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_LIMIT_FREQ; |
| pr_frc(1, "video = limit_freq size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_LIMIT_FREQ); |
| } |
| |
| if (get_video_mute()) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_MUTE_ST) != |
| FRC_FLAG_MUTE_ST) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_MUTE_ST; |
| pr_frc(1, "video = video mute"); |
| } |
| devp->frc_sts.video_mute_cnt++; |
| if (devp->out_sts.out_framerate < 70) |
| no_input = devp->dbg_mute_disable; |
| pr_frc(1, "video_mute_cnt = %d", devp->frc_sts.video_mute_cnt); |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_MUTE_ST); |
| } |
| |
| if ((vf->flag & VFRAME_FLAG_VIDEO_SECURE) == |
| VFRAME_FLAG_VIDEO_SECURE) { |
| devp->in_sts.secure_mode = true; |
| /*for test secure mode disable memc*/ |
| //no_input = true; |
| } else { |
| devp->in_sts.secure_mode = false; |
| } |
| //input security check |
| // frc_check_secure_mode(vf, devp); /*get secure mode will delay 10 frames*/ |
| /*check vd status change*/ |
| if (!no_input) { |
| frc_chk_vd_sts_chg(devp, vf); |
| if (!devp->in_sts.frc_is_tvin) |
| frc_char_flash_check(); |
| else |
| frc_set_seamless_proc(0); // tvin close seamless |
| } |
| |
| if (devp->in_sts.frc_vf_rate == FRC_VD_FPS_100 || |
| devp->in_sts.frc_vf_rate == FRC_VD_FPS_120) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_HIGH_FREQ) != |
| FRC_FLAG_HIGH_FREQ) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_HIGH_FREQ; |
| pr_frc(1, "high freq size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_HIGH_FREQ); |
| } |
| |
| if (devp->in_sts.frc_vf_rate == FRC_VD_FPS_00) { |
| if ((devp->in_sts.st_flag & FRC_FLAG_ZERO_FREQ) != |
| FRC_FLAG_ZERO_FREQ) { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag | FRC_FLAG_ZERO_FREQ; |
| pr_frc(1, "zero freq size(%d,%d)\n", |
| in_size >> 16, |
| in_size & 0xFFFF); |
| } |
| if (vf->duration <= 1500) |
| no_input = true; |
| } else { |
| devp->in_sts.st_flag = |
| devp->in_sts.st_flag & (~FRC_FLAG_ZERO_FREQ); |
| } |
| } |
| |
| /*secure mode*/ |
| if (devp->in_sts.secure_mode != devp->buf.secured && |
| devp->buf.cma_mem_alloced) { |
| if (devp->in_sts.secure_mode == 0 && |
| devp->buf.secured == 1) { |
| no_input = true; |
| frc_re_cfg_cnt = 0; // need reopen instantly |
| } |
| // pr_frc(0, "sec chg _______\n"); |
| // schedule_work(&devp->frc_secure_work); |
| // pr_frc(2, "frc_re_cfg_cnt:%d pre_secure_mode:%d\n", |
| // frc_re_cfg_cnt, devp->buf.secured); |
| } else { |
| frc_re_cfg_cnt = FRC_RE_CFG_CNT; |
| } |
| |
| if (no_input && (devp->control_0 & BIT_0) && get_chip_type() == ID_T5M) |
| devp->auto_n2m = 2; |
| else if ((devp->control_0 & BIT_1) && get_chip_type() == ID_T5M) |
| pfw_data->frc_fw_alg_ctrl.frc_algctrl_u8param4 = 0; |
| else if ((devp->control_0 & BIT_2) && get_chip_type() == ID_T5M) |
| devp->auto_n2m = 1; |
| |
| if (frc_set_n2m_from_vc(vf) == -1) |
| no_input = true; |
| |
| if (devp->frc_hw_pos == FRC_POS_AFTER_POSTBLEND) |
| cur_in_sts.vf_sts = true; |
| else |
| cur_in_sts.vf_sts = no_input ? false : true; |
| |
| if (cur_in_sts.vf_sts) { |
| devp->frc_sts.vs_data_cnt++; |
| frc_rd_reg_by_drv(devp); |
| if (devp->frc_sts.vs_data_cnt < 50) |
| pr_frc(2, "vpp vsync (data) idx =%d, 0x1a1c =0x%x, 0x3f01 =0x%x\n", |
| devp->frc_sts.vs_data_cnt, |
| vpu_reg_read(devp->vpu_byp_frc_reg_addr), |
| READ_FRC_REG(0x3f01)); |
| } |
| frc_update_in_sts(devp, &cur_in_sts, vf, cur_video_sts); |
| |
| /* check input is change */ |
| frc_event = frc_input_sts_check(devp, &cur_in_sts); |
| |
| if (frc_event) |
| pr_frc(1, "event = 0x%08x\n", frc_event); |
| pr_frc(2, "mc crc value = %x", READ_FRC_REG(0x3981)); |
| } |
| |
| void frc_state_change_finish(struct frc_dev_s *devp) |
| { |
| if (devp->frc_sts.state == FRC_STATE_ENABLE && |
| (devp->frc_sts.new_state == FRC_STATE_BYPASS || |
| devp->frc_sts.new_state == FRC_STATE_DISABLE)) |
| devp->frc_sts.changed_flag = 1; |
| |
| devp->frc_sts.state = devp->frc_sts.new_state; |
| devp->frc_sts.state_transing = false; |
| devp->frc_sts.frame_cnt = 0; |
| } |
| |
| void frc_test_mm_secure_set_off(struct frc_dev_s *devp) |
| { |
| if (!tee_enabled()) { |
| pr_frc(0, "tee is not enable\n"); |
| return; |
| } |
| |
| if (secure_tee_handle) { |
| tee_unprotect_mem(secure_tee_handle); |
| pr_frc(0, "%s handl:%d\n", __func__, secure_tee_handle); |
| secure_tee_handle = 0; |
| } |
| } |
| |
| void frc_test_mm_secure_set_on(struct frc_dev_s *devp, u32 start, u32 size) |
| { |
| if (!tee_enabled()) { |
| pr_frc(0, "tee is not enable\n"); |
| return; |
| } |
| |
| if (!secure_tee_handle) { |
| tee_protect_mem_by_type(TEE_MEM_TYPE_FRC, start, size, &secure_tee_handle); |
| pr_frc(0, "%s handl:%d start:0x%x size:0x%x\n", __func__, |
| secure_tee_handle, start, size); |
| } |
| } |
| |
| void frc_mm_secure_set(struct frc_dev_s *devp) |
| { |
| phys_addr_t addr_start; |
| u32 addr_size; |
| enum frc_state_e new_state; |
| |
| if (!tee_enabled()) { |
| pr_frc(0, "tee is not enable\n"); |
| return; |
| } |
| if (!devp) |
| return; |
| if (!devp->probe_ok || !devp->power_on_flag) |
| return; |
| |
| /*data buffer set to secure mode*/ |
| addr_start = devp->buf.secure_start; |
| // data buf size: 0x9a30000 |
| addr_size = devp->buf.secure_size; |
| |
| /*data buffer, me/mc info and link buffer set to secure mode*/ |
| //addr_start = devp->buf.cma_mem_paddr_start + devp->buf.lossy_mc_y_info_buf_paddr; |
| //addr_size = devp->buf.norm_hme_data_buf_paddr[0] - devp->buf.lossy_mc_y_info_buf_paddr; |
| |
| new_state = devp->frc_sts.new_state; |
| |
| /*secure mode check*/ |
| if (!devp->in_sts.secure_mode) { |
| if (devp->buf.secured) { |
| devp->buf.secured = false; |
| /*call secure api to exit secure mode*/ |
| tee_unprotect_mem(secure_tee_handle); |
| frc_force_secure(false); |
| pr_frc(1, "%s tee_unprotect_mem %d\n", __func__, |
| secure_tee_handle); |
| secure_tee_handle = 0; |
| } |
| } else { |
| /*need set mm to secure mode*/ |
| if (new_state == FRC_STATE_ENABLE) { |
| if (!devp->buf.secured) { |
| devp->buf.secured = true; |
| /*call secure api enter secure mode*/ |
| tee_protect_mem_by_type(TEE_MEM_TYPE_FRC, addr_start, |
| addr_size, &secure_tee_handle); |
| frc_force_secure(true); |
| pr_frc(2, "%s handl:%d addr_start:0x%lx addr_size:0x%x\n", |
| __func__, secure_tee_handle, |
| (ulong)addr_start, addr_size); |
| } |
| } else { |
| if (devp->buf.secured) { |
| devp->buf.secured = false; |
| /*call secure api to exit secure mode*/ |
| tee_unprotect_mem(secure_tee_handle); |
| frc_force_secure(false); |
| pr_frc(1, "%s tee_unprotect_mem %d\n", __func__, |
| secure_tee_handle); |
| secure_tee_handle = 0; |
| } |
| } |
| } |
| } |
| |
| void frc_state_handle(struct frc_dev_s *devp) |
| { |
| enum frc_state_e cur_state; |
| enum frc_state_e new_state; |
| struct frc_fw_data_s *pfw_data; |
| u32 state_changed = 0; |
| u32 frame_cnt = 0; |
| u32 vframe_idx = 0; |
| static u8 forceidx; |
| static u8 bypasscnt; |
| static u8 freezecnt; |
| static u8 off2on_cnt; |
| u8 frc_input_fid = 0; |
| u32 read0x60 = 0; |
| u8 chg_flag = 0; |
| u32 log = 1; |
| |
| cur_state = devp->frc_sts.state; |
| new_state = devp->frc_sts.new_state; |
| frame_cnt = devp->frc_sts.frame_cnt; |
| chg_flag = devp->ud_dbg.res2_time_en; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| vframe_idx = devp->in_sts.vf_index; |
| |
| if (cur_state != new_state) { |
| state_changed = 1; |
| pr_frc(log, "stat_chg(%d->%d), frm_cnt:%d\n", cur_state, |
| new_state, frame_cnt); |
| if (chg_flag < 0x1F && frame_cnt < 20 && |
| devp->clk_state == FRC_CLOCK_NOR) |
| pr_frc(log, "frm:%d,reg_0x102:0x%8X,0x113:0x%8X,0x146:0x%8X,0x147:0x%8X\n", |
| frame_cnt, |
| READ_FRC_REG(FRC_REG_PAT_POINTER), |
| READ_FRC_REG(FRC_REG_OUT_FID), |
| READ_FRC_REG(FRC_REG_FWD_PHS), |
| READ_FRC_REG(FRC_REG_FWD_FID)); |
| pr_frc(log, "in_cnt:%X,out_cnt:%X,DBG1:0x%08X,DBG2:0x%08X,DBG3:0x%08X\n", |
| READ_FRC_REG(0x6d), |
| READ_FRC_REG(0x6e), |
| READ_FRC_REG(FRC_REG_INP_HS_DBG1), |
| READ_FRC_REG(FRC_REG_INP_HS_DBG2), |
| READ_FRC_REG(FRC_REG_INP_HS_DBG3)); |
| pr_frc(log, "%s chk INP_MCDW_CTRL=0x%x, MCDW_CTRL=0x%x\n", |
| __func__, |
| READ_FRC_REG(FRC_INP_MCDW_CTRL), |
| READ_FRC_REG(FRC_MCDW_PATH_CTRL)); |
| } |
| switch (cur_state) { |
| case FRC_STATE_DISABLE: |
| if (state_changed) { |
| if (new_state == FRC_STATE_BYPASS) { |
| set_frc_bypass(ON); |
| schedule_work(&devp->frc_secure_work); |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } else if (new_state == FRC_STATE_ENABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR && |
| devp->buf.cma_mem_alloced) { |
| // frc_mm_secure_set(devp); |
| // frc_clr_badedit_effect_before_enable(); |
| schedule_work(&devp->frc_secure_work); |
| get_vout_info(devp); |
| frc_hw_initial(devp); |
| //first : set bypass off |
| set_frc_bypass(OFF); |
| read0x60 = READ_FRC_REG(FRC_REG_TOP_RESERVE0) & 0xFF; |
| bypasscnt = (read0x60 & 0xfff0) >> 4; |
| freezecnt = read0x60 & 0x0f; |
| // frc_get_film_base_vf(devp); |
| // if (freezecnt < (pfw_data->frc_top_type.vfp & 0x0f)) |
| // freezecnt = pfw_data->frc_top_type.vfp & 0x0f; |
| // else |
| // pfw_data->frc_top_type.vfp |= (freezecnt & 0x0f); |
| if (pfw_data->frc_input_cfg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| //second: set frc enable on |
| frc_memc_clr_vbuffer(devp, 1); |
| set_frc_enable(ON); |
| // devp->frc_fw_pause = 0; |
| pr_frc(log, "frc_bypass_cnt:%d,freeze_cnt:%d\n", |
| bypasscnt, freezecnt); |
| devp->frc_sts.frame_cnt++; |
| } |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt < bypasscnt) { |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| if (devp->frc_sts.frame_cnt == bypasscnt && is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| } else if (devp->frc_sts.frame_cnt == bypasscnt) { |
| if (!is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 1) { |
| forceidx = frc_frame_forcebuf_enable(1); |
| frc_frame_forcebuf_count(forceidx); |
| if (chg_flag == 0) |
| frc_memc_120hz_patch_2(devp); |
| pr_frc(log, "d-e_freeze idx:%d, frm:%d, chg:%d\n", |
| forceidx, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + 1 && |
| devp->frc_sts.frame_cnt < |
| freezecnt + bypasscnt + 1) { |
| frc_frame_forcebuf_count(forceidx); |
| if (devp->frc_sts.frame_cnt == chg_flag + bypasscnt + 1) |
| frc_memc_120hz_patch_2(devp); |
| frc_input_fid = |
| READ_FRC_REG(FRC_REG_PAT_POINTER) >> 4 & 0xF; |
| pr_frc(log, "d-e_freezing readidx:%d, frm:%d, chg:%d\n", |
| frc_input_fid, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == |
| freezecnt + bypasscnt + 1) { |
| frc_frame_forcebuf_enable(0); |
| frc_memc_120hz_patch_3(devp); |
| frc_memc_clr_vbuffer(devp, 0); |
| pr_frc(log, "d-e_freezed to open, frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| // frc_state_change_finish(devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (frc_check_film_mode(devp) != 0 || off2on_cnt > 29) { |
| pr_frc(log, "d-e_stat_chg %s -> %s[%d] done, used_frm:%d[%d]\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state], |
| frc_check_film_mode(devp), |
| off2on_cnt, |
| devp->frc_sts.frame_cnt); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + freezecnt + 1 && |
| (frc_check_film_mode(devp) == 0)) { |
| pr_frc(log, "d-e_detecting film[%d], frm: %d\n", |
| frc_check_film_mode(devp), |
| devp->frc_sts.frame_cnt); |
| off2on_cnt++; |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| case FRC_STATE_ENABLE: |
| if (state_changed) { |
| if (new_state == FRC_STATE_DISABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| schedule_work(&devp->frc_secure_work); |
| frc_frame_forcebuf_enable(0); |
| // devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| frc_clr_badedit_effect_before_enable(); |
| devp->frc_sts.frame_cnt++; |
| } else { |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else if (new_state == FRC_STATE_BYPASS) { |
| //first frame set enable off |
| if (devp->frc_sts.frame_cnt == 0) { |
| schedule_work(&devp->frc_secure_work); |
| frc_frame_forcebuf_enable(0); |
| // devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| frc_clr_badedit_effect_before_enable(); |
| devp->frc_sts.frame_cnt++; |
| } else { |
| //second frame set bypass on |
| set_frc_bypass(ON); |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s->%s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| case FRC_STATE_BYPASS: |
| if (state_changed) { |
| if (new_state == FRC_STATE_DISABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR) { |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| set_frc_bypass(OFF); |
| // devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else if (new_state == FRC_STATE_ENABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR && |
| devp->buf.cma_mem_alloced) { |
| //first frame set bypass off |
| // frc_clr_badedit_effect_before_enable(); |
| schedule_work(&devp->frc_secure_work); |
| frc_memc_clr_vbuffer(devp, 1); |
| get_vout_info(devp); |
| frc_hw_initial(devp); |
| set_frc_bypass(OFF); |
| devp->frc_sts.frame_cnt++; |
| } |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 1) { |
| //second frame set enable on |
| read0x60 = READ_FRC_REG(FRC_REG_TOP_RESERVE0) & 0xFF; |
| bypasscnt = (read0x60 & 0xfff0) >> 4; |
| freezecnt = read0x60 & 0x0f; |
| // frc_get_film_base_vf(devp); |
| // if (freezecnt < (pfw_data->frc_top_type.vfp & 0x0f)) |
| // freezecnt = pfw_data->frc_top_type.vfp & 0x0f; |
| // else |
| // pfw_data->frc_top_type.vfp |= (freezecnt & 0x0f); |
| if (pfw_data->frc_input_cfg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| // devp->frc_fw_pause = 0; |
| set_frc_enable(ON); |
| pr_frc(log, "frc_bypass_cnt:%d,freeze_cnt:%d", |
| bypasscnt, freezecnt); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt < bypasscnt + 1) { |
| pr_frc(log, "b-e_bypassing frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| if (devp->frc_sts.frame_cnt > bypasscnt && is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 1) { |
| if (!is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 2) { |
| // frc_memc_120hz_patch_3(devp); |
| forceidx = frc_frame_forcebuf_enable(1); |
| frc_frame_forcebuf_count(forceidx); |
| if (chg_flag == 0) |
| frc_memc_120hz_patch_2(devp); |
| pr_frc(log, "b-e_freeze start, rd_idx:%d, frm:%d, chg:%d\n", |
| forceidx, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + 2 && |
| devp->frc_sts.frame_cnt < |
| bypasscnt + freezecnt + 2) { |
| frc_frame_forcebuf_count(forceidx); |
| if (devp->frc_sts.frame_cnt == chg_flag + bypasscnt + 2) |
| frc_memc_120hz_patch_2(devp); |
| frc_input_fid = |
| READ_FRC_REG(FRC_REG_PAT_POINTER) >> 4 & 0xF; |
| pr_frc(log, "b-e_freezing readidx %d, frm: %d, chg:%d\n", |
| frc_input_fid, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == |
| bypasscnt + freezecnt + 2) { |
| frc_frame_forcebuf_enable(0); |
| frc_memc_120hz_patch_3(devp); |
| frc_memc_clr_vbuffer(devp, 0); |
| pr_frc(log, "b-e_freezed to open, frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| // frc_state_change_finish(devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (frc_check_film_mode(devp) != 0 || devp->frc_sts.frame_cnt > 29) { |
| pr_frc(log, "b-e_stat_chg %s -> %s[%d] done, used frm:%d[%d]\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state], |
| frc_check_film_mode(devp), |
| off2on_cnt, |
| devp->frc_sts.frame_cnt); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + freezecnt + 2 && |
| (frc_check_film_mode(devp) == 0)) { |
| pr_frc(log, "b-e_detecting film[%d], frm: %d\n", |
| frc_check_film_mode(devp), |
| devp->frc_sts.frame_cnt); |
| off2on_cnt++; |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| |
| default: |
| pr_frc(0, "err state %d\n", cur_state); |
| break; |
| } |
| } |
| |
| void frc_state_handle_new(struct frc_dev_s *devp) |
| { |
| enum frc_state_e cur_state; |
| enum frc_state_e new_state; |
| struct frc_fw_data_s *pfw_data; |
| u32 state_changed = 0; |
| u32 frame_cnt = 0; |
| u32 vframe_idx = 0; |
| static u8 forceidx; |
| static u8 bypasscnt; |
| static u8 freezecnt; |
| static u8 off2on_cnt; |
| u8 frc_input_fid = 0; |
| u32 read0x60 = 0; |
| u8 chg_flag = 0; |
| u8 log = 1; |
| |
| u32 tmp_frm_size; |
| enum chip_id chip; |
| struct frc_top_type_s *frc_top; |
| |
| chip = get_chip_type(); |
| |
| cur_state = devp->frc_sts.state; |
| new_state = devp->frc_sts.new_state; |
| frame_cnt = devp->frc_sts.frame_cnt; |
| chg_flag = devp->ud_dbg.res2_time_en; |
| vframe_idx = devp->in_sts.vf_index; |
| // reg_0x113 = READ_FRC_REG(FRC_REG_OUT_FID); |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| frc_top = &pfw_data->frc_top_type; |
| if (cur_state != new_state) { |
| state_changed = 1; |
| pr_frc(log, "stat_chg(%d->%d), frm_cnt:%d, vd_frm:%d\n", cur_state, |
| new_state, frame_cnt, vframe_idx); |
| if (chg_flag < 0x1F && frame_cnt < 30 && |
| devp->clk_state == FRC_CLOCK_NOR) { |
| pr_frc(log, "frm:%d,reg_0x102:0x%8X,0x113:0x%8X,0x146:0x%8X,0x147:0x%8X\n", |
| frame_cnt, |
| READ_FRC_REG(FRC_REG_PAT_POINTER), |
| READ_FRC_REG(FRC_REG_OUT_FID), |
| READ_FRC_REG(FRC_REG_FWD_PHS), |
| READ_FRC_REG(FRC_REG_FWD_FID)); |
| pr_frc(2, "0x3217 = %x 0x1d21 = %x 0x3218 = %x 0x35 = %x\n", |
| vpu_reg_read(0x3217), vpu_reg_read(0x1d21), |
| vpu_reg_read(0x3218), READ_FRC_REG(FRC_REG_OUT_INT_FLAG)); |
| pr_frc(2, "0x3f05 = %x\n", READ_FRC_REG(FRC_FRAME_SIZE)); |
| pr_frc(2, "%s chk INP_MCDW=0x%x,MCDW_CTRL=0x%x, SRCH_RNG_MODE=%x\n", |
| __func__, |
| READ_FRC_REG(FRC_INP_MCDW_CTRL), |
| READ_FRC_REG(FRC_MCDW_PATH_CTRL), |
| READ_FRC_REG(FRC_SRCH_RNG_MODE) |
| ); |
| } |
| } |
| switch (cur_state) { |
| case FRC_STATE_DISABLE: |
| if (state_changed) { |
| if (new_state == FRC_STATE_BYPASS) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| schedule_work(&devp->frc_secure_work); |
| devp->frc_sts.frame_cnt = 0; |
| /*notify vpu bypass frc default:0 bypass_frc:1 not_bypass_frc:2*/ |
| // devp->need_bypass = 1; |
| set_frc_bypass(ON); |
| devp->frc_sts.frame_cnt++; |
| } else { |
| devp->need_bypass = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } |
| } else if (new_state == FRC_STATE_ENABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR && |
| devp->buf.cma_mem_alloced) { |
| devp->frc_sts.frame_cnt++; |
| // devp->need_bypass = 2; |
| // frc_clr_badedit_effect_before_enable(); |
| } |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 1) { |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| // frc_mm_secure_set(devp); |
| schedule_work(&devp->frc_secure_work); |
| get_vout_info(devp); |
| frc_hw_initial(devp); |
| //first : set bypass off |
| read0x60 = READ_FRC_REG(FRC_REG_TOP_RESERVE0) & 0xFFFF; |
| bypasscnt = (read0x60 & 0xfff0) >> 4; |
| freezecnt = read0x60 & 0xf; |
| //frc_get_film_base_vf(devp); |
| if (pfw_data->frc_input_cfg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| //second: set frc enable on |
| frc_memc_clr_vbuffer(devp, 1); |
| frc_win_align_set(devp, 1); |
| frc_win_size_align(); |
| set_frc_enable(ON); |
| // devp->frc_fw_pause = 0; |
| pr_frc(log, "frc_bypass_cnt:%d,freeze_cnt:%d\n", |
| bypasscnt, freezecnt); |
| devp->st_change = 1; |
| // devp->need_bypass = 0; |
| } else if (devp->frc_sts.frame_cnt == 2) { |
| if (devp->in_sts.t3x_proc_size_chg) { |
| frc_input_init(devp, frc_top); |
| tmp_frm_size = frc_top->hsize; |
| tmp_frm_size |= (frc_top->vsize) << 16; |
| FRC_RDMA_WR_REG_IN(FRC_FRAME_SIZE, tmp_frm_size); |
| } |
| devp->st_change = 3; |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 3) { |
| pr_frc(2, "post 0x3f05 = %x\n", READ_FRC_REG(FRC_FRAME_SIZE)); |
| |
| if (pfw_data->frc_input_cfg && devp->in_sts.t3x_proc_size_chg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt < bypasscnt) { |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| if (devp->frc_sts.frame_cnt == bypasscnt && is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| } else if (devp->frc_sts.frame_cnt == bypasscnt) { |
| if (!is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 1) { |
| forceidx = frc_frame_forcebuf_enable(1); |
| frc_frame_forcebuf_count(forceidx); |
| if (chg_flag == 0) |
| frc_memc_120hz_patch_2(devp); |
| pr_frc(log, "d-e_freeze idx:%d, frm:%d, chg:%d\n", |
| forceidx, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + 1 && |
| devp->frc_sts.frame_cnt < |
| freezecnt + bypasscnt + 1) { |
| frc_frame_forcebuf_count(forceidx); |
| if (devp->frc_sts.frame_cnt == chg_flag + bypasscnt + 1) |
| frc_memc_120hz_patch_2(devp); |
| frc_input_fid = |
| READ_FRC_REG(FRC_REG_PAT_POINTER) >> 4 & 0xF; |
| pr_frc(log, "d-e_freezing readidx:%d, frm:%d, chg:%d\n", |
| frc_input_fid, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == |
| freezecnt + bypasscnt + 1) { |
| frc_frame_forcebuf_enable(0); |
| frc_memc_120hz_patch_3(devp); |
| frc_memc_clr_vbuffer(devp, 0); |
| pr_frc(log, "d-e_freezed to open, frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| // frc_state_change_finish(devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (frc_check_film_mode(devp) != 0 || off2on_cnt > 29) { |
| pr_frc(log, "d-e_stat_chg %s -> %s[%d] done, used_frm:%d[%d]\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state], |
| frc_check_film_mode(devp), |
| off2on_cnt, |
| devp->frc_sts.frame_cnt); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + freezecnt + 1 && |
| (frc_check_film_mode(devp) == 0)) { |
| pr_frc(log, "d-e_detecting film[%d], frm: %d\n", |
| frc_check_film_mode(devp), |
| devp->frc_sts.frame_cnt); |
| off2on_cnt++; |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| case FRC_STATE_ENABLE: |
| if (state_changed) { |
| if (new_state == FRC_STATE_DISABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| schedule_work(&devp->frc_secure_work); |
| frc_frame_forcebuf_enable(0); |
| //devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| frc_clr_badedit_effect_before_enable(); |
| devp->st_change = 2; |
| devp->frc_sts.frame_cnt++; |
| } else { |
| devp->frc_sts.frame_cnt = 0; |
| devp->st_change = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else if (new_state == FRC_STATE_BYPASS) { |
| //first frame set enable off |
| if (devp->frc_sts.frame_cnt == 0) { |
| schedule_work(&devp->frc_secure_work); |
| frc_frame_forcebuf_enable(0); |
| //devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| // devp->need_bypass = 1; |
| set_frc_bypass(ON); |
| frc_clr_badedit_effect_before_enable(); |
| devp->st_change = 2; |
| devp->frc_sts.frame_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 1) { |
| devp->st_change = 0; |
| devp->need_bypass = 0; |
| devp->frc_sts.frame_cnt++; |
| } else { |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s->%s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| case FRC_STATE_BYPASS: |
| if (state_changed) { |
| if (new_state == FRC_STATE_DISABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR) { |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| set_frc_bypass(OFF); |
| //devp->frc_fw_pause = 1; |
| set_frc_enable(OFF); |
| devp->frc_sts.frame_cnt = 0; |
| pr_frc(log, "stat_chg %s -> %s done\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state]); |
| frc_state_change_finish(devp); |
| } |
| } else if (new_state == FRC_STATE_ENABLE) { |
| if (devp->frc_sts.frame_cnt == 0) { |
| if (devp->clk_state != FRC_CLOCK_NOR && |
| devp->clk_state != FRC_CLOCK_XXX2NOR) { |
| devp->clk_state = FRC_CLOCK_XXX2NOR; |
| schedule_work(&devp->frc_clk_work); |
| } else if (devp->clk_state == FRC_CLOCK_NOR && |
| devp->buf.cma_mem_alloced) { |
| //first frame set bypass off |
| set_frc_bypass(OFF); |
| devp->frc_sts.frame_cnt++; |
| // frc_clr_badedit_effect_before_enable(); |
| } |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 1) { |
| schedule_work(&devp->frc_secure_work); |
| frc_memc_clr_vbuffer(devp, 1); |
| get_vout_info(devp); |
| frc_hw_initial(devp); |
| //second frame set enable on |
| read0x60 = READ_FRC_REG(FRC_REG_TOP_RESERVE0) & 0xFFFF; |
| bypasscnt = (read0x60 & 0xfff0) >> 4; |
| freezecnt = read0x60 & 0x0f; |
| //frc_get_film_base_vf(devp); |
| if (pfw_data->frc_input_cfg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| //devp->frc_fw_pause = 0; |
| if (devp->out_sts.out_framerate > 90) { |
| frc_win_align_set(devp, 1); |
| frc_win_size_align(); |
| } |
| set_frc_enable(ON); |
| devp->st_change = 1; |
| devp->need_bypass = 0; |
| pr_frc(log, "frc_bypass_cnt:%d,freeze_cnt:%d", |
| bypasscnt, freezecnt); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 2) { |
| if (devp->in_sts.t3x_proc_size_chg) { |
| frc_input_init(devp, frc_top); |
| tmp_frm_size = frc_top->hsize; |
| tmp_frm_size |= (frc_top->vsize) << 16; |
| FRC_RDMA_WR_REG_IN(FRC_FRAME_SIZE, tmp_frm_size); |
| pr_frc(log, "t3x_proc_size:(%d,%d)", |
| frc_top->hsize, frc_top->vsize); |
| } |
| devp->st_change = 3; |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == 3) { |
| if (pfw_data->frc_input_cfg && devp->in_sts.t3x_proc_size_chg) |
| pfw_data->frc_input_cfg(devp->fw_data); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt < bypasscnt + 1) { |
| pr_frc(log, "b-e_bypassing frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| if (devp->frc_sts.frame_cnt > bypasscnt && is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 1) { |
| if (!is_rdma_enable()) |
| t3x_verB_set_cfg(1, devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == bypasscnt + 2) { |
| // frc_memc_120hz_patch_3(devp); |
| forceidx = frc_frame_forcebuf_enable(1); |
| frc_frame_forcebuf_count(forceidx); |
| if (chg_flag == 0) |
| frc_memc_120hz_patch_2(devp); |
| pr_frc(log, "b-e_freeze start, rd_idx:%d, frm:%d, chg:%d\n", |
| forceidx, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + 2 && |
| devp->frc_sts.frame_cnt < |
| bypasscnt + freezecnt + 2) { |
| frc_frame_forcebuf_count(forceidx); |
| if (devp->frc_sts.frame_cnt == chg_flag + bypasscnt + 2) |
| frc_memc_120hz_patch_2(devp); |
| frc_input_fid = |
| READ_FRC_REG(FRC_REG_PAT_POINTER) >> 4 & 0xF; |
| pr_frc(log, "b-e_freezing readidx %d, frm: %d, chg:%d\n", |
| frc_input_fid, devp->frc_sts.frame_cnt, chg_flag); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (devp->frc_sts.frame_cnt == |
| bypasscnt + freezecnt + 2) { |
| frc_frame_forcebuf_enable(0); |
| frc_memc_120hz_patch_3(devp); |
| frc_memc_clr_vbuffer(devp, 0); |
| pr_frc(log, "b-e_freezed to open, frm:%d\n", |
| devp->frc_sts.frame_cnt); |
| // frc_state_change_finish(devp); |
| devp->frc_sts.frame_cnt++; |
| off2on_cnt++; |
| } else if (frc_check_film_mode(devp) != 0 || devp->frc_sts.frame_cnt > 29) { |
| pr_frc(log, "b-e_stat_chg %s -> %s[%d] done, used frm:%d[%d]\n", |
| frc_state_ary[cur_state], |
| frc_state_ary[new_state], |
| frc_check_film_mode(devp), |
| off2on_cnt, |
| devp->frc_sts.frame_cnt); |
| frc_state_change_finish(devp); |
| off2on_cnt = 0; |
| } else if (devp->frc_sts.frame_cnt > bypasscnt + freezecnt + 2 && |
| (frc_check_film_mode(devp) == 0)) { |
| pr_frc(log, "b-e_detecting film[%d], frm: %d\n", |
| frc_check_film_mode(devp), |
| devp->frc_sts.frame_cnt); |
| off2on_cnt++; |
| devp->frc_sts.frame_cnt++; |
| } |
| } else { |
| pr_frc(0, "err new state %d\n", new_state); |
| } |
| } |
| break; |
| |
| default: |
| pr_frc(0, "err state %d\n", cur_state); |
| break; |
| } |
| } |
| |
| int frc_memc_set_level(u8 level) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pr_frc(1, "set_memc_level:%d\n", level); |
| if (level != pfw_data->frc_top_type.frc_memc_level) { |
| pfw_data->frc_top_type.frc_memc_level = level; |
| if (pfw_data->frc_memc_level) |
| pfw_data->frc_memc_level(pfw_data); |
| } |
| return 1; |
| } |
| |
| int frc_fpp_memc_set_level(u8 level, u8 num) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| int flag = 0; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return 0; |
| pr_frc(1, "fpp_set_memc_level:%d[%d]\n", level, num); |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| if (level != pfw_data->frc_top_type.frc_memc_level) { |
| pfw_data->frc_top_type.frc_memc_level = level; |
| flag = 1; |
| } |
| if (num != pfw_data->frc_top_type.frc_memc_level_1) { |
| pfw_data->frc_top_type.frc_memc_level_1 = num; |
| flag = 1; |
| } |
| if (pfw_data->frc_memc_level && flag) |
| pfw_data->frc_memc_level(pfw_data); |
| return 1; |
| } |
| |
| int frc_lge_memc_set_level(struct v4l2_ext_memc_motion_comp_info comp_info) |
| { |
| u8 memc_type; |
| u32 judder_level = 0; |
| unsigned char temp_level[1]; |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| memc_type = (u8)comp_info.memc_type; |
| |
| pr_frc(1, "comp_info.memc_type:%d, judder_level:%d, blur_level:%d\n", |
| (u8)comp_info.memc_type, comp_info.judder_level, comp_info.blur_level); |
| |
| if (memc_type == V4L2_EXT_MEMC_OFF) { |
| pfw_data->frc_top_type.frc_memc_level = 0; // off |
| } else if (memc_type == V4L2_EXT_MEMC_NATURAL) { |
| pfw_data->frc_top_type.frc_memc_level = 6; // low level |
| } else if (memc_type == V4L2_EXT_MEMC_SMOOTH) { |
| pfw_data->frc_top_type.frc_memc_level = 10; // mid level |
| } else if (memc_type == V4L2_EXT_MEMC_CINEMA_CLEAR) { |
| pfw_data->frc_top_type.frc_memc_level = 3; // mid level |
| } else if (memc_type == V4L2_EXT_MEMC_TYPE_USER) { |
| temp_level[0] = comp_info.judder_level; |
| if (kstrtoint(temp_level, 10, &judder_level) == 0) { |
| // char type |
| if (judder_level <= 10) |
| pfw_data->frc_top_type.frc_memc_level = judder_level; |
| else |
| pr_frc(0, "ioc memc-level char-value is unsupported\n"); |
| } else { |
| // int type |
| judder_level = comp_info.judder_level; |
| if (judder_level <= 10) |
| pfw_data->frc_top_type.frc_memc_level = judder_level; |
| else |
| pr_frc(0, "ioc memc-level int-value is unsupported\n"); |
| } |
| } else if (memc_type == V4L2_EXT_MEMC_TYPE_55_PULLDOWN) { |
| pr_frc(1, "24p film mode\n"); |
| // need to discuss |
| } |
| |
| pr_frc(1, "ioc lge_set_memc_level:%d\n", |
| pfw_data->frc_top_type.frc_memc_level); |
| if (pfw_data->frc_memc_level) |
| pfw_data->frc_memc_level(pfw_data); |
| |
| return 0; |
| } |
| |
| void frc_lge_memc_get_level(struct v4l2_ext_memc_motion_comp_info *comp_info) |
| { |
| enum v4l2_ext_memc_type memc_type; |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| |
| if (pfw_data->frc_top_type.frc_memc_level == 0) { |
| memc_type = (enum v4l2_ext_memc_type)V4L2_EXT_MEMC_OFF; |
| } else if (pfw_data->frc_top_type.frc_memc_level == 3) { |
| memc_type = (enum v4l2_ext_memc_type)V4L2_EXT_MEMC_CINEMA_CLEAR; |
| } else if (pfw_data->frc_top_type.frc_memc_level == 6) { |
| memc_type = (enum v4l2_ext_memc_type)V4L2_EXT_MEMC_NATURAL; |
| } else if (pfw_data->frc_top_type.frc_memc_level == 10) { |
| memc_type = (enum v4l2_ext_memc_type)V4L2_EXT_MEMC_SMOOTH; |
| } else { |
| //user setting |
| memc_type = (enum v4l2_ext_memc_type)V4L2_EXT_MEMC_TYPE_USER; |
| } |
| comp_info->memc_type = memc_type; |
| comp_info->judder_level = '1'; |
| comp_info->blur_level = '1'; |
| } |
| |
| void frc_lge_memc_init(void) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| |
| // reserve frc buf init |
| |
| //frc status and fw_pause ready |
| // devp->frc_fw_pause = true; |
| devp->frc_sts.auto_ctrl = true; |
| frc_change_to_state(FRC_STATE_ENABLE); |
| // devp->frc_sts.re_config = true; |
| pr_frc(0, "frc lge memc init done\n"); |
| } |
| |
| int frc_memc_set_deblur(u8 level) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| // struct frc_fw_alg_ctrl_s *pfrc_fw_alg_ctrl; |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pr_frc(1, "set_deblur_level:%d\n", level); |
| if (level != pfw_data->frc_top_type.frc_deblur_level) { |
| pfw_data->frc_top_type.frc_deblur_level = level; |
| if (pfw_data->frc_memc_level) |
| pfw_data->frc_memc_level(pfw_data); |
| } |
| return 1; |
| } |
| |
| int frc_memc_set_demo(u8 setdemo) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| u32 tmpstart = 0, tmpend = 0; |
| |
| if (!devp) |
| return 0; |
| if (!devp->probe_ok) |
| return 0; |
| if (!devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pr_frc(1, "set_demo_mode:%d\n", setdemo); |
| pr_frc(1, "in_hsize:%4d\n", pfw_data->frc_top_type.hsize); |
| pr_frc(1, "in_vsize:%4d\n", pfw_data->frc_top_type.vsize); |
| pr_frc(1, "out_hsize:%4d\n", pfw_data->frc_top_type.out_hsize); |
| pr_frc(1, "out_vsize:%4d\n", pfw_data->frc_top_type.out_vsize); |
| if (setdemo == 0) { |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0, 3, 1); |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0, 17, 1); |
| } else if (setdemo < 3) { |
| tmpstart = pfw_data->frc_top_type.hsize / 2 << 16; |
| pr_frc(1, "demo_win_start:%4d\n", tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, tmpstart); |
| tmpend = ((pfw_data->frc_top_type.hsize - 1) << 16) + |
| (pfw_data->frc_top_type.vsize - 1); |
| pr_frc(1, "demo_win_end:%4d\n", tmpend); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, (setdemo - 1), 17, 1); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 1, 3, 1); |
| } else if (setdemo < 5) { |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, 0); |
| tmpend = ((pfw_data->frc_top_type.hsize / 2 - 1) << 16) + |
| (pfw_data->frc_top_type.vsize - 1); |
| pr_frc(1, "demo_win_end:%4d\n", tmpend); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, (setdemo - 3), 17, 1); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 1, 3, 1); |
| } |
| return 1; |
| } |
| |
| int frc_init_out_line(void) |
| { |
| u32 vfb = 0; |
| enum chip_id chip; |
| |
| chip = get_chip_type(); |
| if (chip == ID_T3X) |
| vfb = (vpu_reg_read(ENCL_VIDEO_VAVON_BLINE_T3X) >> 16) & 0xffff; |
| else |
| vfb = vpu_reg_read(ENCL_VIDEO_VAVON_BLINE); |
| |
| if (vfb > 0 && vfb < 120) { // need more check 500 is correct or not |
| vfb = (vfb / 4) * 3; // 3/4 point of front vblank, default |
| } else { |
| vfb = 51; |
| PR_ERR("%s read back vfb:%d\n", __func__, vfb); |
| } |
| |
| return vfb; |
| } |
| |
| void frc_vpp_vs_ir_chk_film(struct frc_dev_s *frc_devp) |
| { |
| if (!frc_devp->probe_ok || !frc_devp->power_on_flag) |
| return; |
| if (frc_devp->ud_dbg.res0_dbg_en == 1) { |
| if (!frc_devp->frc_fw_pause) |
| frc_devp->frc_fw_pause = 1; |
| pr_frc(6, "vscnt=%7d, glb=%10d, cntglb=%7d\n", |
| frc_devp->frc_sts.vs_cnt, |
| READ_FRC_REG(FRC_FD_DIF_GL), |
| READ_FRC_REG(FRC_FD_DIF_COUNT_GL)); |
| } // restore prev setting ,need first set fw_pause=0 by |
| // echo frc_pause 0 > /sys/class/frc/debug |
| } |
| |
| int frc_tell_alg_vendor(u8 vendor_info) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_alg_ctrl_s *pfrc_fw_alg_ctrl; |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp) |
| return 0; |
| if (!devp->probe_ok) |
| return 0; |
| if (!devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pfrc_fw_alg_ctrl = (struct frc_fw_alg_ctrl_s *)&pfw_data->frc_fw_alg_ctrl; |
| pr_frc(1, "tell_alg_vendor:0x%x\n", vendor_info); |
| if (pfrc_fw_alg_ctrl->frc_algctrl_u8vendor != vendor_info) |
| pfrc_fw_alg_ctrl->frc_algctrl_u8vendor = vendor_info; |
| // if (pfw_data->frc_fw_ctrl_if) // change to output isr |
| // pfw_data->frc_fw_ctrl_if(pfw_data); |
| return 1; |
| } |
| |
| int frc_set_memc_fallback(u8 fbvale) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_alg_ctrl_s *pfrc_fw_alg_ctrl; |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp) |
| return 0; |
| if (!devp->probe_ok) |
| return 0; |
| if (!devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pfrc_fw_alg_ctrl = (struct frc_fw_alg_ctrl_s *)&pfw_data->frc_fw_alg_ctrl; |
| pr_frc(1, "set mc fallback:0x%x\n", fbvale); |
| pfrc_fw_alg_ctrl->frc_algctrl_u8mcfb = (fbvale > 20) ? 20 : fbvale; |
| if (pfw_data->frc_fw_ctrl_if) |
| pfw_data->frc_fw_ctrl_if(pfw_data); |
| return 1; |
| } |
| |
| int frc_set_film_support(u32 filmcnt) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_alg_ctrl_s *pfrc_fw_alg_ctrl; |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp) |
| return 0; |
| if (!devp->probe_ok) |
| return 0; |
| if (!devp->fw_data) |
| return 0; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| pfrc_fw_alg_ctrl = (struct frc_fw_alg_ctrl_s *)&pfw_data->frc_fw_alg_ctrl; |
| pr_frc(1, "set support film:0x%x\n", filmcnt); |
| pfrc_fw_alg_ctrl->frc_algctrl_u32film = filmcnt; |
| if (pfw_data->frc_fw_ctrl_if) |
| pfw_data->frc_fw_ctrl_if(pfw_data); |
| return 1; |
| } |
| |
| static int notify_frc_signal_to_amvideo(int *char_flash_check) |
| { |
| static int pre_char_flash_check; |
| |
| //#ifdef CONFIG_AMLOGIC_MEDIA_VIDEO |
| if (pre_char_flash_check != *char_flash_check) { |
| pr_frc(2, "char_flash_check = %d\n", *char_flash_check); |
| pre_char_flash_check = *char_flash_check; |
| amvideo_notifier_call_chain |
| (AMVIDEO_UPDATE_FRC_CHAR_FLASH, |
| (void *)char_flash_check); |
| } |
| //#endif |
| return 0; |
| } |
| |
| // fix frc char flashing |
| void frc_char_flash_check(void) |
| { |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| static u16 match_count; |
| // int char_flash_check; |
| int temp, temp2; |
| |
| if (!devp || !devp->probe_ok || !devp->fw_data) |
| return; |
| if (devp->in_sts.high_freq_en) { |
| if (devp->in_sts.high_freq_flash) { |
| char_flash_check = 0; |
| devp->in_sts.high_freq_flash = char_flash_check; |
| notify_frc_signal_to_amvideo(&char_flash_check); |
| } |
| return; |
| } |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| /*4K input/output && memc on && glb_motion && hist*/ |
| if (pfw_data->frc_top_type.hsize == 3840 && |
| pfw_data->frc_top_type.vsize == 2160 && |
| devp->frc_sts.state == 1) { |
| temp = READ_FRC_REG(FRC_BBD_RO_MAX1_HIST_CNT); |
| temp2 = READ_FRC_REG(FRC_BBD_RO_MAX2_HIST_CNT); |
| temp = temp + temp2; |
| if ((temp > MIN_HIST1 && temp < MAX_HIST1) || |
| (temp > MIN_HIST2 && temp < MAX_HIST2)) { |
| match_count++; |
| if (match_count > LIMIT * 2) |
| match_count = LIMIT * 2; |
| } else { |
| match_count--; |
| if (match_count < 1) |
| match_count = 1; |
| } |
| |
| if (match_count > LIMIT) |
| char_flash_check = 1; |
| else |
| char_flash_check = 0; |
| devp->in_sts.high_freq_flash = char_flash_check; |
| notify_frc_signal_to_amvideo(&char_flash_check); |
| } |
| } |
| |
| /* |
| * input vf devp |
| * output status(is tvin? source changed? fps) |
| */ |
| void frc_chk_vd_sts_chg(struct frc_dev_s *devp, struct vframe_s *vf) |
| { |
| static u8 frc_is_tvin_s, frc_source_chg_s; |
| struct frc_fw_data_s *pfw_data; |
| bool vlock_locked; |
| |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| |
| if (!vf) |
| return; |
| if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI || |
| vf->source_type == VFRAME_SOURCE_TYPE_CVBS || |
| vf->source_type == VFRAME_SOURCE_TYPE_TUNER) |
| devp->in_sts.frc_is_tvin = true; |
| else |
| devp->in_sts.frc_is_tvin = false; |
| |
| if (frc_is_tvin_s != devp->in_sts.frc_is_tvin) { |
| frc_is_tvin_s = devp->in_sts.frc_is_tvin; |
| if (devp->in_sts.frc_is_tvin) { |
| WRITE_FRC_BITS(FRC_TOP_MISC_CTRL, 1, 0, 1); |
| WRITE_FRC_BITS(FRC_REG_TOP_CTRL25, 0, 31, 1); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, 0); |
| } |
| pr_frc(1, "input change %d. (1:tvin)\n", frc_is_tvin_s); |
| } |
| |
| // close pps optimize in tvin |
| if (devp->in_sts.frc_is_tvin && char_flash_check) { |
| char_flash_check = 0; |
| devp->in_sts.high_freq_flash = char_flash_check; |
| notify_frc_signal_to_amvideo(&char_flash_check); |
| } |
| |
| if (vf->vc_private) { |
| if (vf->vc_private->flag & VC_FLAG_FIRST_FRAME) |
| devp->in_sts.frc_source_chg = true; |
| else |
| devp->in_sts.frc_source_chg = false; |
| |
| if (frc_source_chg_s != devp->in_sts.frc_source_chg) { |
| pr_frc(1, "input source change [%d->%d]. (1:changed)\n", |
| frc_source_chg_s, devp->in_sts.frc_source_chg); |
| frc_source_chg_s = devp->in_sts.frc_source_chg; |
| } |
| } |
| |
| if (frc_source_chg_s != devp->in_sts.frc_source_chg) { |
| pr_frc(1, "input source change [%d->%d]. (1:changed)\n", |
| frc_source_chg_s, devp->in_sts.frc_source_chg); |
| frc_source_chg_s = devp->in_sts.frc_source_chg; |
| } |
| |
| if (vf->vc_private) { |
| pr_frc(6, "last vf disp vsync count =%d\n", |
| vf->vc_private->last_disp_count); |
| devp->in_sts.frc_last_disp_count = |
| vf->vc_private->last_disp_count; |
| } |
| // every vframe detect frame rate |
| frc_check_vf_rate(vf->duration, devp); |
| |
| if (devp->in_sts.frc_is_tvin) { // hdmi source |
| if (vf->duration == 4000 || vf->duration == 4004) |
| vlock_locked = vlock_get_vlock_flag(); |
| else |
| vlock_locked = vlock_get_phlock_flag() && |
| vlock_get_vlock_flag(); |
| if (vlock_locked) { |
| devp->in_sts.st_flag |= FRC_FLAG_VLOCK_ST; |
| pfw_data->frc_top_type.vfp |= BIT_8; |
| } else { |
| devp->in_sts.st_flag &= (~FRC_FLAG_VLOCK_ST); |
| pfw_data->frc_top_type.vfp &= (~BIT_8); |
| } |
| } |
| } |
| |
| u16 frc_check_film_mode(struct frc_dev_s *frc_devp) |
| { |
| struct frc_fw_data_s *fw_data; |
| struct frc_top_type_s *frc_top; |
| |
| fw_data = (struct frc_fw_data_s *)frc_devp->fw_data; |
| frc_top = &fw_data->frc_top_type; |
| |
| //if (frc_devp->frc_sts.state == FRC_STATE_ENABLE) |
| frc_top->film_mode = READ_FRC_REG(FRC_REG_PHS_TABLE) >> 8 & 0xFF; |
| //else |
| // frc_top->film_mode = EN_DRV_VIDEO; |
| return (u16)(frc_top->film_mode); |
| } |
| |
| // void frc_check_secure_mode(struct vframe_s *vf, struct frc_dev_s *devp) |
| // { |
| // u32 temp; |
| // enum chip_id chip; |
| // static int secure_mode; |
| |
| // chip = get_chip_type(); |
| |
| // if (chip == ID_T3) { |
| // if ((vf->flag & VFRAME_FLAG_VIDEO_SECURE) == |
| // VFRAME_FLAG_VIDEO_SECURE) |
| // devp->in_sts.secure_mode = true; |
| // else |
| // devp->in_sts.secure_mode = false; |
| // } else if (chip == ID_T5M || chip == ID_T3X) { |
| // if (!sec_flag) { |
| // temp = READ_FRC_REG(FRC_RO_FRM_SEC_STAT); |
| // temp = (temp >> 16) & 0xf; // 1: input frame is security |
| // if (temp) |
| // devp->in_sts.secure_mode = true; |
| // else |
| // devp->in_sts.secure_mode = false; |
| // } else { |
| // if ((vf->flag & VFRAME_FLAG_VIDEO_SECURE) == |
| // VFRAME_FLAG_VIDEO_SECURE) |
| // devp->in_sts.secure_mode = true; |
| // else |
| // devp->in_sts.secure_mode = false; |
| // } |
| // } |
| |
| // if (secure_mode != devp->in_sts.secure_mode) { |
| // pr_frc(0, "frc secure sts:%d, sec_flag:%d, chip:%d\n", |
| // devp->in_sts.secure_mode, sec_flag, chip); |
| // secure_mode = devp->in_sts.secure_mode; |
| // } |
| // } |
| |
| void frc_win_align_set(struct frc_dev_s *devp, u8 align_set) |
| { |
| if (!devp) |
| return; |
| if (align_set == devp->ud_dbg.align_dbg_en) |
| return; |
| |
| devp->ud_dbg.align_dbg_en = align_set; |
| |
| if (devp->ud_dbg.align_dbg_en == FRC_WIN_ALIGN_AUTO) { //auto |
| regdata_inpholdctl_0002 = READ_FRC_REG(FRC_INP_HOLD_CTRL); |
| frc_config_reg_value(BIT_20, BIT_20, ®data_inpholdctl_0002); |
| WRITE_FRC_REG_BY_CPU(FRC_INP_HOLD_CTRL, regdata_inpholdctl_0002); |
| WRITE_FRC_BITS(FRC_TOP_MISC_CTRL, 1, 0, 1); |
| WRITE_FRC_BITS(FRC_REG_TOP_CTRL25, 0, 31, 1); |
| } else if (devp->ud_dbg.align_dbg_en == FRC_WIN_ALIGN_MANU) { // manual |
| regdata_inpholdctl_0002 = READ_FRC_REG(FRC_INP_HOLD_CTRL); |
| frc_config_reg_value(BIT_20, BIT_20, ®data_inpholdctl_0002); |
| WRITE_FRC_REG_BY_CPU(FRC_INP_HOLD_CTRL, regdata_inpholdctl_0002); |
| WRITE_FRC_BITS(FRC_TOP_MISC_CTRL, 0, 0, 1); |
| WRITE_FRC_BITS(FRC_REG_TOP_CTRL25, 1, 31, 1); |
| } else if (devp->ud_dbg.align_dbg_en == FRC_WIN_ALIGN_DGB1) { // debug |
| regdata_inpholdctl_0002 = READ_FRC_REG(FRC_INP_HOLD_CTRL); |
| frc_config_reg_value(BIT_20, BIT_20, ®data_inpholdctl_0002); |
| WRITE_FRC_REG_BY_CPU(FRC_INP_HOLD_CTRL, regdata_inpholdctl_0002); |
| } |
| pr_frc(2, "0x2 = %x 0x50 = %x 0x26 = %x\n", READ_FRC_REG(FRC_INP_HOLD_CTRL), |
| READ_FRC_REG(FRC_TOP_MISC_CTRL), READ_FRC_REG(FRC_REG_TOP_CTRL25)); |
| } |
| |
| void frc_win_size_align(void) |
| { |
| u32 tmp_frm_size; |
| u32 tmp_proc_size; |
| u32 shift_bits = 0x1f; |
| u32 mask_bits = ~shift_bits; |
| u32 tmp_ofst_value; |
| enum chip_id chip; |
| struct frc_dev_s *devp; |
| struct frc_top_type_s *frc_top; |
| struct frc_fw_data_s *pfw_data; |
| |
| chip = get_chip_type(); |
| devp = get_frc_devp(); |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| frc_top = &pfw_data->frc_top_type; |
| |
| if (devp->ud_dbg.align_dbg_en == FRC_WIN_ALIGN_AUTO) { |
| if (chip == ID_T3X && devp->in_out_ratio == FRC_RATIO_1_2) { |
| tmp_frm_size = (frc_top->hsize + shift_bits) & mask_bits; |
| tmp_frm_size |= (frc_top->vsize) << 16; |
| } else { |
| tmp_frm_size = frc_top->hsize; |
| tmp_frm_size |= (frc_top->vsize) << 16; |
| } |
| tmp_proc_size = devp->out_sts.vout_width; |
| tmp_proc_size |= (devp->out_sts.vout_height) << 16; |
| |
| tmp_ofst_value = 0; |
| |
| WRITE_FRC_REG_BY_CPU(FRC_FRAME_SIZE, tmp_frm_size); |
| WRITE_FRC_REG_BY_CPU(FRC_PROC_SIZE, tmp_proc_size); |
| if (chip != ID_T3) |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, tmp_ofst_value); |
| } else if (devp->ud_dbg.align_dbg_en == FRC_WIN_ALIGN_MANU) { |
| tmp_proc_size = (devp->in_sts.in_hsize + shift_bits) & mask_bits; |
| tmp_proc_size |= ((devp->in_sts.in_vsize + 0xF) & 0xFFFFFFF0) << 16; |
| // tmp_proc_size |= devp->in_sts.in_vsize << 16; |
| |
| tmp_ofst_value = 0; |
| |
| if (chip == ID_T3X) |
| tmp_ofst_value |= 0 << 13; |
| else if (devp->in_sts.in_hsize & shift_bits) |
| tmp_ofst_value |= (((frc_top->hsize & shift_bits) ^ shift_bits) + 1) << 13; |
| else |
| tmp_ofst_value |= 0 << 13; |
| WRITE_FRC_REG_BY_CPU(FRC_PROC_SIZE, tmp_proc_size); |
| if (chip != ID_T3) |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, tmp_ofst_value); |
| pr_frc(2, "0x51 = %x 0x28 = %x\n", READ_FRC_REG(FRC_PROC_SIZE), |
| READ_FRC_REG(FRC_REG_TOP_CTRL27)); |
| } |
| } |
| |
| void frc_input_size_align_check(struct frc_dev_s *devp) |
| { |
| u8 reg_win_en; |
| u8 reg_auto_align_en; |
| u8 reg_inp_padding_en; |
| u16 in_vsize = 0; |
| u16 in_hsize = 0; |
| |
| /*only for T5M*/ |
| if (get_chip_type() != ID_T5M || devp->in_sts.frc_seamless_en) |
| return; |
| |
| reg_win_en = (READ_FRC_REG(FRC_INP_HOLD_CTRL) >> 20) & 0x1; // bit:20 |
| reg_auto_align_en = READ_FRC_REG(FRC_TOP_MISC_CTRL) & 0x1; // bit:0 |
| reg_inp_padding_en = (READ_FRC_REG(FRC_REG_TOP_CTRL25) >> 31) & 0x1; //bit:31 |
| |
| pr_frc(2, "reg_win_en:%d,reg_auto_align_en:%d,reg_inp_padding_en:%d\n", |
| reg_win_en, reg_auto_align_en, reg_inp_padding_en); |
| pr_frc(2, "in_sts.in_hsize:%d devp->in_sts.in_vsize:%d\n", |
| devp->in_sts.in_hsize, devp->in_sts.in_vsize); |
| pr_frc(2, "devp->out_sts.vout_width:%d devp->out_sts.vout_height:%d\n", |
| devp->out_sts.vout_width, devp->out_sts.vout_height); |
| |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, 0x0); // clear align mothod |
| WRITE_FRC_REG_BY_CPU(FRC_PROC_SIZE, // restore default fhd value |
| (devp->out_sts.vout_height & 0x3fff) << 16 | |
| (devp->out_sts.vout_width & 0x3fff)); |
| |
| if (reg_win_en && reg_auto_align_en && !reg_inp_padding_en) { |
| if (devp->out_sts.vout_width == 1920 && |
| devp->out_sts.vout_height == 1080) { |
| if (devp->in_sts.in_hsize > IN_W_SIZE_FHD_90 && |
| devp->in_sts.in_hsize < devp->out_sts.vout_width && |
| devp->in_sts.in_hsize % 8) |
| in_hsize = 8 - (devp->in_sts.in_hsize % 8); |
| if (devp->in_sts.in_vsize > IN_H_SIZE_FHD_90 && |
| devp->in_sts.in_vsize < devp->out_sts.vout_height && |
| devp->in_sts.in_vsize % 8) |
| in_vsize = 8 - (devp->in_sts.in_vsize % 8); |
| } else if (devp->out_sts.vout_width == 3840 && |
| devp->out_sts.vout_height == 2160) { |
| if (devp->in_sts.in_hsize > IN_W_SIZE_UHD_90 && |
| devp->in_sts.in_hsize < devp->out_sts.vout_width && |
| devp->in_sts.in_hsize % 16) |
| in_hsize = 16 - (devp->in_sts.in_hsize % 16); |
| if (devp->in_sts.in_vsize > IN_H_SIZE_UHD_90 && |
| devp->in_sts.in_vsize < devp->out_sts.vout_height && |
| devp->in_sts.in_vsize % 16) |
| in_vsize = 16 - (devp->in_sts.in_vsize % 16); |
| } |
| WRITE_FRC_REG_BY_CPU(FRC_REG_TOP_CTRL27, |
| (in_hsize & 0x1fff) << 13 | (in_vsize & 0x1ff)); |
| } |
| pr_frc(2, "align_vsize:%d align_hsize:%d\n", in_vsize, in_hsize); |
| } |
| |
| void frc_set_seamless_proc(u32 seamless) |
| { |
| static u32 cur_status; |
| struct frc_dev_s *devp = get_frc_devp(); |
| |
| if (!devp || get_chip_type() == ID_T3 || cur_status == seamless) |
| return; |
| |
| if (devp->frc_sts.state == FRC_STATE_ENABLE) |
| devp->frc_sts.re_config = true; |
| |
| if (seamless) { |
| WRITE_FRC_BITS(FRC_TOP_MISC_CTRL, 0, 0, 1); //auto_align_en |
| WRITE_FRC_BITS(FRC_REG_TOP_CTRL25, 1, 31, 1); //inp_padding_en |
| } else { |
| WRITE_FRC_BITS(FRC_TOP_MISC_CTRL, 1, 0, 1); |
| WRITE_FRC_BITS(FRC_REG_TOP_CTRL25, 0, 31, 1); |
| } |
| devp->in_sts.frc_seamless_en = (u8)seamless; |
| cur_status = seamless; |
| pr_frc(2, "seamless is %d.\n", seamless); |
| } |
| |
| /* Test whether demo window works properly for t3x |
| * input: dome window num (1/2/3/4) |
| * output: number of demo window |
| */ |
| void set_frc_demo_window(u8 demo_num) |
| { |
| u32 tmpstart, tmpend; |
| static u8 demo_style; |
| struct frc_dev_s *devp = get_frc_devp(); |
| struct frc_fw_data_s *pfw_data; |
| |
| if (!devp) |
| return; |
| if (!devp->probe_ok) |
| return; |
| if (!devp->fw_data) |
| return; |
| pfw_data = (struct frc_fw_data_s *)devp->fw_data; |
| |
| if (get_chip_type() == ID_T3X) { |
| if (demo_num == 0) { |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0, 0, 5); |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0, 17, 4); |
| demo_style = 0; |
| } else if (demo_num == 1) { |
| if (!demo_style) { |
| tmpstart = (pfw_data->frc_top_type.hsize / 2) << 16; |
| tmpend = (pfw_data->frc_top_type.hsize) << 16 | |
| pfw_data->frc_top_type.vsize; |
| } else if (demo_style == 1) { |
| tmpstart = 0; |
| tmpend = (pfw_data->frc_top_type.hsize / 2) << 16 | |
| pfw_data->frc_top_type.vsize; |
| } else { |
| tmpstart = (pfw_data->frc_top_type.hsize / 4) << 16 | |
| pfw_data->frc_top_type.vsize / 4; |
| tmpend = (pfw_data->frc_top_type.hsize / 4) * 3 << 16 | |
| pfw_data->frc_top_type.vsize / 4 * 3; |
| } |
| demo_style++; |
| if (demo_style > 2) |
| demo_style = 0; |
| // set demo window-1 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| // enable demo window1 |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0x1, 17, 4); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0x8, 0, 5); |
| } else if (demo_num == 2) { |
| if (!demo_style) { |
| tmpstart = 0; |
| tmpend = (pfw_data->frc_top_type.hsize / 2) << 16 | |
| pfw_data->frc_top_type.vsize / 2; |
| } else { |
| tmpstart = (pfw_data->frc_top_type.hsize / 2) << 16; |
| tmpend = (pfw_data->frc_top_type.hsize) << 16 | |
| pfw_data->frc_top_type.vsize / 2; |
| } |
| // set demo window position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| if (!demo_style) { |
| tmpstart = (pfw_data->frc_top_type.hsize / 2) << 16 | |
| pfw_data->frc_top_type.vsize / 2; |
| tmpend = pfw_data->frc_top_type.hsize << 16 | |
| pfw_data->frc_top_type.vsize; |
| } else { |
| tmpstart = pfw_data->frc_top_type.vsize / 2; |
| tmpend = (pfw_data->frc_top_type.hsize / 2) << 16 | |
| pfw_data->frc_top_type.vsize; |
| } |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ED, tmpend); |
| |
| demo_style++; |
| if (demo_style > 1) |
| demo_style = 0; |
| // enable demo window |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0x3, 17, 4); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0xc, 0, 5); |
| } else if (demo_num == 3) { |
| tmpstart = 0; |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 3 << 16 | |
| pfw_data->frc_top_type.vsize; |
| // set demo window1 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) * 3 << 16; |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 7 << 16 | |
| pfw_data->frc_top_type.vsize; |
| // set demo window2 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ED, tmpend); |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) * 7 << 16; |
| tmpend = (pfw_data->frc_top_type.hsize) << 16 | |
| pfw_data->frc_top_type.vsize; |
| // set demo window3 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW3_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW3_XYXY_ED, tmpend); |
| |
| // enable demo window |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0x7, 17, 4); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0xe, 0, 5); |
| } else if (demo_num == 4) { |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) << 16 | |
| pfw_data->frc_top_type.vsize / 10; |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 4 << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 4; |
| // set demo window1 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW1_XYXY_ED, tmpend); |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) * 6 << 16 | |
| (pfw_data->frc_top_type.vsize / 10); |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 9 << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 4; |
| // set demo window2 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW2_XYXY_ED, tmpend); |
| |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 6; |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 4 << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 9; |
| // set demo window3 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW3_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW3_XYXY_ED, tmpend); |
| tmpstart = (pfw_data->frc_top_type.hsize / 10) * 6 << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 6; |
| tmpend = (pfw_data->frc_top_type.hsize / 10) * 9 << 16 | |
| (pfw_data->frc_top_type.vsize / 10) * 9; |
| // set demo window4 position |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW4_XYXY_ST, tmpstart); |
| WRITE_FRC_REG_BY_CPU(FRC_REG_DEMOWINDOW4_XYXY_ED, tmpend); |
| |
| // enable demo window |
| WRITE_FRC_BITS(FRC_REG_MC_DEBUG1, 0xf, 17, 4); |
| WRITE_FRC_BITS(FRC_MC_DEMO_WINDOW, 0xf, 0, 5); |
| } |
| pr_frc(2, "FRC_REG_MC_DEBUG1 value = 0x%x\n", READ_FRC_REG(FRC_REG_MC_DEBUG1)); |
| pr_frc(2, "FRC_MC_DEMO_WINDOW value = 0x%x\n", READ_FRC_REG(FRC_MC_DEMO_WINDOW)); |
| } |
| } |
| |
| /*bug: t3x 120Hz boot video flash*/ |
| void frc_boot_timestamp_check(struct frc_dev_s *devp) |
| { |
| u64 timestamp; |
| |
| if (get_chip_type() != ID_T3X || |
| devp->in_sts.boot_check_finished) |
| return; |
| |
| timestamp = sched_clock(); |
| timestamp = div64_u64(timestamp, 1000000000); // sec |
| if (timestamp > FRC_BOOT_TIMESTAMP && |
| devp->in_sts.boot_timestamp_en) { |
| if (devp->in_sts.auto_ctrl_reserved) { |
| devp->frc_sts.auto_ctrl = true; |
| frc_change_to_state(FRC_STATE_ENABLE); |
| } |
| devp->in_sts.boot_check_finished = 1; |
| pr_frc(0, "boot check finished, auto-ctrl:%d\n", |
| devp->in_sts.auto_ctrl_reserved); |
| } |
| } |