diff --git a/MAINTAINERS b/MAINTAINERS index b4029f7a8682..1e374e8a9504 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14370,6 +14370,7 @@ F: drivers/amlogic/media/vout/vout_serve/vout2_notify.c F: drivers/amlogic/media/vout/vout_serve/vout2_serve.c F: drivers/amlogic/media/vout/vout_serve/vout_func.c F: drivers/amlogic/media/vout/vout_serve/vout_func.h +F: drivers/amlogic/media/vout/vout_serve/vout_reg.h AMLOGIC GPIO IRQ M: Xingyu Chen @@ -14759,6 +14760,7 @@ F: arch/arm64/boot/dts/amlogic/partition_mbox_ab_P_32.dtsi AMLOGIC BACKLIGHT LDIM DRIVER M: Evoke Zhang F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_spi.c +F: drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c AMLOGIC CAMERA DRIVER M: Guosong Zhou diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.c b/drivers/amlogic/atv_demod/atv_demod_debug.c index 7e66331b99ee..e00cf71dba2d 100644 --- a/drivers/amlogic/atv_demod/atv_demod_debug.c +++ b/drivers/amlogic/atv_demod/atv_demod_debug.c @@ -104,6 +104,7 @@ DEBUGFS_CREATE_NODE(atvdemod_isr_en, 0640, dentry, bool)\ DEBUGFS_CREATE_NODE(atv_audio_overmodulated_cnt, 0640, dentry, u32)\ DEBUGFS_CREATE_NODE(support_secam_l, 0640, dentry, bool)\ + DEBUGFS_CREATE_NODE(atvdemod_horiz_freq_det_en, 0640, dentry, bool)\ } diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c index bb7bb8886915..b7aadef5afe1 100644 --- a/drivers/amlogic/atv_demod/atv_demod_driver.c +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -44,8 +44,10 @@ #include "atvdemod_func.h" #include "atvauddemod_func.h" - -#define AMLATVDEMOD_VER "V2.13" +/********************************CODE CHANGE LIST*****************************/ +/* Date --- Version --- Note *************************************************/ +/* 2019/11/05 --- V2.15 --- Add dynamic monitoring line frequency deviation. */ +#define AMLATVDEMOD_VER "V2.15" struct aml_atvdemod_device *amlatvdemod_devp; @@ -358,7 +360,7 @@ static ssize_t aml_atvdemod_store(struct class *class, int blk = 0, reg = 0; for (blk = 0; blk <= APB_BLOCK_ADDR_TOP; ++blk) { - for (reg = 0; reg <= 0x40; ++reg) { + for (reg = 0; reg < 0x40; ++reg) { val = atv_dmd_rd_long(blk, reg); pr_err("[0x%04x] = 0x%x.\n", (blk << 8) + (reg << 2), val); diff --git a/drivers/amlogic/atv_demod/atv_demod_monitor.c b/drivers/amlogic/atv_demod/atv_demod_monitor.c index 4969acb20d8a..5a6e13a8818e 100644 --- a/drivers/amlogic/atv_demod/atv_demod_monitor.c +++ b/drivers/amlogic/atv_demod/atv_demod_monitor.c @@ -37,6 +37,7 @@ bool audio_thd_en; bool atvdemod_det_nonstd_en; bool atvaudio_det_outputmode_en = true; bool audio_carrier_offset_det_en; +bool atvdemod_horiz_freq_det_en = true; unsigned int atvdemod_timer_delay = 100; /* 1s */ unsigned int atvdemod_timer_delay2 = 10; /* 100ms */ @@ -87,6 +88,9 @@ static void atv_demod_monitor_do_work(struct work_struct *work) if (atvdemod_det_nonstd_en) atv_dmd_non_std_set(true); + + if (atvdemod_horiz_freq_det_en) + atvdemod_horiz_freq_detection(); } static void atv_demod_monitor_timer_handler(unsigned long arg) diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c index 35fb99f9bafb..2b566f7833c4 100644 --- a/drivers/amlogic/atv_demod/atv_demod_ops.c +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -129,6 +129,11 @@ int aml_atvdemod_get_btsc_sap_mode(void) return btsc_sap_mode; } +static bool atvdemod_check_exited(struct atv_demod_priv *priv) +{ + return (priv->state != ATVDEMOD_STATE_WORK); +} + int atv_demod_enter_mode(struct dvb_frontend *fe) { int err_code = 0; @@ -532,9 +537,16 @@ static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, unsigned int broad_std = 0; unsigned int audio = 0; + *video_fmt = 0; + *audio_fmt = 0; + *soundsys = 0; + if (auto_search_std & AUTO_DETECT_COLOR) { for (i = 0; i < try_vfmt_cnt; i++) { + if (atvdemod_check_exited(priv)) + return; + /* SECAM-L/L' */ if ((p->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && (p->std & V4L2_COLOR_STD_SECAM)) { @@ -719,6 +731,9 @@ static void atvdemod_fe_try_signal(struct v4l2_frontend *v4l2_fe, *lock = false; do { + if (atvdemod_check_exited(priv)) + break; + if (tuner_id == AM_TUNER_MXL661) { usleep_range(30 * 1000, 30 * 1000 + 100); } else if (tuner_id == AM_TUNER_R840 || @@ -844,6 +859,9 @@ static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, set_freq = p->frequency; while (abs(afc) > AFC_BEST_LOCK) { + if (atvdemod_check_exited(priv)) + return -1; + if (tuner_id == AM_TUNER_MXL661) usleep_range(30 * 1000, 30 * 1000 + 100); else @@ -1118,13 +1136,15 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) v4l2_std_id std_bk = 0; unsigned int audio = 0; unsigned int soundsys = 0; - int double_check_cnt = 1; + /* int double_check_cnt = 1; */ int auto_search_std = 0; int search_count = 0; /* bool try_secam = false; */ int ret = -1; unsigned int tuner_id = 0; int priv_cfg = 0; + int exit_status = 0; + char *exit_str = ""; if (unlikely(!fe || !p || !fe->ops.tuner_ops.get_status || @@ -1137,7 +1157,7 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) } priv = fe->analog_demod_priv; - if (priv->state != ATVDEMOD_STATE_WORK) { + if (atvdemod_check_exited(priv)) { pr_err("[%s] ATV state is not work.\n", __func__); return V4L2_SEARCH_INVALID; } @@ -1217,6 +1237,11 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) while (minafcfreq <= p->frequency && p->frequency <= maxafcfreq) { + if (atvdemod_check_exited(priv)) { + exit_status = 1; + break; + } + pr_dbg("[%s] [%d] is processing, [min=%d, max=%d].\n", __func__, p->frequency, minafcfreq, maxafcfreq); @@ -1250,6 +1275,9 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) p->soundsys = soundsys; std_bk = 0; audio = 0; + } else { + exit_status = 1; + break; } /* sync param */ @@ -1265,9 +1293,12 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) (uint32_t) p->std, p->frequency); /* when manual search, just search current freq */ - if (p->flag == ANALOG_FLAG_MANUL_SCAN) + if (p->flag == ANALOG_FLAG_MANUL_SCAN) { + exit_status = 2; break; + } +#ifdef DOUBLE_CHECK_44_25MHZ if (p->frequency >= 44200000 && p->frequency <= 44300000 && double_check_cnt) { @@ -1278,10 +1309,22 @@ static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe) p->frequency += afc_step * ((search_count % 2) ? -search_count : search_count); } +#else + ++search_count; + p->frequency += afc_step * ((search_count % 2) ? + -search_count : search_count); +#endif } - pr_dbg("[%s] [%d] over of range [min=%d, max=%d], search failed.\n", - __func__, p->frequency, minafcfreq, maxafcfreq); + if (!exit_status) + exit_str = "over of range, search failed"; + else if (exit_status == 1) + exit_str = "search exited"; + else + exit_str = "search failed"; + + pr_dbg("[%s] [%d] %s.\n", __func__, p->frequency, exit_str); + p->frequency = set_freq; priv_cfg = AML_ATVDEMOD_UNSCAN_MODE; diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c index 76c02cff7921..2b4516d74cff 100644 --- a/drivers/amlogic/atv_demod/atvauddemod_func.c +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -872,7 +872,7 @@ void set_mono_dk(void) { int aa; - adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_DK); + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_DK | (3 << 4)); set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); @@ -889,7 +889,7 @@ void set_mono_i(void) { int aa; - adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_I); + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_I | (3 << 4)); set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); @@ -906,7 +906,7 @@ void set_mono_bg(void) { int aa; - adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_BG); + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_BG | (3 << 4)); set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); @@ -923,7 +923,7 @@ void set_mono_l(void) { int aa; - adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_L); + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_L | (3 << 4)); set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); @@ -1586,7 +1586,7 @@ void set_outputmode(uint32_t standard, uint32_t outmode) case AUDIO_STANDARD_MONO_I: case AUDIO_STANDARD_MONO_L: /* for FM MONO system to detection nicam status */ - if (!aud_reinit && get_nicam_lock_status()) { + if (!aud_mono_only && !aud_reinit && get_nicam_lock_status()) { if (standard == AUDIO_STANDARD_MONO_I) aud_std = AUDIO_STANDARD_NICAM_I; else if (standard == AUDIO_STANDARD_MONO_L) diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c index 6e9a3618ceae..78e6f8b6dc6f 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.c +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -260,7 +260,7 @@ void atv_dmd_misc(void) /* for audio non-standard signal, first set gain 0 to mute, * then unmute in detection. */ - if (audio_atv_ov || atv_audio_overmodulated_en) + if ((audio_atv_ov || atv_audio_overmodulated_en) && non_std_en == 0) aml_audio_valume_gain_set(0); else aml_audio_valume_gain_set(audio_gain_val); @@ -287,8 +287,8 @@ void atv_dmd_misc(void) atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x0c, 0x387c0831); atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc020901); } else { - if (tuner_id == AM_TUNER_R840 || tuner_id == AM_TUNER_R842 - || non_std_en == 4) { + if ((tuner_id == AM_TUNER_R840 || tuner_id == AM_TUNER_R842) && + non_std_en == 4) { /* Reduce target amplitude and response speed */ atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x17070200); @@ -338,45 +338,67 @@ void atv_dmd_misc(void) pr_dbg("%s done.\n", __func__); } -void atv_dmd_ring_filter(bool on) +void atv_dmd_ring_filter(bool on, int std) { - unsigned long filter_status = 0; + int i = 0; + int filter = 0; + unsigned long status = 0; + unsigned long data = 0; + const unsigned int reg_addr[10] = { + 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, + }; + const unsigned int peak_filter[][10] = { + /* default */ + { 0x8423F6, 0xFF86A967, 0x37FE45, 0xFF86A967, 0x3C223B, + 0x8423F6, 0xFF86A967, 0x37FE45, 0xFF86A967, 0x3C223B }, + /* ntsc-m */ + { 0x8274bf, 0x1d175c, 0x2aa526, 0x1d175c, 0x2d19e4, + 0x8274bf, 0x1d175c, 0x2aa526, 0x1d175c, 0x2d19e4 }, + /* pal-i */ + { 0x94d888, 0x5a39fb, 0xd8ebb, 0x5a39fb, 0x226744, + 0x94d888, 0x5a39fb, 0xd8ebb, 0x5a39fb, 0x226744 } + }; + if (!is_meson_tl1_cpu() && !is_meson_tm2_cpu()) return; - filter_status = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c); - if (((filter_status & 0x01) && on) || (!(filter_status & 0x01) && !on)) + if (on) { + if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) { + filter = 2; + } else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { + filter = 2; + } else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) { + filter = 2; + } else if (std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || + std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) { + filter = 1; + } else { + filter = 0; + on = false; + } + } else { + filter = 0; + } + + status = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c); + data = atv_dmd_rd_long(APB_BLOCK_ADDR_GDE_EQUAL, reg_addr[0]); + if ((data == peak_filter[filter][0]) && on && (status & 0x01)) return; - if (on) { - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8274bf); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0x1d175c); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x2aa526); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0x1d175c); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x2d19e4); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8274bf); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0x1d175c); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x2aa526); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0x1d175c); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x2d19e4); + if (!on && !(status & 0x01)) + return; + /* disable filter */ + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); + + for (i = 0; i < 10; ++i) { + atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, + reg_addr[i], peak_filter[filter][i]); + } + + if (on) { /* enable filter */ atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x1); - } else { - /* default value */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x10, 0x8423F6); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x14, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x18, 0x37FE45); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x1c, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x20, 0x3C223B); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x24, 0x8423F6); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x28, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x2c, 0x37FE45); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x30, 0xFF86A967); - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x34, 0x3C223B); - - /* disable filter */ - atv_dmd_wr_long(APB_BLOCK_ADDR_GDE_EQUAL, 0x4c, 0x0); } pr_dbg("%s do atv_dmd_ring_filter %d ...\n", __func__, on); @@ -2021,12 +2043,10 @@ int atvdemod_init(struct atv_demod_priv *priv) if (!priv->scanning || non_std_en) atv_dmd_misc(); - if (!priv->scanning && - (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M || - broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC)) - atv_dmd_ring_filter(true); + if (!priv->scanning) + atv_dmd_ring_filter(true, broad_std); else - atv_dmd_ring_filter(false); + atv_dmd_ring_filter(false, broad_std); atv_dmd_soft_reset(); @@ -2525,3 +2545,45 @@ void aml_audio_overmodulation(int enable) #endif } } + +void atvdemod_horiz_freq_detection(void) +{ + unsigned long data = 0; + int field_lock = 0; + int line_lock = 0; + int line = 0; + int std_line = 0; + unsigned long horiz_freq = 0; + + data = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x4c); + field_lock = data & 0x4; /* bit2 */ + line_lock = data & 0x10; /* bit4 */ + line = (data >> 6) & 0x3ff; /* bit[15-6] */ + + switch (broad_std) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: + std_line = 525; + break; + default: + std_line = 625; + break; + } + + if (field_lock == 0 && line_lock == 0) { + /* bit[31-8] */ + data = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x10); + + /* fh +/- (200 / 0.23841858) */ + if ((line - std_line) > 7) + horiz_freq = freq_hz_cvrt + 0x347; + else if ((line - std_line) < -7) + horiz_freq = freq_hz_cvrt - 0x347; + else + horiz_freq = freq_hz_cvrt; + + data = (horiz_freq << 8) | (data & 0xff); + + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x10, data); + } +} diff --git a/drivers/amlogic/atv_demod/atvdemod_func.h b/drivers/amlogic/atv_demod/atvdemod_func.h index f7e09d36e151..c8f2f0caaf43 100644 --- a/drivers/amlogic/atv_demod/atvdemod_func.h +++ b/drivers/amlogic/atv_demod/atvdemod_func.h @@ -31,6 +31,7 @@ extern unsigned int aud_std; extern unsigned int aud_mode; extern bool audio_thd_en; extern bool aud_reinit; +extern bool aud_mono_only; extern bool atv_audio_overmodulated_en; extern unsigned int non_std_en; @@ -70,7 +71,7 @@ extern void read_version_register(void); extern void check_communication_interface(void); extern void power_on_receiver(void); extern void atv_dmd_misc(void); -extern void atv_dmd_ring_filter(bool on); +void atv_dmd_ring_filter(bool on, int std); extern void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, int Tuner_Input_IF_inverted, int GDE_Curve, @@ -214,6 +215,7 @@ extern void set_atvdemod_scan_mode(int val); extern int atvauddemod_init(void); extern int amlfmt_aud_standard(int broad_std); extern void atvauddemod_set_outputmode(void); +void atvdemod_horiz_freq_detection(void); /*from amldemod/amlfrontend.c*/ extern int vdac_enable_check_dtv(void); diff --git a/drivers/amlogic/drm/meson_drv.c b/drivers/amlogic/drm/meson_drv.c index bfa68937374d..d74da5e62d2e 100644 --- a/drivers/amlogic/drm/meson_drv.c +++ b/drivers/amlogic/drm/meson_drv.c @@ -40,9 +40,9 @@ #include "meson_fb.h" #endif #include "meson_drv.h" +#include "meson_vpu.h" #include "meson_vpu_pipeline.h" - #define DRIVER_NAME "meson" #define DRIVER_DESC "Amlogic Meson DRM driver" @@ -114,23 +114,313 @@ static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc) priv->crtc_funcs[crtc]->disable_vblank(priv->crtc); } -static void am_meson_load(struct drm_device *dev) -{ -#if 0 - struct meson_drm *priv = dev->dev_private; - struct drm_crtc *crtc = priv->crtc; - int pipe = drm_crtc_index(crtc); +struct am_meson_logo logo; +core_param(fb_width, logo.width, uint, 0644); +core_param(fb_height, logo.height, uint, 0644); +core_param(display_bpp, logo.bpp, uint, 0644); +core_param(outputmode, logo.outputmode_t, charp, 0644); - if (priv->crtc_funcs[pipe] && - priv->crtc_funcs[pipe]->loader_protect) - priv->crtc_funcs[pipe]->loader_protect(crtc, true); -#endif +static struct drm_framebuffer *am_meson_logo_init_fb(struct drm_device *dev) +{ + struct drm_mode_fb_cmd2 mode_cmd; + struct drm_framebuffer *fb; + struct am_meson_fb *meson_fb; + + DRM_INFO("width=%d,height=%d,start_addr=0x%pa,size=%d\n", + logo.width, logo.height, &logo.start, logo.size); + DRM_INFO("bpp=%d,alloc_flag=%d\n", logo.bpp, logo.alloc_flag); + DRM_INFO("outputmode=%s\n", logo.outputmode); + if (logo.bpp == 16) + mode_cmd.pixel_format = DRM_FORMAT_RGB565; + else + mode_cmd.pixel_format = DRM_FORMAT_XRGB8888; + mode_cmd.offsets[0] = 0; + mode_cmd.width = logo.width; + mode_cmd.height = logo.height; + mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR; + /*ToDo*/ + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * logo.bpp, 32) / 8; + fb = am_meson_fb_alloc(dev, &mode_cmd, NULL); + if (IS_ERR_OR_NULL(fb)) + return NULL; + meson_fb = to_am_meson_fb(fb); + meson_fb->logo = &logo; + + return fb; +} + +#define FPS_DELTA_LIMIT 1 +struct drm_display_mode * +am_meson_drm_display_mode_init(struct drm_connector *connector) +{ + struct drm_display_mode *mode; + struct drm_device *dev; + u32 found, num_modes; + + if (!connector || !connector->dev) + return NULL; + dev = connector->dev; + found = 0; + drm_modeset_lock_all(dev); + if (drm_modeset_is_locked(&dev->mode_config.connection_mutex)) + drm_modeset_unlock(&dev->mode_config.connection_mutex); + num_modes = connector->funcs->fill_modes(connector, + dev->mode_config.max_width, + dev->mode_config.max_height); + drm_modeset_unlock_all(dev); + if (!num_modes) { + DRM_INFO("%s:num_modes is zero\n", __func__); + return NULL; + } + list_for_each_entry(mode, &connector->modes, head) { + if (am_meson_crtc_check_mode(mode, logo.outputmode) == true) { + found = 1; + break; + } + } + if (found) + return mode; + else + return NULL; +} + +static int am_meson_update_output_state(struct drm_atomic_state *state, + struct drm_mode_set *set) +{ + struct drm_device *dev = set->crtc->dev; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + int ret, i; + + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, + state->acquire_ctx); + if (ret) + return ret; + + /* First disable all connectors on the target crtc. */ + ret = drm_atomic_add_affected_connectors(state, set->crtc); + if (ret) + return ret; + + for_each_connector_in_state(state, connector, conn_state, i) { + if (conn_state->crtc == set->crtc) { + ret = drm_atomic_set_crtc_for_connector(conn_state, + NULL); + if (ret) + return ret; + } + } + + /* Then set all connectors from set->connectors on the target crtc */ + for (i = 0; i < set->num_connectors; i++) { + conn_state = drm_atomic_get_connector_state(state, + set->connectors[i]); + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); + + ret = drm_atomic_set_crtc_for_connector(conn_state, + set->crtc); + if (ret) + return ret; + } + + for_each_crtc_in_state(state, crtc, crtc_state, i) { + /* Don't update ->enable for the CRTC in the set_config request, + * since a mismatch would indicate a bug in the upper layers. + * The actual modeset code later on will catch any + * inconsistencies here. + */ + if (crtc == set->crtc) + continue; + + if (!crtc_state->connector_mask) { + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, + NULL); + if (ret < 0) + return ret; + + crtc_state->active = false; + } + } + + return 0; +} + +static int __am_meson_drm_set_config(struct drm_mode_set *set, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_plane_state *primary_state; + struct drm_crtc *crtc = set->crtc; + int hdisplay, vdisplay; + int ret; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + primary_state = drm_atomic_get_plane_state(state, crtc->primary); + if (IS_ERR(primary_state)) + return PTR_ERR(primary_state); + + if (!set->mode) { + WARN_ON(set->fb); + WARN_ON(set->num_connectors); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); + if (ret != 0) + return ret; + + crtc_state->active = false; + + ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); + if (ret != 0) + return ret; + + drm_atomic_set_fb_for_plane(primary_state, NULL); + + goto commit; + } + + WARN_ON(!set->fb); + WARN_ON(!set->num_connectors); + + ret = drm_atomic_set_mode_for_crtc(crtc_state, set->mode); + if (ret != 0) + return ret; + + crtc_state->active = true; + + ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); + if (ret != 0) + return ret; + + drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); + + drm_atomic_set_fb_for_plane(primary_state, set->fb); + primary_state->crtc_x = 0; + primary_state->crtc_y = 0; + primary_state->crtc_w = hdisplay; + primary_state->crtc_h = vdisplay; + primary_state->src_x = set->x << 16; + primary_state->src_y = set->y << 16; + if (drm_rotation_90_or_270(primary_state->rotation)) { + primary_state->src_w = set->fb->height << 16; + primary_state->src_h = set->fb->width << 16; + } else { + primary_state->src_w = set->fb->width << 16; + primary_state->src_h = set->fb->height << 16; + } + +commit: + ret = am_meson_update_output_state(state, set); + if (ret) + return ret; + + return 0; +} + +static int am_meson_drm_set_config(struct drm_mode_set *set) +{ + struct drm_atomic_state *state; + struct drm_crtc *crtc = set->crtc; + int ret = 0; + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) + return -ENOMEM; + + state->legacy_set_config = true; + state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); +retry: + ret = __am_meson_drm_set_config(set, state); + if (ret != 0) + goto fail; + + ret = drm_atomic_commit(state); + if (ret != 0) + goto fail; + + /* Driver takes ownership of state on successful commit. */ + return 0; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + + return ret; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + crtc->primary->old_fb = crtc->primary->fb; + + goto retry; +} + +static void am_meson_load_logo(struct drm_device *dev) +{ + struct drm_mode_set set; + struct drm_framebuffer *fb; + struct drm_display_mode *mode; + struct drm_connector **connector_set; + struct meson_drm *private = dev->dev_private; + + if (!logo.alloc_flag) { + DRM_INFO("%s: logo memory is not cma alloc\n", __func__); + return; + } + fb = am_meson_logo_init_fb(dev); + if (!fb) { + DRM_INFO("%s:framebuffer is NULL!\n", __func__); + return; + } + connector_set = kmalloc_array(1, sizeof(struct drm_connector *), + GFP_KERNEL); + if (!connector_set) + return; + connector_set[0] = am_meson_hdmi_connector(); + if (!connector_set[0]) { + DRM_INFO("%s:connector is NULL!\n", __func__); + kfree(connector_set); + return; + } + mode = am_meson_drm_display_mode_init(connector_set[0]); + if (!mode) { + DRM_INFO("%s:display mode is NULL!\n", __func__); + kfree(connector_set); + return; + } + DRM_INFO("find the match display mode:%s\n", mode->name); + set.crtc = private->crtc; + set.x = 0; + set.y = 0; + set.mode = mode; + set.connectors = connector_set; + set.num_connectors = 1; + set.fb = fb; + drm_modeset_lock_all(dev); + if (am_meson_drm_set_config(&set)) + DRM_INFO("[%s]am_meson_drm_set_config fail\n", __func__); + if (drm_framebuffer_read_refcount(fb) > 1) + drm_framebuffer_unreference(fb); + drm_modeset_unlock_all(dev); + + kfree(connector_set); } #ifdef CONFIG_DRM_MESON_USE_ION static const struct drm_ioctl_desc meson_ioctls[] = { DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl, - DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), + DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW), }; #endif @@ -277,7 +567,7 @@ static int am_meson_drm_bind(struct device *dev) drm_kms_helper_poll_init(drm); - am_meson_load(drm); + am_meson_load_logo(drm); #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV ret = am_meson_drm_fbdev_init(drm); @@ -290,7 +580,6 @@ static int am_meson_drm_bind(struct device *dev) return 0; - err_fbdev_fini: #ifdef CONFIG_DRM_MESON_EMULATE_FBDEV am_meson_drm_fbdev_fini(drm); @@ -384,10 +673,10 @@ static bool am_meson_drv_use_osd(void) if (strcmp(str, "okay") && strcmp(str, "ok")) { DRM_INFO("device %s status is %s\n", - node->name, str); + node->name, str); } else { DRM_INFO("device %s status is %s\n", - node->name, str); + node->name, str); return true; } } @@ -466,6 +755,7 @@ static int am_meson_drv_probe(struct platform_device *pdev) struct component_match *match = NULL; int i; + pr_info("[%s] in\n", __func__); if (am_meson_drv_use_osd()) return am_meson_drv_probe_prune(pdev); @@ -518,7 +808,7 @@ static int am_meson_drv_probe(struct platform_device *pdev) am_meson_add_endpoints(dev, &match, port); of_node_put(port); } - + pr_info("[%s] out\n", __func__); return component_master_add_with_match(dev, &am_meson_drm_ops, match); } diff --git a/drivers/amlogic/drm/meson_drv.h b/drivers/amlogic/drm/meson_drv.h index 4260a3ca00fa..3e35f272e091 100644 --- a/drivers/amlogic/drm/meson_drv.h +++ b/drivers/amlogic/drm/meson_drv.h @@ -59,6 +59,7 @@ struct meson_drm { struct meson_vpu_pipeline *pipeline; struct meson_vpu_funcs *funcs; + struct am_meson_logo *logo; u32 num_crtcs; struct am_meson_crtc *crtcs[MESON_MAX_CRTC]; @@ -76,6 +77,7 @@ static inline int meson_vpu_is_compatible(struct meson_drm *priv, extern int am_meson_register_crtc_funcs(struct drm_crtc *crtc, const struct meson_crtc_funcs *crtc_funcs); extern void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc); +struct drm_connector *am_meson_hdmi_connector(void); #ifdef CONFIG_DEBUG_FS int meson_debugfs_init(struct drm_minor *minor); diff --git a/drivers/amlogic/drm/meson_fb.c b/drivers/amlogic/drm/meson_fb.c index 1c364da4bf3e..81fc0981c595 100644 --- a/drivers/amlogic/drm/meson_fb.c +++ b/drivers/amlogic/drm/meson_fb.c @@ -18,8 +18,7 @@ #include #include "meson_fb.h" - -#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base) +#include "meson_vpu.h" void am_meson_fb_destroy(struct drm_framebuffer *fb) { @@ -27,6 +26,9 @@ void am_meson_fb_destroy(struct drm_framebuffer *fb) drm_gem_object_unreference_unlocked(&meson_fb->bufp->base); drm_framebuffer_cleanup(fb); + if (meson_fb->logo && meson_fb->logo->alloc_flag) + am_meson_free_logo_memory(); + DRM_DEBUG("meson_fb=0x%p,\n", meson_fb); kfree(meson_fb); } @@ -58,9 +60,12 @@ am_meson_fb_alloc(struct drm_device *dev, if (!meson_fb) return ERR_PTR(-ENOMEM); - meson_gem = container_of(obj, struct am_meson_gem_object, base); - meson_fb->bufp = meson_gem; - + if (obj) { + meson_gem = container_of(obj, struct am_meson_gem_object, base); + meson_fb->bufp = meson_gem; + } else { + meson_fb->bufp = NULL; + } drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd); ret = drm_framebuffer_init(dev, &meson_fb->base, @@ -70,6 +75,10 @@ am_meson_fb_alloc(struct drm_device *dev, ret); goto err_free_fb; } + DRM_INFO("meson_fb[id:%d,ref:%d]=0x%p,meson_fb->bufp=0x%p\n", + meson_fb->base.base.id, + atomic_read(&meson_fb->base.base.refcount.refcount), + meson_fb, meson_fb->bufp); return &meson_fb->base; @@ -113,6 +122,10 @@ struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev, kfree(meson_fb); return ERR_PTR(ret); } + DRM_DEBUG("meson_fb[in:%d,ref:%d]=0x%px,meson_fb->bufp=0x%p\n", + meson_fb->base.base.id, + atomic_read(&meson_fb->base.base.refcount.refcount), + meson_fb, meson_fb->bufp); return &meson_fb->base; } diff --git a/drivers/amlogic/drm/meson_fb.h b/drivers/amlogic/drm/meson_fb.h index 9c76d2e71f26..0226ee765899 100644 --- a/drivers/amlogic/drm/meson_fb.h +++ b/drivers/amlogic/drm/meson_fb.h @@ -24,16 +24,40 @@ #include "meson_gem.h" +#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base) + +#define VMODE_NAME_LEN_MAX 64 + +struct am_meson_logo { + struct page *logo_page; + phys_addr_t start; + u32 size; + u32 width; + u32 height; + u32 bpp; + u32 alloc_flag; + u32 info_loaded_mask; + char *outputmode_t; + char outputmode[VMODE_NAME_LEN_MAX]; +}; + struct am_meson_fb { struct drm_framebuffer base; struct am_meson_gem_object *bufp; + struct am_meson_logo *logo; }; -struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev, - struct drm_file *file_priv, - const struct drm_mode_fb_cmd2 *mode_cmd); -struct drm_framebuffer *am_meson_drm_framebuffer_init( - struct drm_device *dev, - struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); +struct drm_framebuffer * +am_meson_fb_create(struct drm_device *dev, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd); +struct drm_framebuffer * +am_meson_drm_framebuffer_init(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); +struct drm_framebuffer * +am_meson_fb_alloc(struct drm_device *dev, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); + #endif diff --git a/drivers/amlogic/drm/meson_gem.c b/drivers/amlogic/drm/meson_gem.c index 4c6ef32a2098..b7dd7b27c492 100644 --- a/drivers/amlogic/drm/meson_gem.c +++ b/drivers/amlogic/drm/meson_gem.c @@ -55,7 +55,7 @@ static int am_meson_gem_alloc_ion_buff( bscatter = true; } - if (IS_ERR(handle)) { + if (IS_ERR_OR_NULL(handle)) { DRM_ERROR("%s: FAILED, flags:0x%x.\n", __func__, flags); return -ENOMEM; diff --git a/drivers/amlogic/drm/meson_hdmi.c b/drivers/amlogic/drm/meson_hdmi.c index e5f0ce60eae3..7cbe8c165c5d 100644 --- a/drivers/amlogic/drm/meson_hdmi.c +++ b/drivers/amlogic/drm/meson_hdmi.c @@ -35,17 +35,11 @@ #include #include "meson_hdmi.h" #include "meson_hdcp.h" +#include "meson_vpu.h" #define DEVICE_NAME "amhdmitx" struct am_hdmi_tx am_hdmi_info; -struct am_vout_mode { - char name[DRM_DISPLAY_MODE_LEN]; - enum vmode_e mode; - int width, height, vrefresh; - unsigned int flags; -}; - static struct am_vout_mode am_vout_modes[] = { { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0}, { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0}, @@ -300,7 +294,6 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder) vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode); set_vout_vmode(vmode); vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode); - am_hdmi->hdcp_work = NULL; mdelay(1000); am_hdmi_hdcp_work_state_change(am_hdmi, 0); } @@ -584,6 +577,11 @@ static const struct of_device_id am_meson_hdmi_dt_ids[] = { MODULE_DEVICE_TABLE(of, am_meson_hdmi_dt_ids); +struct drm_connector *am_meson_hdmi_connector(void) +{ + return &am_hdmi_info.connector; +} + static int am_meson_hdmi_bind(struct device *dev, struct device *master, void *data) { @@ -596,12 +594,9 @@ static int am_meson_hdmi_bind(struct device *dev, int ret; int irq; - am_hdmi = devm_kzalloc(priv->dev, sizeof(*am_hdmi), - GFP_KERNEL); - if (!am_hdmi) - return -ENOMEM; - memcpy(&am_hdmi_info, am_hdmi, sizeof(*am_hdmi)); + DRM_INFO("[%s] in\n", __func__); am_hdmi = &am_hdmi_info; + memset(am_hdmi, 0, sizeof(*am_hdmi)); DRM_INFO("drm hdmitx init and version:%s\n", DRM_HDMITX_VER); am_hdmi->priv = priv; @@ -662,6 +657,7 @@ static int am_meson_hdmi_bind(struct device *dev, DRM_DEBUG_KMS("HDCP init failed, skipping.\n"); } } + DRM_INFO("[%s] out\n", __func__); return 0; } @@ -679,6 +675,7 @@ static const struct component_ops am_meson_hdmi_ops = { static int am_meson_hdmi_probe(struct platform_device *pdev) { + DRM_INFO("[%s] in\n", __func__); return component_add(&pdev->dev, &am_meson_hdmi_ops); } diff --git a/drivers/amlogic/drm/meson_plane.c b/drivers/amlogic/drm/meson_plane.c index c7a2d079b9ad..2c5820641ccb 100644 --- a/drivers/amlogic/drm/meson_plane.c +++ b/drivers/amlogic/drm/meson_plane.c @@ -42,12 +42,18 @@ static u64 afbc_wb_modifier[] = { DRM_FORMAT_MOD_INVALID }; -static void meson_plane_position_calc( - struct meson_vpu_osd_layer_info *plane_info, - struct drm_plane_state *state, - struct drm_display_mode *mode) +static void +meson_plane_position_calc(struct meson_vpu_osd_layer_info *plane_info, + struct drm_plane_state *state, + struct drm_display_mode *disp_mode) { u32 dst_w, dst_h, src_w, src_h, scan_mode_out; + struct drm_display_mode *mode; + + if (IS_ERR_OR_NULL(state->crtc)) + mode = disp_mode; + else + mode = &state->crtc->mode; scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE; plane_info->src_x = state->src_x; @@ -147,7 +153,7 @@ static int meson_plane_fb_check(struct drm_plane *plane, #else struct drm_gem_cma_object *gem; #endif - dma_addr_t phyaddr; + phys_addr_t phyaddr; #ifdef CONFIG_DRM_MESON_USE_ION meson_fb = container_of(fb, struct am_meson_fb, base); @@ -155,9 +161,21 @@ static int meson_plane_fb_check(struct drm_plane *plane, DRM_INFO("meson_fb is NULL!\n"); return -EINVAL; } - phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp); - if (meson_fb->bufp->bscatter) - DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n"); + DRM_DEBUG("meson_fb[id:%d,ref:%d]=0x%p\n", + meson_fb->base.base.id, + atomic_read(&meson_fb->base.base.refcount.refcount), + meson_fb); + if (meson_fb->logo && meson_fb->logo->alloc_flag && + meson_fb->logo->start) { + phyaddr = meson_fb->logo->start; + DRM_DEBUG("logo->phyaddr=0x%pa\n", &phyaddr); + } else if (meson_fb->bufp) { + phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp); + } else { + phyaddr = 0; + DRM_INFO("don't find phyaddr!\n"); + return -EINVAL; + } #else if (!fb) { DRM_INFO("fb is NULL!\n"); @@ -182,12 +200,6 @@ static int meson_plane_get_fb_info(struct drm_plane *plane, struct am_osd_plane *osd_plane = to_am_osd_plane(plane); struct drm_framebuffer *fb = new_state->fb; struct meson_drm *drv = osd_plane->drv; - #ifdef CONFIG_DRM_MESON_USE_ION - struct am_meson_fb *meson_fb; - #else - struct drm_gem_cma_object *gem; - #endif - dma_addr_t phyaddr; if (!drv) { DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__); @@ -197,29 +209,7 @@ static int meson_plane_get_fb_info(struct drm_plane *plane, DRM_INFO("%s invalid plane_index!\n", __func__); return -EINVAL; } - - #ifdef CONFIG_DRM_MESON_USE_ION - meson_fb = container_of(fb, struct am_meson_fb, base); - if (!meson_fb) { - DRM_INFO("meson_fb is NULL!\n"); - return 0; - } - phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp); - if (meson_fb->bufp->bscatter) - DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n"); - plane_info->fb_size = meson_fb->bufp->base.size; - #else - if (!fb) { - DRM_INFO("fb is NULL!\n"); - return -EINVAL; - } - /* Update Canvas with buffer address */ - gem = drm_fb_cma_get_gem_obj(fb, 0); - phyaddr = gem->paddr; - #endif - plane_info->pixel_format = fb->pixel_format; - plane_info->phy_addr = phyaddr; plane_info->byte_stride = fb->pitches[0]; /*setup afbc info*/ @@ -261,6 +251,13 @@ static int meson_plane_atomic_get_property(struct drm_plane *plane, struct drm_property *property, uint64_t *val) { + struct am_osd_plane *osd_plane; + struct am_meson_plane_state *plane_state; + + osd_plane = to_am_osd_plane(plane); + plane_state = to_am_meson_plane_state(state); + if (property == osd_plane->prop_premult_en) + *val = plane_state->premult_en; return 0; } @@ -269,6 +266,14 @@ static int meson_plane_atomic_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { + struct am_osd_plane *osd_plane; + struct am_meson_plane_state *plane_state; + + osd_plane = to_am_osd_plane(plane); + plane_state = to_am_meson_plane_state(state); + if (property == osd_plane->prop_premult_en) + plane_state->premult_en = val; + return 0; } @@ -355,7 +360,7 @@ static void meson_plane_cleanup_fb(struct drm_plane *plane, { struct am_osd_plane *osd_plane = to_am_osd_plane(plane); - DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index); + DRM_DEBUG("osd %d.\n", osd_plane->plane_index); } static void meson_plane_atomic_update(struct drm_plane *plane, @@ -372,6 +377,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane, struct meson_vpu_pipeline_state *mvps; struct am_osd_plane *osd_plane = to_am_osd_plane(plane); struct meson_drm *drv = osd_plane->drv; + struct am_meson_plane_state *plane_state; int ret; if (!state || !drv) { @@ -410,6 +416,8 @@ static int meson_plane_atomic_check(struct drm_plane *plane, return ret; } + plane_state = to_am_meson_plane_state(state); + plane_info->premult_en = plane_state->premult_en; plane_info->enable = 1; DRM_DEBUG("index=%d, zorder=%d\n", plane_info->plane_index, plane_info->zorder); @@ -438,6 +446,24 @@ static const struct drm_plane_helper_funcs am_osd_helper_funcs = { .atomic_disable = meson_plane_atomic_disable, }; +int drm_plane_create_premult_en_property(struct drm_plane *plane) +{ + struct drm_device *dev = plane->dev; + struct drm_property *prop; + struct am_osd_plane *osd_plane; + + osd_plane = to_am_osd_plane(plane); + prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC, + "PREMULT_EN"); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&plane->base, prop, 0); + osd_plane->prop_premult_en = prop; + + return 0; +} + static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i) { struct am_osd_plane *osd_plane; @@ -469,6 +495,7 @@ static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i) format_modifiers, type, plane_name); + drm_plane_create_premult_en_property(plane); drm_plane_helper_add(plane, &am_osd_helper_funcs); osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir, plane_name, osd_plane->plane_index); diff --git a/drivers/amlogic/drm/meson_plane.h b/drivers/amlogic/drm/meson_plane.h index a1e6f4b13cb8..5be8adc5dab0 100644 --- a/drivers/amlogic/drm/meson_plane.h +++ b/drivers/amlogic/drm/meson_plane.h @@ -31,6 +31,7 @@ struct am_meson_plane_state { struct drm_plane_state base; + u32 premult_en; }; struct am_osd_plane { @@ -38,6 +39,7 @@ struct am_osd_plane { struct meson_drm *drv; //point to struct parent. struct dentry *plane_debugfs_dir; int plane_index; + struct drm_property *prop_premult_en; }; #define to_am_osd_plane(x) container_of(x, \ diff --git a/drivers/amlogic/drm/meson_vpu.c b/drivers/amlogic/drm/meson_vpu.c index ca025a89b8ea..91102d5d6465 100644 --- a/drivers/amlogic/drm/meson_vpu.c +++ b/drivers/amlogic/drm/meson_vpu.c @@ -256,9 +256,6 @@ static struct osd_device_data_s osd_tm2 = { .osd0_sc_independ = 1, }; struct osd_device_data_s osd_meson_dev; -static u32 logo_memsize; -static struct page *logo_page; -static struct delayed_work osd_dwork; static struct platform_device *gp_dev; static unsigned long gem_mem_start, gem_mem_size; @@ -350,6 +347,28 @@ char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode) return NULL; } +bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode) +{ + int i; + + if (!mode || !outputmode) + return false; + if (!strcmp(mode->name, "panel")) + return true; + + for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) { + if (!strcmp(am_vout_modes[i].name, outputmode) && + am_vout_modes[i].width == mode->hdisplay && + am_vout_modes[i].height == mode->vdisplay && + am_vout_modes[i].vrefresh == mode->vrefresh && + am_vout_modes[i].flags == + (mode->flags & DRM_MODE_FLAG_INTERLACE)) { + return true; + } + } + return false; +} + void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc) { unsigned long flags; @@ -390,18 +409,43 @@ static irqreturn_t am_meson_vpu_irq(int irq, void *arg) return IRQ_HANDLED; } -static void mem_free_work(struct work_struct *work) +void am_meson_free_logo_memory(void) { - if (logo_memsize > 0) { + phys_addr_t logo_addr = page_to_phys(logo.logo_page); + + if (logo.size > 0) { #ifdef CONFIG_CMA - pr_info("%s, free memory: addr:0x%x\n", - __func__, logo_memsize); + DRM_INFO("%s, free memory: addr:0x%pa,size:0x%x\n", + __func__, &logo_addr, logo.size); dma_release_from_contiguous(&gp_dev->dev, - logo_page, - logo_memsize >> PAGE_SHIFT); + logo.logo_page, + logo.size >> PAGE_SHIFT); #endif } + logo.alloc_flag = 0; +} + +static int am_meson_logo_info_update(struct meson_drm *priv) +{ + logo.start = page_to_phys(logo.logo_page); + logo.alloc_flag = 1; + /*config 1080p logo as default*/ + if (!logo.width || !logo.height) { + logo.width = 1920; + logo.height = 1080; + } + if (!logo.bpp) + logo.bpp = 16; + if (!logo.outputmode_t) { + strcpy(logo.outputmode, "1080p60hz"); + } else { + strncpy(logo.outputmode, logo.outputmode_t, VMODE_NAME_LEN_MAX); + logo.outputmode[VMODE_NAME_LEN_MAX - 1] = '\0'; + } + priv->logo = &logo; + + return 0; } static int am_meson_vpu_bind(struct device *dev, @@ -418,7 +462,7 @@ static int am_meson_vpu_bind(struct device *dev, int ret, irq; /* Allocate crtc struct */ - pr_info("[%s] in\n", __func__); + DRM_INFO("[%s] in\n", __func__); amcrtc = devm_kzalloc(dev, sizeof(*amcrtc), GFP_KERNEL); if (!amcrtc) @@ -434,34 +478,40 @@ static int am_meson_vpu_bind(struct device *dev, ret = of_reserved_mem_device_init(&pdev->dev); if (ret != 0) { dev_err(dev, "failed to init reserved memory\n"); + } else { #ifdef CONFIG_CMA gp_dev = pdev; cma = dev_get_cma_area(&pdev->dev); if (cma) { - logo_memsize = cma_get_size(cma); - pr_info("reserved memory base:0x%x, size:0x%x\n", - (u32)cma_get_base(cma), logo_memsize); - if (logo_memsize > 0) { - logo_page = + logo.size = cma_get_size(cma); + DRM_INFO("reserved memory base:0x%x, size:0x%x\n", + (u32)cma_get_base(cma), logo.size); + if (logo.size > 0) { + logo.logo_page = dma_alloc_from_contiguous(&pdev->dev, - logo_memsize >> + logo.size >> PAGE_SHIFT, 0); - if (!logo_page) { - pr_err("allocate buffer failed:%d\n", - logo_memsize); - } + if (!logo.logo_page) + DRM_INFO("allocate buffer failed\n"); + else + am_meson_logo_info_update(private); } } else { - pr_info("------ NO CMA\n"); + DRM_INFO("------ NO CMA\n"); } #endif - } else { - dma_declare_coherent_memory(drm_dev->dev, gem_mem_start, - gem_mem_start, gem_mem_size, - DMA_MEMORY_EXCLUSIVE); - pr_info("meson drm mem_start = 0x%x, size = 0x%x\n", - (u32)gem_mem_start, (u32)gem_mem_size); + if (gem_mem_start) { + dma_declare_coherent_memory(drm_dev->dev, + gem_mem_start, + gem_mem_start, + gem_mem_size, + DMA_MEMORY_EXCLUSIVE); + pr_info("meson drm mem_start = 0x%x, size = 0x%x\n", + (u32)gem_mem_start, (u32)gem_mem_size); + } else { + DRM_INFO("------ NO reserved dma\n"); + } } ret = am_meson_plane_create(private); @@ -495,10 +545,7 @@ static int am_meson_vpu_bind(struct device *dev, return ret; disable_irq(amcrtc->vblank_irq); - - INIT_DELAYED_WORK(&osd_dwork, mem_free_work); - schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000)); - pr_info("[%s] out\n", __func__); + DRM_INFO("[%s] out\n", __func__); return 0; } diff --git a/drivers/amlogic/drm/meson_vpu.h b/drivers/amlogic/drm/meson_vpu.h index e288a33be97d..f400ee263f3a 100644 --- a/drivers/amlogic/drm/meson_vpu.h +++ b/drivers/amlogic/drm/meson_vpu.h @@ -31,7 +31,10 @@ struct am_vout_mode { unsigned int flags; }; +extern struct am_meson_logo logo; extern struct osd_device_data_s osd_meson_dev; char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode); +void am_meson_free_logo_memory(void); +bool am_meson_crtc_check_mode(struct drm_display_mode *mode, char *outputmode); #endif /* __AM_MESON_VPU_H */ diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.h b/drivers/amlogic/drm/meson_vpu_pipeline.h index 8b26bbd5db23..2ce8d9f2215f 100644 --- a/drivers/amlogic/drm/meson_vpu_pipeline.h +++ b/drivers/amlogic/drm/meson_vpu_pipeline.h @@ -39,7 +39,7 @@ #define MESON_BLOCK_MAX_NAME_LEN 32 /*ratio base for scaler calc;maybe need bigger than 1000*/ #define RATIO_BASE 1000 -#define MESON_OSD_INPUT_W_LIMIT 1920 +#define MESON_OSD_INPUT_W_LIMIT 3840 #define MAX_DIN_NUM 4 #define MAX_DOUT_NUM 2 @@ -169,6 +169,7 @@ struct meson_vpu_osd_layer_info { u32 afbc_inter_format; u32 afbc_en; u32 fb_size; + u32 premult_en; }; struct meson_vpu_osd { @@ -205,6 +206,7 @@ struct meson_vpu_osd_state { int r_mode; u32 plane_index; u32 fb_size; + u32 premult_en; }; struct meson_vpu_afbc { diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c index 96c2579e4c78..c70fcd7693fb 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c @@ -80,6 +80,34 @@ static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic coef0 */ 0xf84d42f9, 0xf84a45f9, 0xf84848f8 }; +static unsigned int __osd_filter_coefs_2point_binilear[] = { + /* 2 point bilinear, bank_length == 2 coef2 */ + 0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, 0x78080000, 0x760a0000, + 0x740c0000, 0x720e0000, 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000, + 0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, 0x60200000, 0x5e220000, + 0x5c240000, 0x5a260000, 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000, + 0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, 0x48380000, 0x463a0000, + 0x443c0000, 0x423e0000, 0x40400000 +}; + +static unsigned int __osd_filter_coefs_4point_triangle[] = { + 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, + 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, + 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, + 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, + 0x18382808, 0x18382808, 0x17372909, 0x17372909, + 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, + 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, + 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, + 0x10303010 +}; + +static unsigned int *osd_scaler_filter_table[] = { + __osd_filter_coefs_bicubic, + __osd_filter_coefs_2point_binilear, + __osd_filter_coefs_4point_triangle +}; + /*********vsc config begin**********/ /*vsc phase_step=(v_in << 20)/v_out */ void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step) @@ -309,7 +337,7 @@ void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end) *1:config horizontal coef *0:config vertical coef */ -void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag) +void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag, u32 *coef) { u8 i; @@ -320,8 +348,7 @@ void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag) (flag << 8) | (0 << 0)/*coef index 7bits*/); for (i = 0; i < 33; i++) - VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef, - __osd_filter_coefs_bicubic[i]); + VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef, coef[i]); } /*********sc top ctrl end************/ static void f2v_get_vertical_phase( @@ -381,6 +408,8 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg, u32 width_out = scaler_state->output_width; u32 height_out = scaler_state->output_height; u32 scan_mode_out = scaler_state->scan_mode_out; + u32 vsc_double_line_mode; + u32 *coef_h, *coef_v; bool scaler_enable; if (width_in == width_out && height_in == height_out && @@ -389,10 +418,13 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg, else scaler_enable = true; - if (width_out > linebuffer) + if (width_in > linebuffer) { vsc_bank_length = bank_length >> 1; - else + vsc_double_line_mode = 1; + } else { vsc_bank_length = bank_length; + vsc_double_line_mode = 0; + } hsc_init_rec_num = bank_length; hsc_bank_length = bank_length; hsc_init_rpt_p0_num = bank_length / 2 - 1; @@ -432,6 +464,17 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg, phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS); phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out; phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS); + /*check coef*/ + if (scan_mode_out && width_out <= 720) { + coef_h = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE]; + coef_v = osd_scaler_filter_table[COEFS_4POINT_TRIANGLE]; + } else if (vsc_double_line_mode == 1) { + coef_h = osd_scaler_filter_table[COEFS_BICUBIC]; + coef_v = osd_scaler_filter_table[COEFS_2POINT_BINILEAR]; + } else { + coef_h = osd_scaler_filter_table[COEFS_BICUBIC]; + coef_v = osd_scaler_filter_table[COEFS_BICUBIC]; + } /*input size config*/ osd_sc_in_h_set(reg, height_in); @@ -449,13 +492,14 @@ void osd_scaler_config(struct osd_scaler_reg_s *reg, osd_sc_dummy_data_set(reg, 0x80808080); /*h/v coef config*/ - osd_sc_coef_set(reg, 1); - osd_sc_coef_set(reg, 0); + osd_sc_coef_set(reg, OSD_SCALER_COEFF_H, coef_h); + osd_sc_coef_set(reg, OSD_SCALER_COEFF_V, coef_v); /*init recv line num*/ osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num); osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num); osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num); + osd_vsc_double_line_mode_set(reg, vsc_double_line_mode); /*repeate line0 num*/ osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num); @@ -650,9 +694,6 @@ static void scaler_hw_init(struct meson_vpu_block *vblk) scaler->reg = &osd_scaler_reg[vblk->index]; scaler->linebuffer = OSD_SCALE_LINEBUFFER; scaler->bank_length = OSD_SCALE_BANK_LENGTH; - /*disable sc*/ - osd_sc_en_set(scaler->reg, 0); - osd_sc_path_en_set(scaler->reg, 0); DRM_DEBUG("%s hw_init called.\n", scaler->base.name); } diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h index 34ebb03906ee..91b3d730a669 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h +++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h @@ -79,6 +79,15 @@ #define OSD_ZOOM_TOTAL_BITS 24 #define OSD_PHASE_BITS 16 +#define OSD_SCALER_COEFF_H 1 +#define OSD_SCALER_COEFF_V 0 + +enum scaler_coef_e { + COEFS_BICUBIC = 0, + COEFS_2POINT_BINILEAR, + COEFS_4POINT_TRIANGLE +}; + enum f2v_vphase_type_e { F2V_IT2IT = 0, F2V_IB2IB, diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c index 487dfe088ede..7b733cb8508e 100644 --- a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c +++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c @@ -227,6 +227,14 @@ void osd_block_enable(struct osd_mif_reg_s *reg, bool flag) VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1); } +/*osd alpha_div en + *if input is premult,alpha_div=1,else alpha_div=0 + */ +void osd_alpha_div_enable(struct osd_mif_reg_s *reg, bool flag) +{ + VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_mali_unpack_ctrl, flag, 28, 1); +} + /*osd ctrl config*/ void osd_ctrl_set(struct osd_mif_reg_s *reg) { @@ -354,6 +362,7 @@ static int osd_check_state(struct meson_vpu_block *vblk, mvos->phy_addr = plane_info->phy_addr; mvos->pixel_format = plane_info->pixel_format; mvos->fb_size = plane_info->fb_size; + mvos->premult_en = plane_info->premult_en; return 0; } @@ -371,6 +380,7 @@ static void osd_set_state(struct meson_vpu_block *vblk, u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr; struct osd_scope_s scope_src = {0, 1919, 0, 1079}; struct osd_mif_reg_s *reg = osd->reg; + bool alpha_div_en; crtc = vblk->pipeline->crtc; amc = to_am_meson_crtc(crtc); @@ -379,6 +389,7 @@ static void osd_set_state(struct meson_vpu_block *vblk, DRM_DEBUG("set_state break for NULL.\n"); return; } + alpha_div_en = mvos->premult_en ? 1 : 0; src_h = mvos->src_h; byte_stride = mvos->byte_stride; phy_addr = mvos->phy_addr; @@ -388,12 +399,15 @@ static void osd_set_state(struct meson_vpu_block *vblk, scope_src.v_end = mvos->src_y + mvos->src_h - 1; pixel_format = mvos->pixel_format; canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]]; + /*Toto: need to separate*/ + osd_ctrl_set(osd->reg); canvas_config(canvas_index, phy_addr, byte_stride, src_h, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); osd_canvas_index[vblk->index] ^= 1; osd_canvas_config(reg, canvas_index); osd_input_size_config(reg, scope_src); osd_color_config(reg, pixel_format); + osd_alpha_div_enable(reg, alpha_div_en); DRM_DEBUG("plane_index=%d,HW-OSD=%d\n", mvos->plane_index, vblk->index); DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n", @@ -519,7 +533,6 @@ static void osd_hw_init(struct meson_vpu_block *vblk) return; } osd->reg = &osd_mif_reg[vblk->index]; - osd_ctrl_set(osd->reg); DRM_DEBUG("%s hw_init done.\n", osd->base.name); } diff --git a/drivers/amlogic/input/keyboard/gpio_keypad.c b/drivers/amlogic/input/keyboard/gpio_keypad.c index 585f40f6c71c..399e1ae09f65 100644 --- a/drivers/amlogic/input/keyboard/gpio_keypad.c +++ b/drivers/amlogic/input/keyboard/gpio_keypad.c @@ -256,6 +256,10 @@ static int meson_gpio_kp_probe(struct platform_device *pdev) return -EINVAL; } } + //get all gpio desc. + desc = devm_gpiod_get_index(&pdev->dev, "key", i, GPIOD_IN); + if (IS_ERR_OR_NULL(desc)) + return -EINVAL; keypad->key[i].desc = desc; //The gpio default is high level. keypad->key[i].current_status = 1; diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.c index 5e8cd663e4e6..076b22bfe66e 100644 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.c +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.c @@ -492,8 +492,19 @@ static int fts_input_dev_report_b(struct ts_event *event, struct fts_ts_data *da } input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]); - input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]); - input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]); + if (data->pdata->rotation) { + input_report_abs(data->input_dev, ABS_MT_POSITION_X, + data->pdata->x_max - event->au16_y[i]); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, + event->au16_x[i]); + + } else { + input_report_abs(data->input_dev, ABS_MT_POSITION_X, + event->au16_x[i]); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, + event->au16_y[i]); + } + touchs |= BIT(event->au8_finger_id[i]); data->touchs |= BIT(event->au8_finger_id[i]); @@ -994,10 +1005,15 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) rc = of_property_read_u32(np, "y_max", &temp_val); if (!rc) { - pdata->x_max = temp_val; - FTS_DEBUG("y_max=%d", pdata->x_max); + pdata->y_max = temp_val; + FTS_DEBUG("y_max=%d", pdata->y_max); } + rc = of_property_read_u32(np, "rotation", &temp_val); + if (!rc) { + pdata->rotation = temp_val; + FTS_DEBUG("rotation = %d", pdata->rotation); + } FTS_FUNC_EXIT(); return 0; diff --git a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.h index d9ca8b037510..a18ec47e6387 100644 --- a/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.h +++ b/drivers/amlogic/input/touchscreen/focaltech_touch/focaltech_core.h @@ -109,20 +109,21 @@ struct fts_ts_platform_data { - s32 irq_gpio; - u32 irq_gpio_flags; - s32 reset_gpio; - u32 reset_gpio_flags; - bool have_key; - u32 key_number; - u32 keys[4]; - u32 key_y_coord; - u32 key_x_coords[4]; - u32 x_max; - u32 y_max; - u32 x_min; - u32 y_min; - u32 max_touch_number; + s32 irq_gpio; + u32 irq_gpio_flags; + s32 reset_gpio; + u32 reset_gpio_flags; + bool have_key; + u32 key_number; + u32 keys[4]; + u32 key_y_coord; + u32 key_x_coords[4]; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 max_touch_number; + u32 rotation; }; struct ts_event diff --git a/drivers/amlogic/media/Kconfig b/drivers/amlogic/media/Kconfig index 46220fa252dc..6159286a38d6 100644 --- a/drivers/amlogic/media/Kconfig +++ b/drivers/amlogic/media/Kconfig @@ -89,6 +89,7 @@ source "drivers/amlogic/media/vout/Kconfig" source "drivers/amlogic/media/osd/Kconfig" source "drivers/amlogic/media/osd_ext/Kconfig" source "drivers/amlogic/media/deinterlace/Kconfig" +source "drivers/amlogic/media/di_multi/Kconfig" source "drivers/amlogic/media/di_local/Kconfig" source "drivers/amlogic/media/vin/Kconfig" source "drivers/amlogic/media/video_processor/Kconfig" diff --git a/drivers/amlogic/media/Makefile b/drivers/amlogic/media/Makefile index c72ece4cdd37..fe43ed79907f 100644 --- a/drivers/amlogic/media/Makefile +++ b/drivers/amlogic/media/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_AMLOGIC_MEDIA_FB) += osd/ obj-$(CONFIG_AMLOGIC_MEDIA_FB_EXT) += osd_ext/ obj-$(CONFIG_AMLOGIC_VOUT) += vout/ obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += deinterlace/ +obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_multi/ obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di_local/ obj-$(CONFIG_AMLOGIC_MEDIA_VIN) += vin/ obj-$(CONFIG_AMLOGIC_MEDIA_VIDEO_PROCESSOR) += video_processor/ diff --git a/drivers/amlogic/media/common/canvas/canvas_mgr.c b/drivers/amlogic/media/common/canvas/canvas_mgr.c index db416df15659..d1b65d93d9a3 100644 --- a/drivers/amlogic/media/common/canvas/canvas_mgr.c +++ b/drivers/amlogic/media/common/canvas/canvas_mgr.c @@ -516,8 +516,8 @@ static void canvas_pool_config(void) canvas_pool_register_const_canvas(0, 0x25, "amvdec"); canvas_pool_register_const_canvas(0x26, 0x39, "vdin"); canvas_pool_register_const_canvas(0x78, 0xbf, "amvdec"); - canvas_pool_register_const_canvas(0x60, 0x65, "display"); - canvas_pool_register_const_canvas(0x66, 0x6b, "display2"); + canvas_pool_register_const_canvas(0x58, 0x6f, "display"); + /* canvas_pool_register_const_canvas(0x66, 0x6b, "display2"); */ canvas_pool_register_const_canvas(0x70, 0x77, "ppmgr"); canvas_pool_register_const_canvas(0xe4, 0xef, "encoder"); canvas_pool_register_const_canvas(0x40, 0x48, "osd"); diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index 33466a84ceaa..0717b4e0ae42 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -800,6 +800,11 @@ void codec_mm_release(struct codec_mm_s *mem, const char *owner) return; spin_lock_irqsave(&mgt->lock, flags); + if (!codec_mm_valid_mm_locked(mem)) { + pr_err("codec mm not valied!\n"); + spin_unlock_irqrestore(&mgt->lock, flags); + return; + } index = atomic_dec_return(&mem->use_cnt); max_owner = mem->owner[index]; for (i = 0; i < index; i++) { diff --git a/drivers/amlogic/media/common/ge2d/fillrect.c b/drivers/amlogic/media/common/ge2d/fillrect.c index 00d56101d79b..8c0369fa20ea 100644 --- a/drivers/amlogic/media/common/ge2d/fillrect.c +++ b/drivers/amlogic/media/common/ge2d/fillrect.c @@ -54,6 +54,7 @@ static void _fillrect(struct ge2d_context_s *wq, ge2d_cmd_cfg->alpha_blend_mode = OPERATION_LOGIC; ge2d_cmd_cfg->alpha_logic_op = LOGIC_OPERATION_COPY; ge2d_cmd_cfg->wait_done_flag = 1; + ge2dgen_disable_matrix(wq); ge2d_wq_add_work(wq); } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c index e397caa1fc2e..c5502f25f212 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c @@ -102,9 +102,9 @@ static void aml_dma_put(void *buf_priv) buf->vaddr = NULL; clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); - kfree(buf); ge2d_log_dbg("ge2d free:aml_dma_buf=0x%p,buf->index=%d\n", buf, buf->index); + kfree(buf); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -129,6 +129,7 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, if (cma_pages) { paddr = page_to_phys(cma_pages); } else { + kfree(buf); pr_err("failed to alloc cma pages.\n"); return NULL; } @@ -148,7 +149,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) { struct aml_dma_buf *buf = buf_priv; unsigned long pfn = 0; - unsigned long vsize = vma->vm_end - vma->vm_start; + unsigned long vsize; int ret = -1; if (!buf || !vma) { @@ -156,6 +157,8 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) return -EINVAL; } + vsize = vma->vm_end - vma->vm_start; + pfn = buf->dma_addr >> PAGE_SHIFT; ret = remap_pfn_range(vma, vma->vm_start, pfn, vsize, vma->vm_page_prot); @@ -206,11 +209,6 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, for_each_sg(sgt->sgl, sg, sgt->nents, i) { struct page *page = phys_to_page(phys); - if (!page) { - sg_free_table(sgt); - kfree(attach); - return -ENOMEM; - } sg_set_page(sg, page, PAGE_SIZE, 0); phys += PAGE_SIZE; } diff --git a/drivers/amlogic/media/common/ge2d/ge2d_main.c b/drivers/amlogic/media/common/ge2d/ge2d_main.c index 48a5940e4a40..3af17151f87a 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_main.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_main.c @@ -260,7 +260,7 @@ static int ge2d_ioctl_config_ex_mem(struct ge2d_context_s *context, ge2d_config_ex_mem = &(ge2d_para_config.para_config_memtype); if (ge2d_para_config.para_config_memtype.ge2d_magic - == sizeof(struct config_para_ex_memtype_s)) { + == sizeof(struct compat_config_para_ex_memtype_s)) { struct config_para_ex_ion_s *pge2d_config_ex; uf_ex_mem = diff --git a/drivers/amlogic/media/common/ge2d/ge2d_wq.c b/drivers/amlogic/media/common/ge2d/ge2d_wq.c index 3e35319206f3..b775f27684a9 100644 --- a/drivers/amlogic/media/common/ge2d/ge2d_wq.c +++ b/drivers/amlogic/media/common/ge2d/ge2d_wq.c @@ -806,7 +806,7 @@ static int build_ge2d_config(struct ge2d_context_s *context, update_canvas_cfg(canvas_cfg, cfg->dst_planes[i].addr, cfg->dst_planes[i].w * - src->bpp / 8, + dst->bpp / 8, cfg->dst_planes[i].h); } } @@ -824,7 +824,8 @@ static int setup_display_property(struct src_dst_para_s *src_dst, int index) u32 cs_width = 0, cs_height = 0, cs_addr = 0; unsigned int data32; unsigned int bpp; - unsigned int block_mode[] = {2, 4, 8, 16, 16, 32, 0, 24}; + unsigned int block_mode[] = {2, 4, 8, 16, 16, 32, 0, 24, + 0, 0, 0, 0, 0, 0, 0, 0}; src_dst->canvas_index = index; if (ge2d_meson_dev.canvas_status == 0) { diff --git a/drivers/amlogic/media/common/ge2d/ge2dgen.c b/drivers/amlogic/media/common/ge2d/ge2dgen.c index aad11e720a6c..c3dbbb2360b6 100644 --- a/drivers/amlogic/media/common/ge2d/ge2dgen.c +++ b/drivers/amlogic/media/common/ge2d/ge2dgen.c @@ -430,3 +430,11 @@ void ge2dgen_const_color(struct ge2d_context_s *wq, wq->config.update_flag |= UPDATE_DP_GEN; } } + +void ge2dgen_disable_matrix(struct ge2d_context_s *wq) +{ + struct ge2d_dp_gen_s *dp_gen_cfg = ge2d_wq_get_dp_gen(wq); + + dp_gen_cfg->conv_matrix_en = 0; + wq->config.update_flag |= UPDATE_DP_GEN; +} diff --git a/drivers/amlogic/media/common/ge2d/ge2dgen.h b/drivers/amlogic/media/common/ge2d/ge2dgen.h index 35e5739f2873..3d9c894633ea 100644 --- a/drivers/amlogic/media/common/ge2d/ge2dgen.h +++ b/drivers/amlogic/media/common/ge2d/ge2dgen.h @@ -84,6 +84,6 @@ void ge2dgen_cb(struct ge2d_context_s *wq, void ge2dgen_const_color(struct ge2d_context_s *wq, unsigned int color); - +void ge2dgen_disable_matrix(struct ge2d_context_s *wq); #endif diff --git a/drivers/amlogic/media/common/rdma/rdma.c b/drivers/amlogic/media/common/rdma/rdma.c index 21fece89cea2..059c08ffe9b4 100644 --- a/drivers/amlogic/media/common/rdma/rdma.c +++ b/drivers/amlogic/media/common/rdma/rdma.c @@ -254,8 +254,8 @@ static void line_n_int_rdma_irq(void *arg) force_rdma_config[LINE_N_INT_RDMA] = 1; else force_rdma_config[LINE_N_INT_RDMA] = 0; - rdma_done[VSYNC_RDMA] = true; - irq_count[VSYNC_RDMA]++; + rdma_done[LINE_N_INT_RDMA] = true; + irq_count[LINE_N_INT_RDMA]++; } u32 VSYNC_RD_MPEG_REG(u32 adr) @@ -428,8 +428,10 @@ static int __init rdma_init(void) { second_rdma_feature = 0; +#if 0 /*def LINE_INT_WORK_AROUND */ if (is_meson_g12b_revb()) second_rdma_feature = 1; +#endif cur_enable[VSYNC_RDMA] = 0; enable[VSYNC_RDMA] = 1; diff --git a/drivers/amlogic/media/common/rdma/rdma_mgr.c b/drivers/amlogic/media/common/rdma/rdma_mgr.c index 79e2d35ae94a..4b0a57f6eb90 100644 --- a/drivers/amlogic/media/common/rdma/rdma_mgr.c +++ b/drivers/amlogic/media/common/rdma/rdma_mgr.c @@ -107,11 +107,18 @@ struct rdma_instance_s { int prev_trigger_type; }; +#define MAX_CONFLICT 32 +struct rdma_conflict_regs_s { + u32 adr[MAX_CONFLICT]; + u32 val[MAX_CONFLICT]; +}; + struct rdma_device_info { const char *device_name; struct platform_device *rdma_dev; struct class *clsp; struct rdma_instance_s rdma_ins[RDMA_NUM]; + struct rdma_conflict_regs_s rdma_reg; }; static struct rdma_device_data_s rdma_meson_dev; @@ -360,6 +367,7 @@ irqreturn_t rdma_mgr_isr(int irq, void *dev_id) int retry_count = 0; u32 rdma_status; int i; + u32 read_val; if (debug_flag & 0x10) return IRQ_HANDLED; rdma_isr_count++; @@ -399,6 +407,13 @@ QUERY: if ((rdma_status & 0xff000000) && (retry_count < 100)) goto QUERY; #endif + for (i = 0; i < MAX_CONFLICT; i++) { + if (info->rdma_reg.adr[i]) { + read_val = READ_VCBUS_REG(info->rdma_reg.adr[i]); + if (read_val == info->rdma_reg.val[i]) + info->rdma_reg.adr[i] = 0; + } + } return IRQ_HANDLED; } @@ -622,19 +637,30 @@ u32 rdma_read_reg(int handle, u32 adr) int i, j = 0; u32 *write_table; int match = 0; + int match_oth = 0; int read_from = 0; struct rdma_device_info *info = &rdma_info; struct rdma_instance_s *ins = &info->rdma_ins[handle]; u32 read_val = READ_VCBUS_REG(adr); - for (i = (ins->rdma_item_count - 1); i >= 0; i--) { - if (ins->reg_buf[i << 1] == adr) { - read_val = ins->reg_buf[(i << 1) + 1]; - match = 1; - read_from = 1; + for (i = 0; i < MAX_CONFLICT; i++) { + if (info->rdma_reg.adr[i] == adr) { + read_val = info->rdma_reg.val[i]; + match_oth = 1; + read_from = 3; break; } } + if (!match_oth) { + for (i = (ins->rdma_item_count - 1); i >= 0; i--) { + if (ins->reg_buf[i << 1] == adr) { + read_val = ins->reg_buf[(i << 1) + 1]; + match = 1; + read_from = 1; + break; + } + } + } if (!match) { write_table = ins->rdma_table_addr; for (i = (ins->rdma_write_count - 1); @@ -650,7 +676,13 @@ u32 rdma_read_reg(int handle, u32 adr) if (rdma_trace_enable) { for (j = 0; j < rdma_trace_num; j++) { if (adr == rdma_trace_reg[j]) { - if (read_from == 2) + if (read_from == 3) + pr_info("(%s) handle %d, %04x=0x%08x from conflict table(%d)\n", + __func__, + handle, adr, + read_val, + ins->rdma_write_count); + else if (read_from == 2) pr_info("(%s) handle %d, %04x=0x%08x from write table(%d)\n", __func__, handle, adr, @@ -704,6 +736,71 @@ int rdma_watchdog_setting(int flag) } EXPORT_SYMBOL(rdma_watchdog_setting); +static bool rdma_check_conflict(int handle, u32 adr, u32 *read_val) +{ + struct rdma_instance_s *oth_ins; + int i, j, k, n; + + for (i = 0; i < MAX_CONFLICT; i++) { + if (rdma_info.rdma_reg.adr[i] == adr) { + if (read_val != NULL) + *read_val = rdma_info.rdma_reg.val[i]; + return true; + } + } + + for (i = 0; i < RDMA_NUM; i++) { + oth_ins = &rdma_info.rdma_ins[i]; + if ((!oth_ins->rdma_table_size) + || (!oth_ins->rdma_item_count) + || (i == handle)) + continue; + for (j = 0; j < oth_ins->rdma_item_count; j++) { + if (oth_ins->reg_buf[j << 1] != adr) + continue; + for (n = 0; n < rdma_trace_num; n++) { + if ((adr == rdma_trace_reg[n]) || + (debug_flag & 0x20)) + pr_info( + "(%s) handle %d, conflict write %04x=0x%08x (oth handle %d)\n", + __func__, + handle, adr, + oth_ins->reg_buf[(j << 1) + 1], + i); + } + for (k = 0; k < MAX_CONFLICT; k++) { + if (!rdma_info.rdma_reg.adr[i]) { + rdma_info.rdma_reg.adr[k] = adr; + rdma_info.rdma_reg.val[k] = + oth_ins->reg_buf[(j << 1) + 1]; + if (read_val != NULL) + *read_val = oth_ins-> + reg_buf[(j << 1) + 1]; + return true; + } + } + } + } + return false; +} + +static void rdma_update_conflict(u32 adr, u32 val) +{ + int i; + + for (i = 0; i < MAX_CONFLICT; i++) { + if (rdma_info.rdma_reg.adr[i] == adr) { + rdma_info.rdma_reg.val[i] = val; + if (debug_flag & 0x20) + pr_info( + "(%s) %04x=0x%08x\n", + __func__, + adr, val); + break; + } + } +} + int rdma_write_reg(int handle, u32 adr, u32 val) { struct rdma_device_info *info = &rdma_info; @@ -716,6 +813,9 @@ int rdma_write_reg(int handle, u32 adr, u32 val) if (debug_flag & 1) pr_info("rdma_write(%d) %d(%x)<=%x\n", handle, ins->rdma_item_count, adr, val); + if (rdma_check_conflict(handle, adr, NULL)) + rdma_update_conflict(adr, val); + if (((ins->rdma_item_count << 1) + 1) < (ins->rdma_table_size / sizeof(u32))) { ins->reg_buf[ins->rdma_item_count << 1] = adr; @@ -755,20 +855,30 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len) int i, j = 0; u32 *write_table; int match = 0; + int match_oth = 0; int read_from = 0; struct rdma_device_info *info = &rdma_info; struct rdma_instance_s *ins = &info->rdma_ins[handle]; u32 read_val = READ_VCBUS_REG(adr); + u32 oth_val = 0; u32 write_val; if (ins->rdma_table_size == 0) return -1; + if (rdma_check_conflict(handle, adr, &oth_val)) { + match_oth = 1; + read_val = oth_val; + read_from = 3; + } + for (i = (ins->rdma_item_count - 1); i >= 0; i--) { if (ins->reg_buf[i << 1] == adr) { - read_val = ins->reg_buf[(i << 1) + 1]; match = 1; - read_from = 1; + if (!match_oth) { + read_val = ins->reg_buf[(i << 1) + 1]; + read_from = 1; + } break; } } @@ -777,40 +887,48 @@ int rdma_write_reg_bits(int handle, u32 adr, u32 val, u32 start, u32 len) for (i = (ins->rdma_write_count - 1); i >= 0; i--) { if (write_table[i << 1] == adr) { - read_val = - write_table[(i << 1) + 1]; - read_from = 2; + if (!match_oth) { + read_val = + write_table[(i << 1) + 1]; + read_from = 2; + } break; } } } write_val = (read_val & ~(((1L<<(len))-1)<<(start))) |((unsigned int)(val) << (start)); - - if (rdma_trace_enable) { - for (j = 0; j < rdma_trace_num; j++) { - if (adr == rdma_trace_reg[j]) { - if (read_from == 2) - pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from write table(%d)\n", - __func__, - handle, adr, - read_val, - write_val, - ins->rdma_write_count); - else if (read_from == 1) - pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from item table(%d)\n", - __func__, - handle, adr, - read_val, - write_val, - ins->rdma_item_count); - else - pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from real reg\n", - __func__, - handle, adr, - read_val, - write_val); - } + if (match_oth) + rdma_update_conflict(adr, write_val); + for (j = 0; j < rdma_trace_num; j++) { + if (adr == rdma_trace_reg[j]) { + if (read_from == 3) + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from conflict table(%d)\n", + __func__, + handle, adr, + read_val, + write_val, + ins->rdma_write_count); + else if (read_from == 2) + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from write table(%d)\n", + __func__, + handle, adr, + read_val, + write_val, + ins->rdma_write_count); + else if (read_from == 1) + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from item table(%d)\n", + __func__, + handle, adr, + read_val, + write_val, + ins->rdma_item_count); + else + pr_info("(%s) handle %d, %04x=0x%08x->0x%08x from real reg\n", + __func__, + handle, adr, + read_val, + write_val); } } if (match) { @@ -1035,6 +1153,7 @@ static int rdma_probe(struct platform_device *pdev) rdma_mgr_irq_request = 0; + memset((void *)&info->rdma_reg, 0, sizeof(struct rdma_conflict_regs_s)); for (i = 0; i < RDMA_NUM; i++) { info->rdma_ins[i].rdma_table_size = 0; if (rdma_meson_dev.rdma_ver == RDMA_VER_1) @@ -1081,12 +1200,15 @@ static int rdma_probe(struct platform_device *pdev) NULL, RDMA_TABLE_SIZE); set_rdma_handle(VSYNC_RDMA, handle); +#if 0 /*def LINE_INT_WORK_AROUND */ if (is_meson_g12b_revb()) { pr_info("g12b revb!!!!\n"); handle = rdma_register(get_rdma_ops(LINE_N_INT_RDMA), NULL, RDMA_TABLE_SIZE); set_rdma_handle(LINE_N_INT_RDMA, handle); } +#endif + info->clsp = class_create(THIS_MODULE, RDMA_MGR_CLASS_NAME); if (IS_ERR(info->clsp)) { diff --git a/drivers/amlogic/media/common/vfm/vfm.c b/drivers/amlogic/media/common/vfm/vfm.c index a2da827fc9e0..7c0e73d19e28 100644 --- a/drivers/amlogic/media/common/vfm/vfm.c +++ b/drivers/amlogic/media/common/vfm/vfm.c @@ -139,6 +139,8 @@ int vfm_map_remove(char *id) int index; int ret = 0; + if (IS_ERR_OR_NULL(id)) + return -1; if (!strcmp(id, "all")) { for (i = 0; i < vfm_map_num; i++) { if (vfm_map[i]) @@ -157,45 +159,56 @@ int vfm_map_add(char *id, char *name_chain) { int i, j; int ret = -1; - char *ptr, *token = NULL; + char *ptr = NULL, *token = NULL; struct vfm_map_s *p; int old_num = vfm_map_num; unsigned long flags; int add_ok = 0; int cnt = 10; + ulong addr; p = kmalloc(sizeof(struct vfm_map_s), GFP_KERNEL); + if (!p) { pr_err("%s: Error, map no mem!!\n", __func__); return -ENOMEM; } + ptr = kstrdup(name_chain, GFP_KERNEL); + addr = (ulong)ptr; + if (!ptr) { + kfree(p); + return -ENOMEM; + } + memset(p, 0, sizeof(struct vfm_map_s)); - if (strlen(id) >= sizeof(p->id)) { - memcpy(p->id, id, sizeof(p->id)); - p->id[sizeof(p->id)-1] = '\0'; - } else + if (strlen(id) >= VFM_NAME_LEN - 1) { + memcpy(p->id, id, VFM_NAME_LEN - 1); + p->id[VFM_NAME_LEN - 1] = '\0'; + } else { memcpy(p->id, id, strlen(id)); + } p->valid = 1; - ptr = name_chain; do { token = strsep(&ptr, "\n "); - if (token == NULL) + if (!token) break; if (*token == '\0') continue; - if (strlen(token) >= sizeof(p->name[p->vfm_map_size])) { + if (p->vfm_map_size >= VFM_MAP_SIZE) + break; + if (strlen(token) >= VFM_NAME_LEN - 1) { memcpy(p->name[p->vfm_map_size], token, - sizeof(p->name[p->vfm_map_size])); - p->name[p->vfm_map_size][ - sizeof(p->name[p->vfm_map_size])-1] = '\0'; - } else + VFM_NAME_LEN - 1); + p->name[p->vfm_map_size][VFM_NAME_LEN - 1] = '\0'; + } else { memcpy(p->name[p->vfm_map_size], token, strlen(token)); + } p->vfm_map_size++; } while (token && cnt--); cnt = 10; /*limit the cnt of retry to avoid the infinite loop*/ - + kfree((void *)addr); retry: for (i = 0; i < vfm_map_num; i++) { struct vfm_map_s *pi = vfm_map[i]; @@ -349,53 +362,53 @@ static void vfm_init(void) { #if ((defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER) && \ (defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE)) - char def_id[] = "default"; + char def_id[VFM_NAME_LEN] = "default"; #ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC char def_name_chain[] = "decoder ppmgr deinterlace amvideo"; #else char def_name_chain[] = "decoder amvideo"; #endif #elif (defined CONFIG_AMLOGIC_POST_PROCESS_MANAGER) - char def_id[] = "default"; + char def_id[VFM_NAME_LEN] = "default"; char def_name_chain[] = "decoder ppmgr amvideo"; #elif (defined CONFIG_AMLOGIC_MEDIA_DEINTERLACE) - char def_id[] = "default"; + char def_id[VFM_NAME_LEN] = "default"; char def_name_chain[] = "decoder deinterlace amvideo"; #else /**/ - char def_id[] = "default"; + char def_id[VFM_NAME_LEN] = "default"; char def_name_chain[] = "decoder amvideo"; #endif /**/ #ifdef CONFIG_TVIN_VIUIN - char def_ext_id[] = "default_ext"; + char def_ext_id[VFM_NAME_LEN] = "default_ext"; char def_ext_name_chain[] = "vdin amvideo2"; #endif /**/ #ifdef CONFIG_VDIN_MIPI - char def_mipi_id[] = "default_mipi"; + char def_mipi_id[VFM_NAME_LEN] = "default_mipi"; char def_mipi_name_chain[] = "vdin mipi"; #endif /**/ #ifdef CONFIG_AMLOGIC_V4L_VIDEO2 - char def_amlvideo2_id[] = "default_amlvideo2"; + char def_amlvideo2_id[VFM_NAME_LEN] = "default_amlvideo2"; char def_amlvideo2_chain[] = "vdin1 amlvideo2.1"; #endif /**/ #if (defined CONFIG_TVIN_AFE) || (defined CONFIG_TVIN_HDMI) #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER - char tvpath_id[] = "tvpath"; + char tvpath_id[VFM_NAME_LEN] = "tvpath"; char tvpath_chain[] = "vdin0 ppmgr deinterlace amvideo"; #else - char tvpath_id[] = "tvpath"; + char tvpath_id[VFM_NAME_LEN] = "tvpath"; char tvpath_chain[] = "vdin0 deinterlace amvideo"; #endif #endif /**/ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - char def_dvbl_id[] = "dvblpath"; + char def_dvbl_id[VFM_NAME_LEN] = "dvblpath"; /* char def_dvbl_chain[] = "dvbldec dvbl amvideo";*/ char def_dvbl_chain[] = "dvbldec amvideo"; - char def_dvel_id[] = "dvelpath"; + char def_dvel_id[VFM_NAME_LEN] = "dvelpath"; char def_dvel_chain[] = "dveldec dvel"; #endif #if 1/*def CONFIG_AM_HDMIIN_DV*/ - char def_dvhdmiin_id[] = "dvhdmiin"; + char def_dvhdmiin_id[VFM_NAME_LEN] = "dvhdmiin"; char def_dvhdmiin_chain[] = "dv_vdin amvideo"; #endif int i; @@ -476,17 +489,20 @@ static inline struct vframe_s *vfm_vf_peek( static void vfm_dump_provider(const char *name) { - struct vframe_provider_s *prov = vf_get_provider_by_name(name); + struct vframe_provider_s *prov; struct vframe_states states; unsigned long flags; struct vframe_s *vf; char *buf, *pbuf; - if (!prov) + if (IS_ERR_OR_NULL(name)) + return; + prov = vf_get_provider_by_name(name); + if (IS_ERR_OR_NULL(prov)) return; buf = kzalloc(0x400, GFP_KERNEL); - if (buf == NULL) + if (!buf) return; pbuf = buf; @@ -738,19 +754,23 @@ static long vfm_ioctl(struct file *file, unsigned int cmd, ulong arg) struct vfmctl *user_argp = (void __user *)arg; struct vfmctl argp; + if (IS_ERR_OR_NULL(user_argp)) + return -EINVAL; memset(&argp, 0, sizeof(struct vfmctl)); switch (cmd) { case VFM_IOCTL_CMD_SET:{ - ret = - copy_from_user(argp.name, user_argp->name, sizeof(argp.name)-1); - ret |= - copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1); + ret = copy_from_user(argp.name, user_argp->name, + sizeof(argp.name) - 1); + argp.name[sizeof(argp.name) - 1] = '\0'; + ret |= copy_from_user(argp.val, user_argp->val, + sizeof(argp.val) - 1); + argp.val[sizeof(argp.val) - 1] = '\0'; if (ret) ret = -EINVAL; else - ret = - vfm_map_store(NULL, NULL, argp.val, sizeof(argp.val) - 1); + ret = vfm_map_store(NULL, NULL, argp.val, + sizeof(argp.val) - 1); } break; case VFM_IOCTL_CMD_GET:{ @@ -766,39 +786,46 @@ static long vfm_ioctl(struct file *file, unsigned int cmd, ulong arg) } break; case VFM_IOCTL_CMD_ADD:{ - ret = - copy_from_user(argp.name, user_argp->name, sizeof(argp.name)-1); - ret |= - copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1); + ret = copy_from_user(argp.name, user_argp->name, + sizeof(argp.name) - 1); + argp.name[sizeof(argp.name) - 1] = '\0'; + ret |= copy_from_user(argp.val, user_argp->val, + sizeof(argp.val) - 1); + argp.val[sizeof(argp.val) - 1] = '\0'; if (ret) ret = -EINVAL; else - ret = vfm_map_add(argp.name, argp.val); + ret = vfm_map_add(argp.name, argp.val); } break; case VFM_IOCTL_CMD_RM:{ - ret = - copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1); + ret = copy_from_user(argp.val, user_argp->val, + sizeof(argp.val) - 1); + argp.val[sizeof(argp.val) - 1] = '\0'; if (ret) ret = -EINVAL; else - ret = vfm_map_remove(argp.val); + ret = vfm_map_remove(argp.val); } break; case VFM_IOCTL_CMD_DUMP:{ - ret = - copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1); + ret = copy_from_user(argp.val, user_argp->val, + sizeof(argp.val) - 1); + argp.val[sizeof(argp.val) - 1] = '\0'; if (ret) ret = -EINVAL; - vfm_dump_provider(argp.val); + else + vfm_dump_provider(argp.val); } break; case VFM_IOCTL_CMD_ADDDUMMY:{ - ret = - copy_from_user(argp.val, user_argp->val, sizeof(argp.val) - 1); + ret = copy_from_user(argp.val, user_argp->val, + sizeof(argp.val) - 1); + argp.val[sizeof(argp.val) - 1] = '\0'; if (ret) ret = -EINVAL; - add_dummy_receiver(argp.val); + else + add_dummy_receiver(argp.val); } break; diff --git a/drivers/amlogic/media/common/vpu/vpu_ctrl.h b/drivers/amlogic/media/common/vpu/vpu_ctrl.h index 30e39dcb3605..2657bc449838 100644 --- a/drivers/amlogic/media/common/vpu/vpu_ctrl.h +++ b/drivers/amlogic/media/common/vpu/vpu_ctrl.h @@ -510,7 +510,9 @@ static struct vpu_ctrl_s vpu_mem_pd_tm2[] = { {VPU_TCON, HHI_VPU_MEM_PD_REG3, 0x3, 16, 16}, {VPU_AXI_WR1, HHI_VPU_MEM_PD_REG4, 0x3, 0, 2}, {VPU_AXI_WR0, HHI_VPU_MEM_PD_REG4, 0x3, 2, 2}, - {VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 4, 4}, + {VPU_AFBCE, HHI_VPU_MEM_PD_REG4, 0x3, 4, 2}, + {VPU_VDIN_WR_MIF2, HHI_VPU_MEM_PD_REG4, 0x3, 6, 2}, + {VPU_DMA, HHI_VPU_MEM_PD_REG4, 0xf, 8, 4}, {VPU_MOD_MAX, VPU_REG_END, 0, 0, 0}, }; diff --git a/drivers/amlogic/media/common/vpu/vpu_module.h b/drivers/amlogic/media/common/vpu/vpu_module.h index 72e1b4fa7c56..ca2e03d9f876 100644 --- a/drivers/amlogic/media/common/vpu/vpu_module.h +++ b/drivers/amlogic/media/common/vpu/vpu_module.h @@ -85,7 +85,8 @@ static char *vpu_mod_table[] = { "axi_wr1", "axi_wr0", "afbce", - "dma" + "vdin_wr_mif2", + "dma", "vpu_mod_max", diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index b2154f0737c7..992b25b3985a 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -118,6 +118,7 @@ static bool mc_mem_alloc; static unsigned int di_pre_rdma_enable; static struct mutex di_event_mutex; static atomic_t di_flag_unreg; //ary 2019-05-27 +static atomic_t di_trig_free_mem; static unsigned int di_force_bit_mode = 10; module_param(di_force_bit_mode, uint, 0664); @@ -319,7 +320,8 @@ void trigger_pre_di_process(unsigned char idx) { if (di_sema_init_flag == 0) return; - + if (!active_flag) + return; log_buffer_state((idx == 'i') ? "irq" : ((idx == 'p') ? "put" : ((idx == 'r') ? "rdy" : "oth"))); @@ -461,6 +463,7 @@ static int lDI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len) static const struct di_ext_ops di_ext = { .di_post_reg_rd = lDI_POST_REG_RD, .di_post_wr_reg_bits = lDI_POST_WR_REG_BITS, + .post_update_mc = di_patch_post_update_mc, }; #endif @@ -561,6 +564,42 @@ int get_di_dump_state_flag(void) { return dump_state_flag; } +/******************************************** + * function: for releas mirror mem + * need call this after unreg di + ********************************************/ +void di_trig_free_mirror_mem(void) +{ + if (atomic_read(&di_flag_unreg) + && de_devp->flag_cma != 2 + && de_devp->flag_cma != 0 + && active_flag) { + atomic_set(&di_trig_free_mem, 1); + up(&di_sema); + di_pr_info("%s\n", __func__); + } +} +EXPORT_SYMBOL(di_trig_free_mirror_mem); +static bool di_free_mem_pre(void) +{ + + if (!atomic_read(&di_trig_free_mem)) + return false; + if (di_pre_stru.cma_alloc_done) + return false; + + if (!di_post_stru.keep_buf + || !atomic_read(&di_flag_unreg)) { + atomic_set(&di_trig_free_mem, 0); + return false; + } + + /*free mirror memory*/ + di_post_stru.keep_buf = NULL; + + return true; +} + /*--------------------------*/ static void parse_param_di(char *buf_orig, char **parm) @@ -656,6 +695,8 @@ store_dbg(struct device *dev, dump_post_mif_reg(); } else if (strncmp(buf, "recycle_buf", 11) == 0) { recycle_keep_buffer(); + } else if (strncmp(buf, "free_mirror", 11) == 0) { + di_trig_free_mirror_mem(); } else if (strncmp(buf, "recycle_post", 12) == 0) { if (di_vf_peek(NULL)) di_vf_put(di_vf_get(NULL), NULL); @@ -1055,10 +1096,10 @@ struct di_buf_s *get_di_buf(int queue_idx, int *start_pos) if (di_log_flag & DI_LOG_QUEUE) { if (di_buf) - di_print("%s: %x(%d,%d)\n", __func__, di_buf, - pool_idx, di_buf_idx); + di_print("%s: 0x%p(%d,%d)\n", __func__, di_buf, + pool_idx, di_buf_idx); else - di_print("%s: %x\n", __func__, di_buf); + di_print("%s: 0x%p\n", __func__, di_buf); } return di_buf; @@ -1113,10 +1154,10 @@ static struct di_buf_s *get_di_buf_head(int queue_idx) if (di_log_flag & DI_LOG_QUEUE) { if (di_buf) - di_print("%s: %x(%d,%d)\n", __func__, di_buf, - pool_idx, di_buf_idx); + di_print("%s: 0x%p(%d,%d)\n", __func__, di_buf, + pool_idx, di_buf_idx); else - di_print("%s: %x\n", __func__, di_buf); + di_print("%s: 0x%p\n", __func__, di_buf); } return di_buf; @@ -1141,9 +1182,9 @@ static void queue_out(struct di_buf_s *di_buf) q = &(queue[di_buf->queue_index]); if (di_log_flag & DI_LOG_QUEUE) - di_print("%s:<%d:%d,%d,%d> %x\n", __func__, - di_buf->queue_index, q->num, q->in_idx, - q->out_idx, di_buf); + di_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, + di_buf->queue_index, q->num, q->in_idx, + q->out_idx, di_buf); if (q->num > 0) { if (q->type == 0) { @@ -1264,8 +1305,8 @@ static void queue_in(struct di_buf_s *di_buf, int queue_idx) } q = &(queue[queue_idx]); if (di_log_flag & DI_LOG_QUEUE) - di_print("%s:<%d:%d,%d,%d> %x\n", __func__, queue_idx, - q->num, q->in_idx, q->out_idx, di_buf); + di_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, queue_idx, + q->num, q->in_idx, q->out_idx, di_buf); if (q->type == 0) { q->pool[q->in_idx] = (di_buf->type << 8) | (di_buf->index); @@ -1702,6 +1743,10 @@ unsigned char is_bypass(vframe_t *vf_in) return 1; if (vf_in && (vf_in->type & VIDTYPE_PIC)) return 1; + if ((is_meson_gxl_package_805X() || is_meson_gxl_package_805Y()) && + vf_in && is_progressive(vf_in)) + return 1; + #if 0 if (vf_in && (vf_in->type & VIDTYPE_COMPRESS)) return 1; @@ -2407,6 +2452,173 @@ static void di_cma_release(struct di_dev_s *devp) __func__, rels_cnt, delta_time, start_time, end_time); } #endif + +static void di_patch_mov_ini(void) +{ + struct di_patch_mov_s *pmov; + + if (!de_devp) + return; + + pmov = &de_devp->mov; + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + pmov->en_support = false; + return; + } + pmov->en_support = true; + pmov->mode = -1; + pmov->nub = 0; +} + +bool di_patch_mov_db(unsigned int addr, unsigned int val) +{ + bool ret = false; + int i; + struct di_patch_mov_s *pmov; + struct di_patch_mov_d_s *pmv; + + if (!de_devp) + return ret; + + pmov = &de_devp->mov; + + if (!pmov->en_support || !pmov->nub) + return ret; + + for (i = 0; i < pmov->nub; i++) { + if (addr == pmov->reg_addr[i]) { + pmv = &pmov->val_db[i]; + pmv->val = val; + pmv->en = true; + pmv->mask = 0xffffffff; + ret = true; + } + } + return ret; +} + +void di_patch_mov_setreg(unsigned int nub, unsigned int *preg) +{ + struct di_patch_mov_s *pmov; + unsigned int i; + + if (!de_devp) + return; + + pmov = &de_devp->mov; + + if (!pmov->en_support) + return; + + pmov->nub = nub; + if (nub > DI_PATCH_MOV_MAX_NUB) { + pr_error("err: %s:nub is overflow %d\n", + __func__, nub); + pmov->nub = DI_PATCH_MOV_MAX_NUB; + } + + pmov->mode = -1; + for (i = 0; i < pmov->nub; i++) { + pmov->reg_addr[i] = preg[i]; + di_pr_info("reg:0x%x\n", preg[i]); + } +} +EXPORT_SYMBOL(di_patch_mov_setreg); + +/************************************************** + * pdate: + * value / mask + * value / mask + * need keep same order with di_patch_mov_setreg + **************************************************/ +bool di_api_mov_sel(unsigned int mode, unsigned int *pdate) +{ + struct di_patch_mov_s *pmov; + int i; + struct di_patch_mov_d_s *pmv; + bool ret = true; + + if (!de_devp) + return false; + + pmov = &de_devp->mov; + + if (!pmov || + !pmov->en_support || + !init_flag) + return false; + + switch (mode) { + case 0:/*setting from db*/ + pmov->mode = 0; + pmov->update = 1; + break; + case 1:/*setting from pq*/ + pmov->update = 0; + for (i = 0; i < pmov->nub; i++) { + pmv = &pmov->val_pq[i]; + pmv->val = pdate[i * 2]; + pmv->mask = pdate[i * 2 + 1]; + pmv->en = true; + } + pmov->mode = 1; + pmov->update = true; + + break; + default: + ret = false; + break; + } + return ret; +} +EXPORT_SYMBOL(di_api_mov_sel); + +static void di_patch_mov_setting(void) +{ + struct di_patch_mov_s *pmov; + int i; + struct di_patch_mov_d_s *pmv; + unsigned int val; + + if (!de_devp) + return; + + pmov = &de_devp->mov; + + if (!pmov || + !pmov->en_support || + pmov->mode < 0 || + pmov->mode > 1 || + !pmov->update) + return; + + if (pmov->mode == 0) + pmv = &pmov->val_db[0]; + else + pmv = &pmov->val_pq[0]; + + for (i = 0; i < pmov->nub; i++) { + if (pmv->en) { + if (pmv->mask != 0xffffffff) { + val = ((RDMA_RD(pmov->reg_addr[i]) & + (~(pmv->mask))) | + (pmv->val & pmv->mask)); + } else { + val = pmv->val; + } + DI_Wr(pmov->reg_addr[i], val); + } + pmv++; + } + pmov->update = 0; +} + +void di_set_comb_mode(unsigned int mode) +{ + di_pre_stru.comb_mode = mode; +} +EXPORT_SYMBOL(di_set_comb_mode); + static int di_init_buf(int width, int height, unsigned char prog_flag) { int i; @@ -2997,7 +3209,7 @@ config_di_pre_mc_mif(struct DI_MC_MIF_s *di_mcinfo_mif, if (di_buf) { pre_size_w = di_buf->vframe->width; pre_size_h = (di_buf->vframe->height + 1) / 2; - di_mcinfo_mif->size_x = (pre_size_h + 1) / 2 - 1; + di_mcinfo_mif->size_x = pre_size_h / 2 - 1; di_mcinfo_mif->size_y = 1; di_mcinfo_mif->canvas_num = di_buf->mcinfo_canvas_idx; @@ -3127,7 +3339,7 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) di_buf->vframe->width / 2 - 1; di_mif->chroma_y_start0 = 0; di_mif->chroma_y_end0 = - di_buf->vframe->height / 2 - 1; + (di_buf->vframe->height + 1) / 2 - 1; } else { if (di_pre_stru.cur_inp_type & VIDTYPE_INTERLACE) di_mif->src_prog = 0; @@ -3143,14 +3355,13 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) di_buf->vframe->width - 1; di_mif->luma_y_start0 = 0; di_mif->luma_y_end0 = - di_buf->vframe->height - 2; + di_buf->vframe->height - 1; di_mif->chroma_x_start0 = 0; di_mif->chroma_x_end0 = di_buf->vframe->width / 2 - 1; di_mif->chroma_y_start0 = 0; di_mif->chroma_y_end0 = - di_buf->vframe->height / 2 - - (di_mif->src_prog?1:2); + (di_buf->vframe->height + 1) / 2 - 1; } else { di_mif->output_field_num = 1; /* bottom */ @@ -3166,7 +3377,7 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) di_mif->chroma_y_start0 = (di_mif->src_prog?0:1); di_mif->chroma_y_end0 = - di_buf->vframe->height / 2 - 1; + (di_buf->vframe->height + 1) / 2 - 1; } } } @@ -3350,6 +3561,7 @@ static void pre_de_process(void) di_pre_stru.input_size_change_flag = false; } + di_patch_mov_setting(); if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { if (de_devp->nrds_enable) { nr_ds_mif_config(); @@ -3407,6 +3619,9 @@ static void pre_de_process(void) } di_pre_stru.field_count_for_cont++; + if (di_pre_stru.field_count_for_cont >= 5) + DI_Wr_reg_bits(DI_MTN_CTRL, 0, 30, 1); + di_txl_patch_prog(di_pre_stru.cur_prog_flag, di_pre_stru.field_count_for_cont, mcpre_en); @@ -3424,14 +3639,16 @@ static void pre_de_process(void) * otherwise may cause watch dog reboot */ di_lock_irqfiq_save(irq_flag2); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + /* enable mc pre mif*/ + enable_di_pre_mif(true, mcpre_en); pre_frame_reset_g12(di_pre_stru.madi_enable, di_pre_stru.mcdi_enable); - else + } else { pre_frame_reset(); - - /* enable mc pre mif*/ - enable_di_pre_mif(true, mcpre_en); + /* enable mc pre mif*/ + enable_di_pre_mif(true, mcpre_en); + } di_unlock_irqfiq_restore(irq_flag2); /*reinit pre busy flag*/ di_pre_stru.pre_de_busy_timer_count = 0; @@ -3536,8 +3753,10 @@ static void pre_de_done_buf_config(void) di_pre_stru.di_post_wr_buf = di_pre_stru.di_wr_buf; post_wr_buf = di_pre_stru.di_post_wr_buf; - if (post_wr_buf) + if (post_wr_buf) { post_wr_buf->vframe->di_pulldown = 0; + post_wr_buf->vframe->di_gmv = 0; + } if (post_wr_buf && !di_pre_stru.cur_prog_flag) { read_pulldown_info(&glb_frame_mot_num, @@ -3552,7 +3771,8 @@ static void pre_de_done_buf_config(void) } post_wr_buf->vframe->di_pulldown |= 0x08; - if (combing_fix_en) + post_wr_buf->vframe->di_gmv = glb_frame_mot_num; + if (di_pre_stru.combing_fix_en) cur_lev = adaptive_combing_fixing( di_pre_stru.mtn_status, glb_field_mot_num, @@ -3890,7 +4110,9 @@ static unsigned char pre_de_buf_config(void) unsigned int width_roundup = 2; u32 rls_timeout; u32 afbc_busy; - u32 is_afbc_mode; + u32 is_afbc_mode = 0; + bool flg_1080i = false; + bool flg_480i = false; if (di_blocking || !atomic_read(&de_devp->mem_flag)) return 0; @@ -3960,7 +4182,8 @@ static unsigned char pre_de_buf_config(void) /*for support compress from dec*/ if (IS_COMP_MODE(vframe->type) && - !is_bypass(vframe)) { + !is_bypass(vframe) && + afbc_is_supported()) { is_afbc_mode = true; if (IS_VDIN_SRC(vframe->source_type) && IS_I_SRC(vframe->type)) { @@ -4395,14 +4618,11 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); } else { /*********************************/ if ((di_buf->vframe->width >= 1920) && - (di_buf->vframe->height >= 1080) && - is_meson_tl1_cpu()) { - if (combing_fix_en) { - combing_fix_en = false; - fix_tl1_1080i_sawtooth_patch(); - } - } else - combing_fix_en = true; + (di_buf->vframe->height >= 1080)) + flg_1080i = true; + else if ((di_buf->vframe->width == 720) && + (di_buf->vframe->height == 480)) + flg_480i = true; /*********************************/ if ( @@ -4586,6 +4806,23 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); recovery_flag++; return 0; } + if (is_meson_tl1_cpu() && + di_pre_stru.comb_mode && + flg_1080i) { + di_pre_stru.combing_fix_en = false; + fix_tl1_1080i_patch_sel(di_pre_stru.comb_mode); + } else { + di_pre_stru.combing_fix_en = combing_fix_en; + } + + if (di_pre_stru.combing_fix_en) { + if (flg_1080i) + com_patch_pre_sw_set(1); + else if (flg_480i) + com_patch_pre_sw_set(2); + else + com_patch_pre_sw_set(0); + } return 1; } @@ -4594,10 +4831,16 @@ static int check_recycle_buf(void) struct di_buf_s *di_buf = NULL;/* , *ptmp; */ int itmp; int ret = 0; + bool blk_flg = 0; +#ifdef DI_KEEP_HIS if (di_blocking) return ret; +#endif queue_for_each_entry(di_buf, ptmp, QUEUE_RECYCLE, list) { + if (di_blocking) + blk_flg = 1; + if ((di_buf->pre_ref_count == 0) && (di_buf->post_ref_count == 0)) { if (di_buf->type == VFRAME_TYPE_IN) { @@ -4610,7 +4853,7 @@ static int check_recycle_buf(void) VFRAME_EVENT_RECEIVER_PUT, NULL); di_print( - "%s: vf_put(%d) %x, %u ms\n", + "%s: vf_put(%d) 0x%p, %u ms\n", __func__, di_pre_stru.recycle_seq, vframe_in[di_buf->index], @@ -4649,6 +4892,10 @@ static int check_recycle_buf(void) #endif } } + + if (blk_flg) + pr_info("di:blk:recycle\n"); + return ret; } @@ -4890,8 +5137,10 @@ static irqreturn_t de_irq(int irq, void *dev_instance) DI_Wr(DI_INTR_CTRL, data32); } #else - if (flag) + if (flag) { + di_hpre_gl_sw(false); DI_Wr(DI_INTR_CTRL, (data32&0xfffffffb)|(intr_mode<<30)); + } #endif if (di_pre_stru.pre_de_busy == 0) { @@ -6737,9 +6986,10 @@ static void di_pre_size_change(unsigned short width, } di_load_pq_table(); - + #ifdef OLD_PRE_GL if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) RDMA_WR(DI_PRE_GL_CTRL, 0x80000005); + #endif if (de_devp->nrds_enable) nr_ds_init(width, height); if (de_devp->pps_enable && pps_position) { @@ -6766,6 +7016,10 @@ static void di_pre_size_change(unsigned short width, static bool need_bypass(struct vframe_s *vf) { needbypass_flag = true; + if ((is_meson_gxl_package_805X() || is_meson_gxl_package_805Y()) && + is_progressive(vf)) + return true; + if (vf->type & VIDTYPE_MVC) return true; @@ -6881,6 +7135,7 @@ static void di_reg_process_irq(void) DI_Wr(DI_CLKG_CTRL, 0xfef60001); /* nr/blend0/ei0/mtn0 clock gate */ } + di_hdr2_hist_init(); if (di_printk_flag & 2) di_printk_flag = 1; @@ -6955,7 +7210,7 @@ static void di_reg_process_irq(void) di_pre_stru.retry_index = 0; init_flag = 1; - di_pre_stru.reg_req_flag_irq = 1; + /*di_pre_stru.reg_req_flag_irq = 1;*/ } di_pre_stru.reg_irq_busy = false; } @@ -7149,66 +7404,79 @@ static int di_task_handle(void *data) ret = down_interruptible(&di_sema); if (ret != 0) continue; - if (active_flag) { - if ((di_pre_stru.unreg_req_flag || - di_pre_stru.force_unreg_req_flag || - di_pre_stru.disable_req_flag) && - (di_pre_stru.pre_de_busy == 0)) { - di_unreg_process(); + + if (!de_devp) + continue; + + if (!active_flag) + continue; + + if ((di_pre_stru.unreg_req_flag || + di_pre_stru.force_unreg_req_flag || + di_pre_stru.disable_req_flag) && + (di_pre_stru.pre_de_busy == 0)) { + di_unreg_process(); #if 0 - /* if mirror mode, can't speed down the clk*/ - /* set min rate for power saving */ - if (de_devp->vpu_clkb) { - clk_set_rate(de_devp->vpu_clkb, - de_devp->clkb_min_rate); - } + /* if mirror mode, can't speed down the clk*/ + /* set min rate for power saving */ + if (de_devp->vpu_clkb) { + clk_set_rate(de_devp->vpu_clkb, + de_devp->clkb_min_rate); + } #endif - } - if (di_pre_stru.reg_req_flag_irq || - di_pre_stru.reg_req_flag) { - di_reg_process(); - di_pre_stru.reg_req_flag = 0; - di_pre_stru.reg_req_flag_irq = 0; - } - #ifdef CONFIG_CMA - /* mutex_lock(&de_devp->cma_mutex);*/ - if (di_pre_stru.cma_release_req) { - atomic_set(&devp->mem_flag, 0); - di_cma_release(devp); - di_pre_stru.cma_release_req = 0; - di_pre_stru.cma_alloc_done = 0; - } - if (di_pre_stru.cma_alloc_req) { - if (di_cma_alloc(devp)) - atomic_set(&devp->mem_flag, 1); - else - atomic_set(&devp->mem_flag, 0); - di_pre_stru.cma_alloc_req = 0; - di_pre_stru.cma_alloc_done = 1; - } - /* mutex_unlock(&de_devp->cma_mutex); */ - #endif } + if (/*di_pre_stru.reg_req_flag_irq ||*/ + di_pre_stru.reg_req_flag) { + di_reg_process(); + di_pre_stru.reg_req_flag = 0; + /*di_pre_stru.reg_req_flag_irq = 0;*/ + } + #ifdef CONFIG_CMA + /* mutex_lock(&de_devp->cma_mutex);*/ + if (di_pre_stru.cma_release_req) { + atomic_set(&devp->mem_flag, 0); + di_cma_release(devp); + di_pre_stru.cma_release_req = 0; + di_pre_stru.cma_alloc_done = 0; + } + if (di_pre_stru.cma_alloc_req) { + if (di_cma_alloc(devp)) + atomic_set(&devp->mem_flag, 1); + else + atomic_set(&devp->mem_flag, 0); + di_pre_stru.cma_alloc_req = 0; + di_pre_stru.cma_alloc_done = 1; + } + if (di_free_mem_pre()) { + di_cma_release(devp); + di_pr_info("release mirror\n"); + atomic_set(&di_trig_free_mem, 0); + } + /* mutex_unlock(&de_devp->cma_mutex); */ + #endif + if (de_devp->flags & DI_VPU_CLKB_SET) { if (is_meson_txlx_cpu()) { if (!use_2_interlace_buff) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, - de_devp->clkb_min_rate); + de_devp->clkb_min_rate); #endif } else { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, - de_devp->clkb_max_rate); + de_devp->clkb_max_rate); #endif } } - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu() || is_meson_tm2_cpu() || - is_meson_sm1_cpu()) { + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { #ifdef CLK_TREE_SUPPORT clk_set_rate(de_devp->vpu_clkb, - de_devp->clkb_max_rate); + de_devp->clkb_max_rate); #endif } de_devp->flags &= (~DI_VPU_CLKB_SET); @@ -7230,7 +7498,7 @@ static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p) if (pre_stru_p->unreg_req_flag_irq && (di_pre_stru.pre_de_busy == 0)) di_unreg_process_irq(); - if (init_flag == 0 && pre_stru_p->reg_req_flag_irq == 0 + if (init_flag == 0 /*&& pre_stru_p->reg_req_flag_irq == 0*/ && (!atomic_read(&di_flag_unreg))) di_reg_process_irq(); } @@ -7258,9 +7526,38 @@ static enum hrtimer_restart di_pre_hrtimer_func(struct hrtimer *timer) if (!di_pre_stru.bypass_flag) di_pre_trigger_work(&di_pre_stru); hrtimer_forward_now(&di_pre_hrtimer, ms_to_ktime(10)); - di_patch_post_update_mc(); + /*di_patch_post_update_mc();*/ return HRTIMER_RESTART; } + +static void post_display_buf_clear(void) +{ + struct di_buf_s *p = NULL; + int itmp; + + pr_info("%s:\n", __func__); + queue_for_each_entry(p, ptmp, QUEUE_DISPLAY, list) { + pr_info("\t%s,%d\n", vframe_type_name[p->type], p->index); + if (p->type == VFRAME_TYPE_POST) { + if (!atomic_dec_and_test(&p->di_cnt)) + di_print("%s,di_cnt > 0\n", __func__); + recycle_vframe_type_post(p); + } else { + queue_in(p, QUEUE_RECYCLE); + di_print("%s: %s[%d] =>recycle_list\n", __func__, + vframe_type_name[p->type], p->index); + } + } +} + +static void dbg_check_list(void) +{ + unsigned int post_display; + + post_display = list_count(QUEUE_DISPLAY); + di_pr_info("display:%d\n", post_display); +} + /* * provider/receiver interface */ @@ -7330,40 +7627,64 @@ static int di_receiver_event_fun(int type, void *data, void *arg) mutex_unlock(&di_event_mutex); pr_info("DI: unreg f\n"); } else if (type == VFRAME_EVENT_PROVIDER_RESET) { - di_blocking = 1; - + /*di_blocking = 1;*/ + mutex_lock(&di_event_mutex); pr_info("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__); if (is_bypass(NULL) || bypass_state || di_pre_stru.bypass_flag) { + /* only if di is bypassed, then we send the message of + * VFRAME_EVENT_PROVIDER_RESET to video and notify + * it to keep the last canvas buffer which was + * alloced by codec not by di. + */ vf_notify_receiver(VFM_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); + di_blocking = 1; + spin_lock_irqsave(&plist_lock, flags); + post_display_buf_clear(); + spin_unlock_irqrestore(&plist_lock, flags); } - - goto light_unreg; - } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) { di_blocking = 1; - - pr_info("%s: vf_notify_receiver ligth unreg\n", __func__); - -light_unreg: + /*-----------------------------------*/ spin_lock_irqsave(&plist_lock, flags); for (i = 0; i < MAX_IN_BUF_NUM; i++) { - if (vframe_in[i]) - pr_dbg("DI:clear vframe_in[%d]\n", i); + pr_info("DI:clear vframe_in[%d]\n", i); vframe_in[i] = NULL; } spin_unlock_irqrestore(&plist_lock, flags); di_blocking = 0; + mutex_unlock(&di_event_mutex); + pr_info("\treset:end\n"); + /*goto light_unreg;*/ + } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) { + mutex_lock(&di_event_mutex); + di_blocking = 1; + + pr_info("%s: LIGHT_UNREG\n", __func__); + +/*light_unreg:*/ +#if 1 + spin_lock_irqsave(&plist_lock, flags); + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + + if (vframe_in[i]) + pr_info("DI:clear vframe_in[%d]\n", i); + + vframe_in[i] = NULL; + } + spin_unlock_irqrestore(&plist_lock, flags); +#endif + di_blocking = 0; + mutex_unlock(&di_event_mutex); + pr_info("\tlight unreg:end\n"); } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME) { unsigned char vf_put_flag = 0; - pr_dbg( - "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", - __func__); + pr_info("%s:LIGHT_UNREG_RETURN_VFRAME\n", __func__); /* * do not display garbage when 2d->3d or 3d->2d */ @@ -7500,6 +7821,7 @@ light_unreg: if (reg_flag) { pr_err("[DI] no muti instance.\n"); mutex_unlock(&di_event_mutex); + dbg_check_list(); return -1; } pr_info("%s: vframe provider reg %s\n", __func__, @@ -7785,9 +8107,11 @@ get_vframe: log_buffer_state("get"); } if (vframe_ret) { - di_print("%s: %s[%d]:%x %u ms\n", __func__, - vframe_type_name[di_buf->type], di_buf->index, vframe_ret, - jiffies_to_msecs(jiffies_64 - vframe_ret->ready_jiffies64)); + di_print("%s: %s[%d]:0x%p %u ms\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index, vframe_ret, + jiffies_to_msecs + (jiffies_64 - vframe_ret->ready_jiffies64)); } if (!post_wr_en && di_post_stru.run_early_proc_fun_flag && vframe_ret) { @@ -7821,8 +8145,10 @@ static void di_vf_put(vframe_t *vf, void *arg) di_print("%s: 0x%p\n", __func__, vf); return; } + #ifdef DI_KEEP_HIS if (di_blocking) return; + #endif log_buffer_state("pu_"); di_buf = (struct di_buf_s *)vf->private_data; if (IS_ERR_OR_NULL(di_buf)) { @@ -8496,7 +8822,7 @@ static int di_probe(struct platform_device *pdev) vf_receiver_init(&di_vf_recv, VFM_NAME, &di_vf_receiver, NULL); vf_reg_receiver(&di_vf_recv); vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL); - active_flag = 1; + /*active_flag = 1;*/ sema_init(&di_sema, 1); ret = request_irq(di_devp->pre_irq, &de_irq, IRQF_SHARED, "pre_di", (void *)"pre_di"); @@ -8523,10 +8849,12 @@ static int di_probe(struct platform_device *pdev) di_devp->task = kthread_run(di_task_handle, di_devp, "kthread_di"); if (IS_ERR(di_devp->task)) pr_err("%s create kthread error.\n", __func__); + active_flag = 1; di_debugfs_init(); /*2018-07-18 add debugfs*/ di_patch_post_update_mc_sw(DI_MC_SW_IC, true); dil_attach_ext_api(&di_ext); + di_patch_mov_ini(); di_pr_info("%s:ok\n", __func__); return ret; @@ -8619,6 +8947,8 @@ static void di_shutdown(struct platform_device *pdev) struct di_dev_s *di_devp = NULL; int ret = 0; + active_flag = 0; + di_devp = platform_get_drvdata(pdev); ret = hrtimer_cancel(&di_pre_hrtimer); pr_info("di pre hrtimer canel %d.\n", ret); @@ -8635,6 +8965,7 @@ static void di_shutdown(struct platform_device *pdev) switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_OFF); kfree(di_devp); + di_devp = NULL; pr_info("[DI] shutdown done.\n"); } @@ -8658,9 +8989,11 @@ static void di_clear_for_suspend(struct di_dev_s *di_devp) di_pre_stru.cma_alloc_done = 0; } #endif + #ifdef DI_KEEP_HIS hrtimer_cancel(&di_pre_hrtimer); tasklet_kill(&di_pre_tasklet); //ary.sui tasklet_disable(&di_pre_tasklet); + #endif pr_info("%s end\n", __func__); } static int save_init_flag; @@ -8674,10 +9007,16 @@ static int di_suspend(struct device *dev) di_devp->flags |= DI_SUSPEND_FLAG; di_clear_for_suspend(di_devp);//add + active_flag = 0; /* fix suspend/resume crash problem */ save_init_flag = init_flag; init_flag = 0; + + hrtimer_cancel(&di_pre_hrtimer); + tasklet_kill(&di_pre_tasklet); + tasklet_disable(&di_pre_tasklet); + #if 0 /*2019-01-18*/ if (di_pre_stru.di_inp_buf) { if (vframe_in[di_pre_stru.di_inp_buf->index]) { @@ -8718,6 +9057,7 @@ static int di_resume(struct device *dev) di_pre_hrtimer.function = di_pre_hrtimer_func; hrtimer_start(&di_pre_hrtimer, ms_to_ktime(10), HRTIMER_MODE_REL); tasklet_enable(&di_pre_tasklet); + active_flag = 1; /************/ pr_info("di: resume module\n"); return 0; diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 996170db0a38..d93e31283797 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -220,6 +220,29 @@ extern bool is_vsync_rdma_enable(void); #define TABLE_LEN_MAX 10000 #define TABLE_FLG_END (0xfffffffe) +/****************************************** + * patch for TV-10258 multiwave group issue + *****************************************/ +#define DI_PATCH_MOV_MAX_NUB 5 + +struct di_patch_mov_d_s { + unsigned int val; + unsigned int mask; + bool en; +}; + +struct di_patch_mov_s { + unsigned int reg_addr[DI_PATCH_MOV_MAX_NUB]; + struct di_patch_mov_d_s val_db[DI_PATCH_MOV_MAX_NUB]; + struct di_patch_mov_d_s val_pq[DI_PATCH_MOV_MAX_NUB]; + int mode;/*-1 : not set; 0: set from db, 1: set from pq*/ + bool en_support; + bool update; + unsigned int nub; +}; + +bool di_patch_mov_db(unsigned int addr, unsigned int val); + struct di_dev_s { dev_t devt; struct cdev cdev; /* The cdev structure */ @@ -254,6 +277,7 @@ struct di_dev_s { struct page *total_pages; atomic_t mem_flag; struct dentry *dbg_root; /*dbg_fs*/ + struct di_patch_mov_s mov; }; struct di_pre_stru_s { @@ -299,7 +323,7 @@ struct di_pre_stru_s { int unreg_req_flag_irq; int unreg_req_flag_cnt; int reg_req_flag; - int reg_req_flag_irq; + /*int reg_req_flag_irq;*/ int reg_req_flag_cnt; int reg_irq_busy; int force_unreg_req_flag; @@ -376,6 +400,10 @@ struct di_pre_stru_s { bool retry_en; unsigned int retry_index; unsigned int retry_cnt; + /*****************/ + bool combing_fix_en; + unsigned int comb_mode; + /*struct di_patch_mov_s mov;*/ }; struct di_post_stru_s { @@ -473,4 +501,6 @@ struct di_buf_s *get_di_buf(int queue_idx, int *start_pos); #define pr_error(fmt, args ...) pr_err("DI: " fmt, ## args) +/******************************************/ +/*#define DI_KEEP_HIS 0*/ #endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 5d9d3aff655d..ac68b40a78ee 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -475,8 +475,10 @@ void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p) di_pre_stru_p->unreg_req_flag_irq); pr_info("reg_req_flag = %d\n", di_pre_stru_p->reg_req_flag); + #ifdef DI_KEEP_HIS pr_info("reg_req_flag_irq = %d\n", di_pre_stru_p->reg_req_flag_irq); + #endif pr_info("cur_width = %d\n", di_pre_stru_p->cur_width); pr_info("cur_height = %d\n", @@ -547,8 +549,10 @@ static int dump_di_pre_stru_seq(struct seq_file *seq, void *v) di_pre_stru_p->unreg_req_flag_irq); seq_printf(seq, "%-25s = %d\n", "reg_req_flag", di_pre_stru_p->reg_req_flag); + #ifdef DI_KEEP_HIS seq_printf(seq, "%-25s = %d\n", "reg_req_flag_irq", di_pre_stru_p->reg_req_flag_irq); + #endif seq_printf(seq, "%-25s = %d\n", "cur_width", di_pre_stru_p->cur_width); seq_printf(seq, "%-25s = %d\n", "cur_height", @@ -583,6 +587,10 @@ static int dump_di_pre_stru_seq(struct seq_file *seq, void *v) di_pre_stru_p->bypass_pre ? "true" : "false"); seq_printf(seq, "%-25s = %s\n", "invert_flag", di_pre_stru_p->invert_flag ? "true" : "false"); + seq_printf(seq, "%-25s = %s\n", "combing_fix_en", + di_pre_stru_p->combing_fix_en ? "true" : "false"); + seq_printf(seq, "%-25s = %d\n", "comb_mode", + di_pre_stru_p->comb_mode); return 0; } @@ -875,6 +883,7 @@ void dump_vframe(struct vframe_s *vf) pr_info("pixel_ratio %d list %p\n", vf->pixel_ratio, &vf->list); pr_info("di_pulldown 0x%x\n", vf->di_pulldown); + pr_info("di_gmv 0x%x\n", vf->di_gmv); } void print_di_buf(struct di_buf_s *di_buf, int format) @@ -1071,6 +1080,30 @@ void dump_afbcd_reg(void) VD2_AFBCD1_MISC_CTRL, RDMA_RD(VD2_AFBCD1_MISC_CTRL)); } +static int dbg_patch_mov_data_show(struct seq_file *seq, void *v) +{ + struct di_dev_s *de_devp = get_di_de_devp(); + struct di_patch_mov_s *pmov = &de_devp->mov; + int i; + + seq_printf(seq, "mode:%d\n", pmov->mode); + seq_printf(seq, "en_support:%d\n", pmov->en_support); + seq_printf(seq, "number:%d\n", pmov->nub); + seq_printf(seq, "update:%d\n", pmov->update); + for (i = 0; i < DI_PATCH_MOV_MAX_NUB; i++) { + seq_printf(seq, "index:[%d]\n", i); + seq_printf(seq, "\treg:0x%x\n", pmov->reg_addr[i]); + if (i < pmov->nub) + seq_printf(seq, "\t\t= 0x%x\n", + RDMA_RD(pmov->reg_addr[i])); + seq_printf(seq, "\tdb_val:0x%x\n", pmov->val_db[i].val); + seq_printf(seq, "\tdb_en :0x%x\n", pmov->val_db[i].en); + seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].val); + seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].en); + } + return 0; +} + /*2018-08-17 add debugfs*/ /*same as dump_state*/ static int seq_file_di_state_show(struct seq_file *seq, void *v) @@ -1250,6 +1283,7 @@ DEFINE_SHOW_DI(seq_file_dump_di_reg); DEFINE_SHOW_DI(seq_file_dump_mif_size_state); DEFINE_SHOW_DI(seq_file_afbc); DEFINE_SHOW_DI(reg_cue_int); +DEFINE_SHOW_DI(dbg_patch_mov_data); struct di_debugfs_files_t { const char *name; @@ -1263,6 +1297,7 @@ static struct di_debugfs_files_t di_debugfs_files[] = { {"dumpmif", S_IFREG | 0644, &seq_file_dump_mif_size_state_fops}, {"dumpafbc", S_IFREG | 0644, &seq_file_afbc_fops}, {"reg_cue", S_IFREG | 0644, ®_cue_int_fops}, + {"dumpmov", S_IFREG | 0644, &dbg_patch_mov_data_fops}, }; void di_debugfs_init(void) diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index a0d0c13d4e42..c94c56dcc5c7 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -33,6 +33,8 @@ #include "deinterlace.h" #include "register.h" #include "register_nr4.h" +#include "nr_drv.h" + #ifdef DET3D #include "detect3d.h" #endif @@ -139,6 +141,8 @@ static void ma_di_init(void) /* mtn setting */ if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { DI_Wr_reg_bits(DI_MTN_CTRL, 1, 0, 1); + DI_Wr_reg_bits(DI_MTN_CTRL, 1, 30, 1); + DI_Wr_reg_bits(DI_MTN_CTRL, 0xf, 24, 4); DI_Wr(DI_MTN_1_CTRL1, 0x202015); } else DI_Wr(DI_MTN_1_CTRL1, 0xa0202015); @@ -331,7 +335,7 @@ void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned short *mcinfo_vadr) if (!lmv_lock_win_en) return; - if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { pr_debug("%s: only support G12A and after chips.\n", __func__); return; } @@ -431,7 +435,11 @@ static void pre_hold_block_mode_config(void) if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { DI_Wr(DI_PRE_HOLD, 0); /* go field after 2 lines */ + #ifdef OLD_PRE_GL DI_Wr(DI_PRE_GL_CTRL, (0x80000000|line_num_pre_frst)); + #else + di_hpre_gl_sw(false); + #endif } else if (is_meson_txlx_cpu()) { /* setup pre process ratio to 66.6%*/ DI_Wr(DI_PRE_HOLD, (1 << 31) | (1 << 16) | 3); @@ -754,9 +762,10 @@ void enable_di_pre_aml( /* * enable&disable contwr txt */ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) - RDMA_WR_BITS(DI_MTN_CTRL, madi_en?5:0, 29, 3); - else + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { + RDMA_WR_BITS(DI_MTN_CTRL, madi_en, 29, 1); + RDMA_WR_BITS(DI_MTN_CTRL, madi_en, 31, 1); + } else RDMA_WR_BITS(DI_MTN_1_CTRL1, madi_en?5:0, 29, 3); if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { @@ -3227,11 +3236,28 @@ void pre_frame_reset_g12(unsigned char madi_en, RDMA_WR_BITS(MCVECWR_CAN_SIZE, 0, 14, 1); RDMA_WR_BITS(MCINFWR_CAN_SIZE, 0, 14, 1); + #ifdef OLD_PRE_GL reg_val = 0xc3200000 | line_num_pre_frst; RDMA_WR(DI_PRE_GL_CTRL, reg_val); reg_val = 0x83200000 | line_num_pre_frst; RDMA_WR(DI_PRE_GL_CTRL, reg_val); + #else + di_hpre_gl_sw(true); + #endif } + +/*2019-12-25 by feijun*/ +void di_hpre_gl_sw(bool on) +{ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + return; + if (on) + RDMA_WR(DI_PRE_GL_CTRL, + 0x80200000 | line_num_pre_frst); + else + RDMA_WR(DI_PRE_GL_CTRL, 0xc0000000); +} + /* * frame + soft reset for the pre modules */ @@ -3362,6 +3388,15 @@ void diwr_set_power_control(unsigned char enable) enable?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); } +void di_hdr2_hist_init(void) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) { + RDMA_WR(DI_HDR2_HIST_CTRL, 0x5510); + RDMA_WR(DI_HDR2_HIST_H_START_END, 0x10000); + RDMA_WR(DI_HDR2_HIST_V_START_END, 0x0); + } +} + void di_top_gate_control(bool top_en, bool mc_en) { if (top_en) { @@ -3835,30 +3870,35 @@ void pulldown_vof_win_config(struct pulldown_detected_s *wins) wins->regs[3].win_vs, 17, 12); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, wins->regs[3].win_ve, 1, 12); - + /* revert the setting of top two lines do weave for */ + /* interlace video, suggest by vlsi-feijun */ DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, (wins->regs[0].win_ve > wins->regs[0].win_vs) ? 1 : 0, 16, 1); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - wins->regs[0].blend_mode, 8, 2); + /*wins->regs[0].blend_mode*/ + 0x03, 8, 2); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, (wins->regs[1].win_ve > wins->regs[1].win_vs) ? 1 : 0, 17, 1); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - wins->regs[1].blend_mode, 10, 2); + /*wins->regs[1].blend_mode*/ + 0x03, 10, 2); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, (wins->regs[2].win_ve > wins->regs[2].win_vs) ? 1 : 0, 18, 1); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - wins->regs[2].blend_mode, 12, 2); + /*wins->regs[2].blend_mode*/ + 0x03, 12, 2); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, (wins->regs[3].win_ve > wins->regs[3].win_vs) ? 1 : 0, 19, 1); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - wins->regs[3].blend_mode, 14, 2); + /*wins->regs[3].blend_mode*/ + 0x03, 14, 2); } @@ -3868,6 +3908,7 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr) unsigned int table_name = 0, nr_table = 0; bool ctrl_reg_flag = false; struct am_reg_s *regs_p = NULL; + bool mov_flg = false; if (pq_load_dbg == 1) return; @@ -3889,6 +3930,11 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr) addr = regs_p->addr; value = regs_p->val; mask = regs_p->mask; + if (nr_demo_flag) { + if (addr == NR4_TOP_CTRL) + mask &= ~(0x7 << 6); + } + if (pq_load_dbg == 2) pr_info("[%u][0x%x] = [0x%x]&[0x%x]\n", i, addr, value, mask); @@ -3911,7 +3957,9 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr) } if (table_name & nr_table) ctrl_reg_flag = set_nr_ctrl_reg_table(addr, value); - if (!ctrl_reg_flag) + if (table_name & TABLE_NAME_DI) + mov_flg = di_patch_mov_db(addr, value); + if (!ctrl_reg_flag && !mov_flg) DI_Wr(addr, value); if (pq_load_dbg == 2) pr_info("[%u][0x%x] = [0x%x] %s\n", i, addr, diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h index bf1fa6a2137e..fa6966ad53fc 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -184,6 +184,7 @@ void di_post_switch_buffer( ); void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, bool mc_enable); +void di_hdr2_hist_init(void); void di_top_gate_control(bool top_en, bool mc_en); void di_pre_gate_control(bool enable, bool mc_enable); void di_post_gate_control(bool gate); @@ -201,6 +202,7 @@ void pulldown_vof_win_config(struct pulldown_detected_s *wins); void di_load_regs(struct di_pq_parm_s *di_pq_ptr); void pre_frame_reset_g12(unsigned char madi_en, unsigned char mcdi_en); void pre_frame_reset(void); +void di_hpre_gl_sw(bool on); void di_interrupt_ctrl(unsigned char ma_en, unsigned char det3d_en, unsigned char nrds_en, unsigned char post_wr, unsigned char mc_en); diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index 6c3681fae4b8..ffd5f68b4358 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -161,7 +161,6 @@ static unsigned int combing_bias_static_setting[MAX_NUM_DI_REG] = { 0x00000166 }; - static unsigned int combing_normal_setting[MAX_NUM_DI_REG] = { 0x00202015, 0x1A1A3A62, @@ -182,18 +181,18 @@ static unsigned int combing_normal_setting[MAX_NUM_DI_REG] = { }; static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = { - 0x00202015, - 0x1A1A3A62, - 0x15200101, - 0x01200440, - 0x74200D0D, - 0x0D5A1520, - 0x0A0A0201, - 0x1A1A2662, - 0x0D200302, - 0x02020606, - 0x05080344, - 0x40020a04, + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + 0x40020a04, /* 11 */ /*idea from mingliang.dong & vlsi zheng.bao begin*/ 0x0001FF12, /* 0x0001ff0c */ 0x00200204, /* 0x00400204 */ @@ -203,17 +202,17 @@ static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = { }; static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = { - 0x00202015, - 0x1A1A3A62, - 0x15200101, - 0x01200440, - 0x74200D0D, - 0x0D5A1520, - 0x0A0A0201, - 0x1A1A2662, - 0x0D200302, - 0x02020606, - 0x05080344, + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ /*idea from mingliang.dong & vlsi zheng.bao begin*/ 0x60000404, /* 0x40020a04*/ 0x0001FF12, /* 0x0001ff0c */ @@ -222,6 +221,177 @@ static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = { /*idea from mingliang.dong & vlsi zheng.bao end*/ 0x00000131 }; + +/************************************************** + * + **************************************************/ +/*same as: combing_bias_motion_setting*/ +static const unsigned int combing_bias_p_ori[] = { + /**/ + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + 0x40020a04, /* 11 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000142 +}; + +static const unsigned int combing_very_p_ori[] = { + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x60000404, /* 0x40020a04*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000131 +}; + +static const unsigned int combing_bias_p_1080i[] = { + /**/ + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + 0x40020a04, /* 11 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x0001ff0c, + 0x00400204, + 0x00016404, + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000142 +}; + +static const unsigned int combing_very_p_1080i[] = { + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200101, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x40020a04, + 0x0001ff0c, + 0x00400204, + 0x00016404, + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000131 +}; + +/*same as combing_bias_motion_setting ex:*/ +/* 3nd : from 0x15200101 to 0x15200301*/ +static unsigned int combing_bias_p_480i[] = { + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200301, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + 0x40020a04, /* 11 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000142 +}; + +/*same as combing_very_motion_setting ex:*/ +/* 3nd : from 0x15200101 to 0x15200301*/ +static unsigned int combing_very_p_480i[] = { + 0x00202015, /* 0 */ + 0x1A1A3A62, /* 1 */ + 0x15200301, /* 2 */ + 0x01200440, /* 3 */ + 0x74200D0D, /* 4 */ + 0x0D5A1520, /* 5 */ + 0x0A0A0201, /* 6 */ + 0x1A1A2662, /* 7 */ + 0x0D200302, /* 8 */ + 0x02020606, /* 9 */ + 0x05080344, /* 10 */ + /*idea from mingliang.dong & vlsi zheng.bao begin*/ + 0x60000404, /* 0x40020a04*/ + 0x0001FF12, /* 0x0001ff0c */ + 0x00200204, /* 0x00400204 */ + 0x00012002, /* 0x00016404 */ + /*idea from mingliang.dong & vlsi zheng.bao end*/ + 0x00000131 +}; + +static unsigned int di_mtn_p_mode; + +void com_patch_pre_sw_set(unsigned int mode) +{ + unsigned int *p1, *p2; + /* mode is 0: ori */ + /* mode is 1: 1080i */ + /* mode is 2: 480i */ + if (mode == di_mtn_p_mode) + return; + + p1 = &combing_bias_motion_setting[0]; + p2 = &combing_very_motion_setting[0]; + if (mode == 0) { + memcpy(p1, &combing_bias_p_ori[0], + sizeof(combing_bias_p_ori)); + memcpy(p2, &combing_very_p_ori[0], + sizeof(combing_very_p_ori)); + di_mtn_p_mode = 0; + } else if (mode == 1) { + memcpy(p1, &combing_bias_p_1080i[0], + sizeof(combing_bias_p_1080i)); + memcpy(p2, &combing_very_p_1080i[0], + sizeof(combing_very_p_1080i)); + di_mtn_p_mode = 1; + } else if (mode == 2) { + memcpy(p1, &combing_bias_p_480i[0], + sizeof(combing_bias_p_480i)); + memcpy(p2, &combing_very_p_480i[0], + sizeof(combing_very_p_480i)); + di_mtn_p_mode = 2; + } +} + /*special for resolution test file*/ static unsigned int combing_resolution_setting[MAX_NUM_DI_REG] = { 0x00202015, @@ -301,6 +471,7 @@ void mtn_int_combing_glbmot(void) if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) {/*from VLSI yanling.liu*/ combing_glbmot_radprat[0] = 30; } + di_mtn_p_mode = 0; } void adpative_combing_exit(void) { @@ -495,13 +666,19 @@ static unsigned int small_local_mtn = 70; module_param(small_local_mtn, uint, 0644); MODULE_PARM_DESC(small_local_mtn, "small_local_mtn"); +static unsigned int small_local_mtn1 = 30; +module_param(small_local_mtn1, uint, 0644); +MODULE_PARM_DESC(small_local_mtn1, "small_local_mtn1"); + unsigned int adp_set_mtn_ctrl10(unsigned int diff, unsigned int dlvel, unsigned int frame_diff_avg) { int istp = 0, idats = 0, idatm = 0, idatr = 0; unsigned int rst = 0; - if (frame_diff_avg < small_local_mtn) + if ( + (frame_diff_avg < small_local_mtn) && + (frame_diff_avg > small_local_mtn1)) rst = combing_very_motion_setting[9]; else if (dlvel == 0) { if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) @@ -636,7 +813,7 @@ MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg"); /*from VLSI yanling.liu, the patch fix TL1 1080I in some dark */ /*scenes and roller coasters have small sawtooth, when turn off*/ /*combing_fix_en, set the registers*/ -void fix_tl1_1080i_sawtooth_patch(void) +static void fix_tl1_1080i_sawtooth_patch(void) { DI_Wr(0x1741, 0x0A0A1A22); DI_Wr(0x1742, 0x0a100101); @@ -651,6 +828,35 @@ void fix_tl1_1080i_sawtooth_patch(void) DI_Wr(0x17af, 0x60020a60); } +static void fix_tl1_1080i_patch2(void) +{ + DI_Wr(0x1741, 0x010a010a); + DI_Wr(0x1742, 0x01010101); + DI_Wr(0x1743, 0x00000101); + DI_Wr(0x1744, 0x00000101); + DI_Wr(0x17a9, 0x01010102); + DI_Wr(0x17aa, 0x02020101); + DI_Wr(0x17ab, 0x010a010a); + DI_Wr(0x17ac, 0x010a0102); + DI_Wr(0x17ad, 0x08080808); + DI_Wr(0x17ae, 0x01010101); + DI_Wr(0x17af, 0xff00031f); +} + +void fix_tl1_1080i_patch_sel(unsigned int mode) +{ + switch (mode) { + case 0:/*not set*/ + break; + case 1: + fix_tl1_1080i_sawtooth_patch(); + break; + case 2: + fix_tl1_1080i_patch2(); + break; + } +} + static int combing_cnt; int combing_diff_min = 2000; int combing_diff_max = 2000; @@ -714,9 +920,16 @@ int adaptive_combing_fixing( combing_cnt = combing_cnt + 1; else combing_cnt = 0; - if (glb_mot[0] < combing_diff_min && glb_mot[1] > combing_diff_max && - combing_cnt <= combing_cnt_thd) - glb_mot[0] = glb_mot[1]; + if ( + is_meson_txhd_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { + if ( + glb_mot[0] < combing_diff_min && + glb_mot[1] > combing_diff_max && + combing_cnt <= combing_cnt_thd) + glb_mot[0] = glb_mot[1]; + } glb_mot_avg5 = (glb_mot[0] + glb_mot[1] + glb_mot[2] + glb_mot[3] + glb_mot[4]) / 5; @@ -816,9 +1029,10 @@ module_param_named(cmb_adpset_cnt, cmb_adpset_cnt, int, 0644); static const struct mtn_op_s di_ops_mtn = { .mtn_int_combing_glbmot = mtn_int_combing_glbmot, .adpative_combing_exit = adpative_combing_exit, - .fix_tl1_1080i_sawtooth_patch = fix_tl1_1080i_sawtooth_patch, + .fix_tl1_1080i_patch_sel = fix_tl1_1080i_patch_sel, .adaptive_combing_fixing = adaptive_combing_fixing, .adpative_combing_config = adpative_combing_config, + .com_patch_pre_sw_set = com_patch_pre_sw_set, /*.module_para = dim_seq_file_module_para_mtn,*/ }; diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h index 13cc468c7e07..0592f5dd69b8 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h @@ -39,12 +39,13 @@ struct combing_status_s *adpative_combing_config(unsigned int width, unsigned int height, enum vframe_source_type_e src_type, bool prog, enum tvin_sig_fmt_e fmt); -extern void fix_tl1_1080i_sawtooth_patch(void); +void fix_tl1_1080i_patch_sel(unsigned int mode); int adaptive_combing_fixing( struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, int bit_mode); void adpative_combing_exit(void); extern void mtn_int_combing_glbmot(void); +void com_patch_pre_sw_set(unsigned int mode); #endif diff --git a/drivers/amlogic/media/deinterlace/di_pqa.h b/drivers/amlogic/media/deinterlace/di_pqa.h index dbe43803cb24..fcf3e54ba969 100644 --- a/drivers/amlogic/media/deinterlace/di_pqa.h +++ b/drivers/amlogic/media/deinterlace/di_pqa.h @@ -111,7 +111,7 @@ bool di_attach_ops_nr(const struct nr_op_s **ops); struct mtn_op_s { void (*mtn_int_combing_glbmot)(void); void (*adpative_combing_exit)(void); - void (*fix_tl1_1080i_sawtooth_patch)(void); + void (*fix_tl1_1080i_patch_sel)(unsigned int mode); int (*adaptive_combing_fixing)( struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, @@ -123,6 +123,7 @@ struct mtn_op_s { enum vframe_source_type_e src_type, bool prog, enum tvin_sig_fmt_e fmt); + void (*com_patch_pre_sw_set)(unsigned int mode); int (*module_para)(struct seq_file *seq); }; diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c index f3172c3e4854..919dc77c6133 100644 --- a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c @@ -235,6 +235,29 @@ static int dif01_ratio = 10; module_param(dif01_ratio, int, 0644); MODULE_PARM_DESC(dif01_ratio, "dif01_ratio"); +static int nflagch4_ratio = 1; +module_param(nflagch4_ratio, int, 0644); +MODULE_PARM_DESC(nflagch4_ratio, "nflagch4_ratio"); + +static int nflagch5_ratio = 2; +module_param(nflagch5_ratio, int, 0644); +MODULE_PARM_DESC(nflagch5_ratio, "nflagch5_ratio"); + +static int nflagch4_th = 0; +module_param(nflagch4_th, int, 0644); +MODULE_PARM_DESC(nflagch4_th, "nflagch4_th"); + +static int nflagch5_th = 0; +module_param(nflagch5_th, int, 0644); +MODULE_PARM_DESC(nflagch5_th, "nflagch5_th"); + +static int dif02_flag = 1; +module_param(dif02_flag, int, 0644); +MODULE_PARM_DESC(dif02_flag, "dif02_flag"); + +static int dif02_ratio = 20; +module_param(dif02_ratio, int, 0644); +MODULE_PARM_DESC(dif02_ratio, "dif02_ratio"); static int flm22_force; @@ -697,6 +720,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int nFlgChk1 = 0; int nFlgChk2 = 0; int nFlgChk3 = 0; /* for Mit32VHLine */ + int nFlgChk4 = 0; + int nFlgChk5 = 0; + int nMean = 0; int luma_avg = 0; int flm32_dif02_gap = 0; @@ -749,7 +775,11 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, nSM += nT1; } } - nAV11 = (nSM - nMx + nT2 / 2) / (nT2 - 1); + /* for coverity error,"nT2 - 1" which may be zero */ + if (nT2 != 1) + nAV11 = (nSM - nMx + nT2 / 2) / (nT2 - 1); + else + pr_info("%s: Error nT2 is one\n", __func__); nAV1 = (sFrmDifAvgRat * nAV11 + (32 - sFrmDifAvgRat) * nAV12); nAV1 = ((nAV1 + 16) >> 5); @@ -819,6 +849,35 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlgChk1 = 0; nFlgChk2 = 0; } + //nFlgChk4/5 large dif change quit mode + if ( + pFlg32[HISDETNUM - 1] > 1 && (dif02_flag || + nDif02[HISDIFNUM - 1] > (1 << dif02_ratio))) { + nFlgChk4 = nDif02[HISDIFNUM - 1] - nDif02[HISDIFNUM - 6]; + if (nFlgChk4 < 0) + nFlgChk4 = -nFlgChk4; + nFlgChk4 = nFlgChk4; + nMean = (nDif02[HISDIFNUM - 1] + nDif01[HISDIFNUM - 6]) / 2; + nFlgChk4 = nflagch4_ratio * nFlgChk4 / nMean; + } else { + nFlgChk4 = 0; + } + if ( + pFlg32[HISDETNUM - 1] == 1 || + pFlg32[HISDETNUM - 1] == 2 || + pFlg32[HISDETNUM - 1] == 4) { + nFlgChk5 = nDif01[HISDIFNUM - 1] - nDif01[HISDIFNUM - 6]; + if (nFlgChk5 < 0) + nFlgChk5 = -nFlgChk5; + nMean = (nDif01[HISDIFNUM - 1] + nDif01[HISDIFNUM - 6]) / 2; + nFlgChk5 = nflagch5_ratio * nFlgChk5 / nMean; + } else { + nFlgChk5 = 0; + } + if (prt_flg) + sprintf(debug_str + strlen(debug_str), + "nFlgChk4/5=(%2d,%2d)\n", + nFlgChk4, nFlgChk5); nT2 = 5 * nDif02[HISDIFNUM - 1] / (nMn + sFrmDifLgTDif + 1); nT2 = nT2>>1; @@ -839,7 +898,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nSTP > 16) nSTP = 16; /*patch for dark scenes don't into pulldown32 by vlsi yanling*/ - if (((nMx + nMn/2) / (nMn + 1)) < flm32_dif02_gap) + if ( + ((nMx + nMn / 2) / (nMn + 1)) < flm32_dif02_gap && + pFlg32[HISDETNUM - 1] > 1) nSTP = 0; /*---------------*/ for (nT0 = 1; nT0 < HISDETNUM; nT0++) { @@ -913,6 +974,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, } nFlg12[nT0] = ((nSTP + 8) >> 4); + + if (nT0 == 5 && nMIX == 1 && nFlg01[nT0] == 0) + nFlg12[nT0] = 0; } /* -------------------------------------------- */ @@ -964,7 +1028,9 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, (nFlgChk3 > flm32_ck13_rtn)) || (nFlgChk2 > flm32_chk2_rtn) || ((pFlg32[HISDETNUM-1] == 4) && - (nFlgChk3 > flm32_chk3_rtn))) { + (nFlgChk3 > flm32_chk3_rtn)) || + (nFlgChk4 > nflagch4_th || + nFlgChk5 > nflagch5_th)) { pRDat->pMod32[HISDETNUM - 1] = 0; pRDat->pFlg32[HISDETNUM - 1] = 0; @@ -1376,8 +1442,17 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, } nFlgChk6 = nFlgChk6 / 6; - nAV21 = (nSM21 + nL21 / 2) / nL21; /* High average */ - nAV22 = (nSM22 + nL22 / 2) / nL22; /* Low average */ + /* for coverity error,"nL21/nL22" which may be zero */ + if (nL21) + nAV21 = (nSM21 + nL21 / 2) / nL21; /* High average */ + else + pr_info("%s: Error nL21 is zero\n", __func__); + + if (nL22) + nAV22 = (nSM22 + nL22 / 2) / nL22; /* Low average */ + else + pr_info("%s: Error nL22 is zero\n", __func__); + nOfst = nAV21 - nAV22; if (prt_flg) diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c index e63015bbeb51..19db64421530 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.c +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -47,6 +47,8 @@ module_param_named(nr2_en, nr2_en, uint, 0644); static bool nr_ctrl_reg; +bool nr_demo_flag; + int global_bs_calc_sw(int *pGbsVldCnt, int *pGbsVldFlg, int *pGbs, @@ -1196,6 +1198,18 @@ static void nr_all_ctrl(bool enable) DI_Wr_reg_bits(DNR_CTRL, value, 16, 1); } + +static void nr_demo_mode(bool enable) +{ + if (enable) { + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 6, 3); + nr_demo_flag = 1; + } else { + DI_Wr_reg_bits(NR4_TOP_CTRL, 7, 6, 3); + nr_demo_flag = 0; + } +} + static ssize_t nr_dbg_store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) @@ -1208,6 +1222,15 @@ static ssize_t nr_dbg_store(struct device *dev, nr_all_ctrl(false); else if (!strcmp(parm[0], "enable")) nr_all_ctrl(true); + else if (!strcmp(parm[0], "demo")) { + if (!strcmp(parm[1], "enable")) { + nr_demo_mode(true); + pr_info("nr demo enable\n"); + } else if (!strcmp(parm[1], "disable")) { + nr_demo_mode(false); + pr_info("nr demo disable\n"); + } + } kfree(buf_orig); return count; diff --git a/drivers/amlogic/media/deinterlace/nr_drv.h b/drivers/amlogic/media/deinterlace/nr_drv.h index 3af10f6adab4..9b160d4fdf27 100644 --- a/drivers/amlogic/media/deinterlace/nr_drv.h +++ b/drivers/amlogic/media/deinterlace/nr_drv.h @@ -186,5 +186,6 @@ bool set_nr_ctrl_reg_table(unsigned int addr, unsigned int value); extern void cue_int(struct vframe_s *vf); +extern bool nr_demo_flag; #endif diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index 5d8a36acb1de..ac9105a77e48 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -180,6 +180,13 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, #define MCINFWR_Y 0x37f6 #define MCINFWR_CTRL 0x37f7 #define MCINFWR_CAN_SIZE 0x37f8 + +/* from TM2 new added */ +/* DI HDR2 */ +#define DI_HDR2_HIST_CTRL 0x37ad +#define DI_HDR2_HIST_H_START_END 0x37ae +#define DI_HDR2_HIST_V_START_END 0x37af + /* DI SCALE */ #define DI_SCO_FIFO_CTRL 0x374e #define DI_SC_TOP_CTRL 0x374f diff --git a/drivers/amlogic/media/di_local/di_local.c b/drivers/amlogic/media/di_local/di_local.c index 18fb0e5fbbfc..3d86532d8dc0 100644 --- a/drivers/amlogic/media/di_local/di_local.c +++ b/drivers/amlogic/media/di_local/di_local.c @@ -127,6 +127,13 @@ int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len) } EXPORT_SYMBOL(DI_POST_WR_REG_BITS); +void DI_POST_UPDATE_MC(void) +{ + if (dil_api && dil_api->post_update_mc) + dil_api->post_update_mc(); +} +EXPORT_SYMBOL(DI_POST_UPDATE_MC); + /*************************************** * reserved mem for di * **************************************/ diff --git a/drivers/amlogic/media/di_local/di_local.h b/drivers/amlogic/media/di_local/di_local.h index b956011a4403..7f4b548394c1 100644 --- a/drivers/amlogic/media/di_local/di_local.h +++ b/drivers/amlogic/media/di_local/di_local.h @@ -21,6 +21,7 @@ struct di_ext_ops { unsigned int (*di_post_reg_rd)(unsigned int addr); int (*di_post_wr_reg_bits)(u32 adr, u32 val, u32 start, u32 len); + void (*post_update_mc)(void); }; #endif /*__DI_LOCAL_H__*/ diff --git a/drivers/amlogic/media/di_multi/Kconfig b/drivers/amlogic/media/di_multi/Kconfig new file mode 100644 index 000000000000..8670046914f2 --- /dev/null +++ b/drivers/amlogic/media/di_multi/Kconfig @@ -0,0 +1,15 @@ +# +# Deinterlace driver configuration +# + +menu "DI_MULTI driver" + +config AMLOGIC_MEDIA_DEINTERLACE + tristate "DI_MULTI driver" + default n + help + Select to enable AMLOGIC DEINTERLACE driver + process interlace source need three continueed fields, + wave progressive source with two interlace fields from + one progreesive fields +endmenu diff --git a/drivers/amlogic/media/di_multi/Makefile b/drivers/amlogic/media/di_multi/Makefile new file mode 100644 index 000000000000..23df5523652e --- /dev/null +++ b/drivers/amlogic/media/di_multi/Makefile @@ -0,0 +1,34 @@ +# # Makefile for the Post Process Manager device # +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +ccflags-y := -D DEBUG_SUPPORT +ccflags-y := -DDEBUG +else +ccflags-y := -DDEBUG +endif +ccflags-y += -I. +CFLAGS_dim.o := -I$(src) +obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += dim.o +dim-objs += deinterlace.o +dim-objs += deinterlace_hw.o +#dim-objs += deinterlace_mtn.o +dim-objs += deinterlace_dbg.o +#dim-objs += nr_drv.o +#dim-objs += pulldown_drv.o +#dim-objs += detect3d.o +dim-objs += nr_downscale.o +dim-objs += di_pps.o +dim-objs += di_vframe.o +dim-objs += di_prc.o +dim-objs += di_pre.o +dim-objs += di_post.o +dim-objs += di_reg_tab.o +dim-objs += di_dbg.o +dim-objs += di_que.o +dim-objs += di_sys.o +dim-objs += di_task.o +dim-objs += di_api.o +#dim-objs += film_mode_fmw/vof_soft_top.o +#dim-objs += film_mode_fmw/flm_mod_xx.o +#dim-objs += film_mode_fmw/film_fw1.o +ccflags-y += -Idrivers/amlogic/media/common/rdma/ +ccflags-y += -I$(src) \ No newline at end of file diff --git a/drivers/amlogic/media/di_multi/deinterlace.c b/drivers/amlogic/media/di_multi/deinterlace.c new file mode 100644 index 000000000000..34f13c39ce62 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace.c @@ -0,0 +1,8417 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA +#include +#endif +#include +#include "register.h" +#include "deinterlace.h" +#include "deinterlace_dbg.h" +#include "nr_downscale.h" + +#include "di_data_l.h" +#include "di_dbg.h" +#include "di_pps.h" +#include "di_pre.h" +#include "di_prc.h" +#include "di_task.h" +#include "di_vframe.h" +#include "di_que.h" +#include "di_api.h" +#include "di_sys.h" + +/*2018-07-18 add debugfs*/ +#include +#include +/*2018-07-18 -----------*/ + +#ifdef DET3D +#include "detect3d.h" +#endif +#define ENABLE_SPIN_LOCK_ALWAYS + +static DEFINE_SPINLOCK(di_lock2); + +#define di_lock_irqfiq_save(irq_flag) \ + spin_lock_irqsave(&di_lock2, irq_flag) + +#define di_unlock_irqfiq_restore(irq_flag) \ + spin_unlock_irqrestore(&di_lock2, irq_flag) + +#ifdef SUPPORT_MPEG_TO_VDIN +static int mpeg2vdin_flag; +static int mpeg2vdin_en; +#endif + +static int di_reg_unreg_cnt = 40; +static bool overturn; + +int dim_get_reg_unreg_cnt(void) +{ + return di_reg_unreg_cnt; +} + +static bool mc_mem_alloc; + +static unsigned int di_pre_rdma_enable; + +/************************************** + * + * + *************************************/ +unsigned int di_dbg = DBG_M_EVENT; +module_param(di_dbg, uint, 0664); +MODULE_PARM_DESC(di_dbg, "debug print"); + +/* destroy unnecessary frames before display */ +static unsigned int hold_video; + +DEFINE_SPINLOCK(plist_lock); + +static const char version_s[] = "2019-04-25ma"; + +/*1:enable bypass pre,ei only; + * 2:debug force bypass pre,ei for post + */ +static int bypass_pre; + +static int invert_top_bot; + +/* add avoid vframe put/get error */ +static int di_blocking; +/* + * bit[2]: enable bypass all when skip + * bit[1:0]: enable bypass post when skip + */ +/*static int di_vscale_skip_enable;*/ + +/* 0: not support nr10bit, 1: support nr10bit */ +/*static unsigned int nr10bit_support;*/ + +#ifdef RUN_DI_PROCESS_IN_IRQ +/* + * di_process() run in irq, + * dim_reg_process(), dim_unreg_process() run in kernel thread + * dim_reg_process_irq(), di_unreg_process_irq() run in irq + * di_vf_put(), di_vf_peek(), di_vf_get() run in irq + * di_receiver_event_fun() run in task or irq + */ +/* + * important: + * to set input2pre, VFRAME_EVENT_PROVIDER_VFRAME_READY of + * vdin should be sent in irq + */ + +static int input2pre; +/*false:process progress by field; + * true: process progress by frame with 2 interlace buffer + */ +static int input2pre_buf_miss_count; +static int input2pre_proc_miss_count; +static int input2pre_throw_count; +static int input2pre_miss_policy; +/* 0, do not force pre_de_busy to 0, use di_wr_buf after dim_irq happen; + * 1, force pre_de_busy to 0 and call + * dim_pre_de_done_buf_clear to clear di_wr_buf + */ +#endif +/*false:process progress by field; + * bit0: process progress by frame with 2 interlace buffer + * bit1: temp add debug for 3d process FA,1:bit0 force to 1; + */ +/*static int use_2_interlace_buff;*/ +/* prog_proc_config, + * bit[2:1]: when two field buffers are used, + * 0 use vpp for blending , + * 1 use post_di module for blending + * 2 debug mode, bob with top field + * 3 debug mode, bot with bot field + * bit[0]: + * 0 "prog vdin" use two field buffers, + * 1 "prog vdin" use single frame buffer + * bit[4]: + * 0 "prog frame from decoder/vdin" use two field buffers, + * 1 use single frame buffer + * bit[5]: + * when two field buffers are used for decoder (bit[4] is 0): + * 1,handle prog frame as two interlace frames + * bit[6]:(bit[4] is 0,bit[5] is 0,use_2_interlace_buff is 0): 0, + * process progress frame as field,blend by post; + * 1, process progress frame as field,process by normal di + */ +/*static int prog_proc_config = (1 << 5) | (1 << 1) | 1;*/ +/* + * for source include both progressive and interlace pictures, + * always use post_di module for blending + */ +#define is_handle_prog_frame_as_interlace(vframe) \ + (((dimp_get(eDI_MP_prog_proc_config) & 0x30) == 0x20) && \ + (((vframe)->type & VIDTYPE_VIU_422) == 0)) + +static int frame_count; +static int disp_frame_count; +int di_get_disp_cnt(void) +{ + return disp_frame_count; +} + +static unsigned long reg_unreg_timeout_cnt; +#ifdef DET3D +static unsigned int det3d_mode; +static void set3d_view(enum tvin_trans_fmt trans_fmt, struct vframe_s *vf); +#endif + +static void di_pq_parm_destroy(struct di_pq_parm_s *pq_ptr); +static struct di_pq_parm_s *di_pq_parm_create(struct am_pq_parm_s *); + +static unsigned int unreg_cnt;/*cnt for vframe unreg*/ +static unsigned int reg_cnt;/*cnt for vframe reg*/ + +static unsigned char recovery_flag; + +static unsigned int recovery_log_reason; +static unsigned int recovery_log_queue_idx; +static struct di_buf_s *recovery_log_di_buf; + +unsigned char dim_vcry_get_flg(void) +{ + return recovery_flag; +} + +void dim_vcry_flg_inc(void) +{ + recovery_flag++; +} + +void dim_vcry_set_flg(unsigned char val) +{ + recovery_flag = val; +} + +void dim_reg_timeout_inc(void) +{ + reg_unreg_timeout_cnt++; +} + +/********************************/ +unsigned int dim_vcry_get_log_reason(void) +{ + return recovery_log_reason; +} + +void dim_vcry_set_log_reason(unsigned int val) +{ + recovery_log_reason = val; +} + +/********************************/ +unsigned char dim_vcry_get_log_q_idx(void) +{ + return recovery_log_queue_idx; +} + +void dim_vcry_set_log_q_idx(unsigned int val) +{ + recovery_log_queue_idx = val; +} + +/********************************/ +struct di_buf_s **dim_vcry_get_log_di_buf(void) +{ + return &recovery_log_di_buf; +} + +void dim_vcry_set_log_di_buf(struct di_buf_s *di_bufp) +{ + recovery_log_di_buf = di_bufp; +} + +void dim_vcry_set(unsigned int reason, unsigned int idx, + struct di_buf_s *di_bufp) +{ + recovery_log_reason = reason; + recovery_log_queue_idx = idx; + recovery_log_di_buf = di_bufp; +} + +static long same_field_top_count; +static long same_field_bot_count; +/* bit 0: + * 0, keep 3 buffers in pre_ready_list for checking; + * 1, keep 4 buffers in pre_ready_list for checking; + */ + +static struct queue_s *get_queue_by_idx(unsigned int channel, int idx); +static void dump_state(unsigned int channel); +static void recycle_keep_buffer(unsigned int channel); + +#define DI_PRE_INTERVAL (HZ / 100) + +/* + * progressive frame process type config: + * 0, process by field; + * 1, process by frame (only valid for vdin source whose + * width/height does not change) + */ + +static struct di_buf_s *cur_post_ready_di_buf; + +/************For Write register**********************/ + +static unsigned int num_di_stop_reg_addr = 4; +static unsigned int di_stop_reg_addr[4] = {0}; + +static unsigned int is_need_stop_reg(unsigned int addr) +{ + int idx = 0; + + if (dimp_get(eDI_MP_di_stop_reg_flag)) { + for (idx = 0; idx < num_di_stop_reg_addr; idx++) { + if (addr == di_stop_reg_addr[idx]) { + pr_dbg("stop write addr: %x\n", addr); + return 1; + } + } + } + + return 0; +} + +void dim_DI_Wr(unsigned int addr, unsigned int val) +{ + if (is_need_stop_reg(addr)) + return; + ddbg_reg_save(addr, val, 0, 32); + Wr(addr, val); +} + +void dim_DI_Wr_reg_bits(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len) +{ + if (is_need_stop_reg(adr)) + return; + ddbg_reg_save(adr, val, start, len); /*ary add for debug*/ + Wr_reg_bits(adr, val, start, len); +} + +void dim_VSYNC_WR_MPEG_REG(unsigned int addr, unsigned int val) +{ + if (is_need_stop_reg(addr)) + return; + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) + dim_DI_Wr(addr, val); + else + VSYNC_WR_MPEG_REG(addr, val); +} + +void dim_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, unsigned int val, + unsigned int start, unsigned int len) +{ + if (is_need_stop_reg(addr)) + return; + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) + dim_DI_Wr_reg_bits(addr, val, start, len); + else + VSYNC_WR_MPEG_REG_BITS(addr, val, start, len); +} + +#ifdef DI_V2 +unsigned int DI_POST_REG_RD(unsigned int addr) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (IS_ERR_OR_NULL(de_devp)) + return 0; + if (de_devp->flags & DI_SUSPEND_FLAG) { + PR_ERR("REG 0x%x access prohibited.\n", addr); + return 0; + } + return VSYNC_RD_MPEG_REG(addr); +} +EXPORT_SYMBOL(DI_POST_REG_RD); + +int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (IS_ERR_OR_NULL(de_devp)) + return 0; + if (de_devp->flags & DI_SUSPEND_FLAG) { + PR_ERR("REG 0x%x access prohibited.\n", adr); + return -1; + } + return VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); +} +EXPORT_SYMBOL(DI_POST_WR_REG_BITS); +#else +unsigned int l_DI_POST_REG_RD(unsigned int addr) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (IS_ERR_OR_NULL(de_devp)) + return 0; + if (de_devp->flags & DI_SUSPEND_FLAG) { + PR_ERR("REG 0x%x access prohibited.\n", addr); + return 0; + } + return VSYNC_RD_MPEG_REG(addr); +} + +int l_DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (IS_ERR_OR_NULL(de_devp)) + return 0; + if (de_devp->flags & DI_SUSPEND_FLAG) { + PR_ERR("REG 0x%x access prohibited.\n", adr); + return -1; + } + return VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); +} + +#endif +/**********************************/ + +/***************************** + * di attr management : + * enable + * mode + * reg + ******************************/ +/*config attr*/ + +int pre_run_flag = DI_RUN_FLAG_RUN; +static int dump_state_flag; + +const char *dim_get_version_s(void) +{ + return version_s; +} + +int dim_get_blocking(void) +{ + return di_blocking; +} + +unsigned long dim_get_reg_unreg_timeout_cnt(void) +{ + return reg_unreg_timeout_cnt; +} + +struct di_buf_s *dim_get_recovery_log_di_buf(void) +{ + return recovery_log_di_buf; +} + +struct vframe_s **dim_get_vframe_in(unsigned int ch) +{ + return get_vframe_in(ch); +} + +int dim_get_dump_state_flag(void) +{ + return dump_state_flag; +} + +/*--------------------------*/ + +ssize_t +store_dbg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int channel = get_current_channel(); /* debug only*/ + struct di_buf_s *pbuf_local = get_buf_local(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + + if (strncmp(buf, "buf", 3) == 0) { + struct di_buf_s *di_buf_tmp = 0; + + if (kstrtoul(buf + 3, 16, (unsigned long *)&di_buf_tmp)) + return count; + dim_dump_di_buf(di_buf_tmp); + } else if (strncmp(buf, "vframe", 6) == 0) { + vframe_t *vf = 0; + + if (kstrtoul(buf + 6, 16, (unsigned long *)&vf)) + return count; + dim_dump_vframe(vf); + } else if (strncmp(buf, "pool", 4) == 0) { + unsigned long idx = 0; + + if (kstrtoul(buf + 4, 10, &idx)) + return count; + dim_dump_pool(get_queue_by_idx(channel, idx)); + } else if (strncmp(buf, "state", 4) == 0) { + dump_state(channel); + pr_info("add new debugfs: cat /sys/kernel/debug/di/state\n"); + } else if (strncmp(buf, "prog_proc_config", 16) == 0) { + if (buf[16] == '1') + dimp_set(eDI_MP_prog_proc_config, 1); + else + dimp_set(eDI_MP_prog_proc_config, 0); + } else if (strncmp(buf, "init_flag", 9) == 0) { + if (buf[9] == '1') + set_init_flag(0, true);/*init_flag = 1;*/ + else + set_init_flag(0, false);/*init_flag = 0;*/ + } else if (strncmp(buf, "prun", 4) == 0) { + pre_run_flag = DI_RUN_FLAG_RUN; + } else if (strncmp(buf, "ppause", 6) == 0) { + pre_run_flag = DI_RUN_FLAG_PAUSE; + } else if (strncmp(buf, "pstep", 5) == 0) { + pre_run_flag = DI_RUN_FLAG_STEP; + } else if (strncmp(buf, "dumpreg", 7) == 0) { + pr_info("add new debugfs: cat /sys/kernel/debug/di/dumpreg\n"); + } else if (strncmp(buf, "dumpmif", 7) == 0) { + dim_dump_mif_size_state(ppre, ppost); + } else if (strncmp(buf, "recycle_buf", 11) == 0) { + recycle_keep_buffer(channel); + } else if (strncmp(buf, "recycle_post", 12) == 0) { + if (di_vf_l_peek(channel)) + di_vf_l_put(di_vf_l_get(channel), channel); + } else if (strncmp(buf, "mem_map", 7) == 0) { + dim_dump_buf_addr(pbuf_local, MAX_LOCAL_BUF_NUM * 2); + } else { + pr_info("DI no support cmd %s!!!\n", buf); + } + + return count; +} + +#ifdef ARY_TEMP +static int __init di_read_canvas_reverse(char *str) +{ + unsigned char *ptr = str; + + pr_dbg("%s: bootargs is %s.\n", __func__, str); + if (strstr(ptr, "1")) { + invert_top_bot |= 0x1; + overturn = true; + } else { + invert_top_bot &= (~0x1); + overturn = false; + } + + return 0; +} + +__setup("video_reverse=", di_read_canvas_reverse); +#endif + +static unsigned char *di_log_buf; +static unsigned int di_log_wr_pos; +static unsigned int di_log_rd_pos; +static unsigned int di_log_buf_size; + +static unsigned int buf_state_log_start; +/* set to 1 by condition of "post_ready count < buf_state_log_threshold", + * reset to 0 by set buf_state_log_threshold as 0 + */ + +static DEFINE_SPINLOCK(di_print_lock); + +#define PRINT_TEMP_BUF_SIZE 128 + +static int di_print_buf(char *buf, int len) +{ + unsigned long flags; + int pos; + int di_log_rd_pos_; + + if (di_log_buf_size == 0) + return 0; + + spin_lock_irqsave(&di_print_lock, flags); + di_log_rd_pos_ = di_log_rd_pos; + if (di_log_wr_pos >= di_log_rd_pos) + di_log_rd_pos_ += di_log_buf_size; + + for (pos = 0; pos < len && di_log_wr_pos < (di_log_rd_pos_ - 1); + pos++, di_log_wr_pos++) { + if (di_log_wr_pos >= di_log_buf_size) + di_log_buf[di_log_wr_pos - di_log_buf_size] = buf[pos]; + else + di_log_buf[di_log_wr_pos] = buf[pos]; + } + if (di_log_wr_pos >= di_log_buf_size) + di_log_wr_pos -= di_log_buf_size; + spin_unlock_irqrestore(&di_print_lock, flags); + return pos; +} + +/* static int log_seq = 0; */ +int dim_print(const char *fmt, ...) +{ + va_list args; + int avail = PRINT_TEMP_BUF_SIZE; + char buf[PRINT_TEMP_BUF_SIZE]; + int pos, len = 0; + + if (dimp_get(eDI_MP_di_printk_flag) & 1) { + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_PRECISE_TIMESTAMP) + pr_dbg("%llums:", cur_to_msecs()); + va_start(args, fmt); + vprintk(fmt, args); + va_end(args); + return 0; + } + + if (di_log_buf_size == 0) + return 0; + +/* len += snprintf(buf+len, avail-len, "%d:",log_seq++); */ + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_TIMESTAMP) + len += snprintf(buf + len, avail - len, "%u:", + jiffies_to_msecs(jiffies_64)); + + va_start(args, fmt); + len += vsnprintf(buf + len, avail - len, fmt, args); + va_end(args); + + if ((avail - len) <= 0) + buf[PRINT_TEMP_BUF_SIZE - 1] = '\0'; + + pos = di_print_buf(buf, len); +/* pr_dbg("dim_print:%d %d\n", di_log_wr_pos, di_log_rd_pos); */ + return pos; +} + +ssize_t dim_read_log(char *buf) +{ + unsigned long flags; + ssize_t read_size = 0; + + if (di_log_buf_size == 0) + return 0; +/* pr_dbg("show_log:%d %d\n", di_log_wr_pos, di_log_rd_pos); */ + spin_lock_irqsave(&di_print_lock, flags); + if (di_log_rd_pos < di_log_wr_pos) + read_size = di_log_wr_pos - di_log_rd_pos; + + else if (di_log_rd_pos > di_log_wr_pos) + read_size = di_log_buf_size - di_log_rd_pos; + + if (read_size > PAGE_SIZE) + read_size = PAGE_SIZE; + if (read_size > 0) + memcpy(buf, di_log_buf + di_log_rd_pos, read_size); + + di_log_rd_pos += read_size; + if (di_log_rd_pos >= di_log_buf_size) + di_log_rd_pos = 0; + spin_unlock_irqrestore(&di_print_lock, flags); + return read_size; +} + +ssize_t +store_log(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long flags, tmp; + + if (strncmp(buf, "bufsize", 7) == 0) { + if (kstrtoul(buf + 7, 10, &tmp)) + return count; + spin_lock_irqsave(&di_print_lock, flags); + kfree(di_log_buf); + di_log_buf = NULL; + di_log_buf_size = 0; + di_log_rd_pos = 0; + di_log_wr_pos = 0; + if (tmp >= 1024) { + di_log_buf_size = 0; + di_log_rd_pos = 0; + di_log_wr_pos = 0; + di_log_buf = kmalloc(tmp, GFP_KERNEL); + if (di_log_buf) + di_log_buf_size = tmp; + } + spin_unlock_irqrestore(&di_print_lock, flags); + pr_dbg("di_store:set bufsize tmp %lu %u\n", + tmp, di_log_buf_size); + } else if (strncmp(buf, "printk", 6) == 0) { + if (kstrtoul(buf + 6, 10, &tmp)) + return count; + + dimp_set(eDI_MP_di_printk_flag, tmp); + } else { + dim_print("%s", buf); + } + return 16; +} + +ssize_t +show_vframe_status(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret = 0; + int get_ret = 0; + + struct vframe_states states; + int ch; + struct di_mng_s *pbm = get_bufmng(); + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + if (!pbm->sub_act_flg[ch]) + continue; + else + ret += sprintf(buf + ret, "ch[%d]\n", ch); + + get_ret = vf_get_states_by_name(di_rev_name[ch], &states); + + if (get_ret == 0) { + ret += sprintf(buf + ret, "vframe_pool_size=%d\n", + states.vf_pool_size); + ret += sprintf(buf + ret, "vframe buf_free_num=%d\n", + states.buf_free_num); + ret += sprintf(buf + ret, "vframe buf_recycle_num=%d\n", + states.buf_recycle_num); + ret += sprintf(buf + ret, "vframe buf_avail_num=%d\n", + states.buf_avail_num); + } else { + ret += sprintf(buf + ret, "vframe no states\n"); + } + } + return ret; +} + +/*************************** + * di buffer management + ***************************/ + +static const char * const vframe_type_name[] = { + "", "di_buf_in", "di_buf_loc", "di_buf_post" +}; + +const char *dim_get_vfm_type_name(unsigned int nub) +{ + if (nub < 4) + return vframe_type_name[nub]; + + return ""; +} + +static unsigned int default_width = 1920; +static unsigned int default_height = 1080; + +/* + * all buffers are in + * 1) list of local_free_list,in_free_list,pre_ready_list,recycle_list + * 2) di_pre_stru.di_inp_buf + * 3) di_pre_stru.di_wr_buf + * 4) cur_post_ready_di_buf + * 5) (struct di_buf_s*)(vframe->private_data)->di_buf[] + * + * 6) post_free_list_head + * 8) (struct di_buf_s*)(vframe->private_data) + */ + +/*move to deinterlace .h #define queue_t struct queue_s*/ + +static struct queue_s *get_queue_by_idx(unsigned int channel, int idx) +{ + struct queue_s *pqueue = get_queue(channel); + + if (idx < QUEUE_NUM) + return &pqueue[idx]; + else + return NULL; +} + +struct di_buf_s *dim_get_buf(unsigned int channel, int queue_idx, + int *start_pos) +{ + struct queue_s *pqueue = get_queue(channel); + queue_t *q = &pqueue[queue_idx]; + int idx = 0; + unsigned int pool_idx, di_buf_idx; + struct di_buf_s *di_buf = NULL; + int start_pos_init = *start_pos; + struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel); + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s:<%d:%d,%d,%d> %d\n", __func__, queue_idx, + q->num, q->in_idx, q->out_idx, *start_pos); + + if (q->type == 0) { + if ((*start_pos) < q->num) { + idx = q->out_idx + (*start_pos); + if (idx >= MAX_QUEUE_POOL_SIZE) + idx -= MAX_QUEUE_POOL_SIZE; + + (*start_pos)++; + } else { + idx = MAX_QUEUE_POOL_SIZE; + } + } else if ((q->type == 1) || (q->type == 2)) { + for (idx = (*start_pos); idx < MAX_QUEUE_POOL_SIZE; idx++) { + if (q->pool[idx] != 0) { + *start_pos = idx + 1; + break; + } + } + } + if (idx < MAX_QUEUE_POOL_SIZE) { + pool_idx = ((q->pool[idx] >> 8) & 0xff) - 1; + di_buf_idx = q->pool[idx] & 0xff; + if (pool_idx < VFRAME_TYPE_NUM) { + if (di_buf_idx < pbuf_pool[pool_idx].size) + di_buf = + &(pbuf_pool[pool_idx].di_buf_ptr[ + di_buf_idx]); + } + } + + if ((di_buf) && ((((pool_idx + 1) << 8) | di_buf_idx) + != ((di_buf->type << 8) | (di_buf->index)))) { + PR_ERR("%s:(%x,%x)\n", __func__, + (((pool_idx + 1) << 8) | di_buf_idx), + ((di_buf->type << 8) | (di_buf->index))); + if (recovery_flag == 0) { + recovery_log_reason = 1; + recovery_log_queue_idx = + (start_pos_init << 8) | queue_idx; + recovery_log_di_buf = di_buf; + } + recovery_flag++; + di_buf = NULL; + } + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) { + if (di_buf) + dim_print("%s: 0x%p(%d,%d)\n", __func__, di_buf, + pool_idx, di_buf_idx); + else + dim_print("%s: 0x%p\n", __func__, di_buf); + } + + return di_buf; +} + +/*--------------------------*/ +u8 *dim_vmap(ulong addr, u32 size, bool *bflg) +{ + u8 *vaddr = NULL; + ulong phys = addr; + u32 offset = phys & ~PAGE_MASK; + u32 npages = PAGE_ALIGN(size) / PAGE_SIZE; + struct page **pages = NULL; + pgprot_t pgprot; + int i; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + + if (offset) + npages++; + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + + /*nocache*/ + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + PR_ERR("the phy(%lx) vmaped fail, size: %d\n", + addr - offset, npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + + vfree(pages); +#if 0 + if (debug_mode & 0x20) { + dim_print("[HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", + __func__, addr, vaddr + offset, + npages << PAGE_SHIFT); + } +#endif + *bflg = true; + + return vaddr + offset; +} + +void dim_unmap_phyaddr(u8 *vaddr) +{ + void *addr = (void *)(PAGE_MASK & (ulong)vaddr); + + vunmap(addr); +} + +/*--------------------------*/ +ssize_t +store_dump_mem(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + unsigned int n = 0, canvas_w = 0, canvas_h = 0; + unsigned long nr_size = 0, dump_adr = 0; + struct di_buf_s *di_buf = NULL; + struct vframe_s *post_vf = NULL; + char *buf_orig, *ps, *token; + char *parm[5] = { NULL }; + char delim1[3] = " "; + char delim2[2] = "\n"; + struct file *filp = NULL; + loff_t pos = 0; + void *buff = NULL; + mm_segment_t old_fs; + bool bflg_vmap = false; + unsigned int channel = get_current_channel();/* debug only*/ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + /*ary add 2019-07-2 being*/ + unsigned int indx; + struct di_buf_s *pbuf_post; + struct di_buf_s *pbuf_local; + struct di_post_stru_s *ppost; + struct di_mm_s *mm = dim_mm_get();/*mm-0705*/ + /*************************/ + + buf_orig = kstrdup(buf, GFP_KERNEL); + ps = buf_orig; + strcat(delim1, delim2); + while (1) { + token = strsep(&ps, delim1); + if (!token) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } + if (strcmp(parm[0], "capture") == 0) { + di_buf = ppre->di_mem_buf_dup_p; + } else if (strcmp(parm[0], "c_post") == 0) { + /*ary add 2019-07-2*/ + if (kstrtouint(parm[2], 0, &channel)) { + PR_ERR("c_post:ch is not number\n"); + kfree(buf_orig); + return 0; + } + if (kstrtouint(parm[3], 0, &indx)) { + PR_ERR("c_post:ch is not number\n"); + kfree(buf_orig); + return 0; + } + di_pr_info("c_post:ch[%d],index[%d]\n", channel, indx); + + ppre = get_pre_stru(channel); + ppost = get_post_stru(channel); + /*mm-0705 if (indx >= ppost->di_post_num) {*/ + if (indx >= mm->sts.num_post) { + PR_ERR("c_post:index is overflow:%d[%d]\n", indx, + mm->sts.num_post); + kfree(buf_orig); + return 0; + } + pbuf_post = get_buf_post(channel); + di_buf = &pbuf_post[indx]; + } else if (strcmp(parm[0], "c_local") == 0) { + /*ary add 2019-07-2*/ + if (kstrtouint(parm[2], 0, &channel)) { + PR_ERR("c_local:ch is not number\n"); + kfree(buf_orig); + return 0; + } + if (kstrtouint(parm[3], 0, &indx)) { + PR_ERR("c_local:ch is not number\n"); + kfree(buf_orig); + return 0; + } + di_pr_info("c_local:ch[%d],index[%d]\n", channel, indx); + + ppre = get_pre_stru(channel); + ppost = get_post_stru(channel); + #if 0 + if (indx >= ppost->di_post_num) { + PR_ERR("c_local:index is overflow:%d[%d]\n", + indx, ppost->di_post_num); + kfree(buf_orig); + return 0; + } + #endif + pbuf_local = get_buf_local(channel); + di_buf = &pbuf_local[indx]; + } else if (strcmp(parm[0], "capture_pready") == 0) { /*ary add*/ + + if (!di_que_is_empty(channel, QUE_POST_READY)) { + di_buf = di_que_peek(channel, QUE_POST_READY); + pr_info("get post ready di_buf:%d:0x%p\n", + di_buf->index, di_buf); + } else { + pr_info("war:no post ready buf\n"); + } + } else if (strcmp(parm[0], "capture_post") == 0) { + if (di_vf_l_peek(channel)) { + post_vf = di_vf_l_get(channel); + if (!IS_ERR_OR_NULL(post_vf)) { + di_buf = post_vf->private_data; + di_vf_l_put(post_vf, channel); + pr_info("get post di_buf:%d:0x%p\n", + di_buf->index, di_buf); + } else { + pr_info("war:peek no post buf, vfm[0x%p]\n", + post_vf); + } + + post_vf = NULL; + } else { + pr_info("war:can't peek post buf\n"); + } + } else if (strcmp(parm[0], "capture_nrds") == 0) { + dim_get_nr_ds_buf(&dump_adr, &nr_size); + } else { + PR_ERR("wrong dump cmd\n"); + kfree(buf_orig); + return len; + } + if (nr_size == 0) { + if (unlikely(!di_buf)) { + pr_info("war:di_buf is null\n"); + kfree(buf_orig); + return len; + } + canvas_w = di_buf->canvas_width[NR_CANVAS]; + canvas_h = di_buf->canvas_height; + nr_size = canvas_w * canvas_h * 2; + dump_adr = di_buf->nr_adr; + + pr_info("w=%d,h=%d,size=%ld,addr=%lu\n", + canvas_w, canvas_h, nr_size, dump_adr); + } + old_fs = get_fs(); + set_fs(KERNEL_DS); + /* pr_dbg("dump path =%s\n",dump_path); */ + filp = filp_open(parm[1], O_RDWR | O_CREAT, 0666); + if (IS_ERR(filp)) { + PR_ERR("create %s error.\n", parm[1]); + kfree(buf_orig); + return len; + } + dump_state_flag = 1; + if (de_devp->flags & DI_MAP_FLAG) { + /*buff = (void *)phys_to_virt(dump_adr);*/ + buff = dim_vmap(dump_adr, nr_size, &bflg_vmap); + if (!buff) { + if (nr_size <= 5222400) { + pr_info("di_vap err\n"); + filp_close(filp, NULL); + kfree(buf_orig); + return len; + } + /*try again:*/ + PR_INF("vap err,size to 5222400, try again\n"); + nr_size = 5222400; + buff = dim_vmap(dump_adr, nr_size, &bflg_vmap); + if (!buff) { + filp_close(filp, NULL); + kfree(buf_orig); + return len; + } + } + } else { + buff = ioremap(dump_adr, nr_size); + } + if (IS_ERR_OR_NULL(buff)) + PR_ERR("%s: ioremap error.\n", __func__); + vfs_write(filp, buff, nr_size, &pos); +/* pr_dbg("di_chan2_buf_dup_p:\n nr:%u,mtn:%u,cnt:%u\n", + * di_pre_stru.di_chan2_buf_dup_p->nr_adr, + * di_pre_stru.di_chan2_buf_dup_p->mtn_adr, + * di_pre_stru.di_chan2_buf_dup_p->cnt_adr); + * pr_dbg("di_inp_buf:\n nr:%u,mtn:%u,cnt:%u\n", + * di_pre_stru.di_inp_buf->nr_adr, + * di_pre_stru.di_inp_buf->mtn_adr, + * di_pre_stru.di_inp_buf->cnt_adr); + * pr_dbg("di_wr_buf:\n nr:%u,mtn:%u,cnt:%u\n", + * di_pre_stru.di_wr_buf->nr_adr, + * di_pre_stru.di_wr_buf->mtn_adr, + * di_pre_stru.di_wr_buf->cnt_adr); + * pr_dbg("di_mem_buf_dup_p:\n nr:%u,mtn:%u,cnt:%u\n", + * di_pre_stru.di_mem_buf_dup_p->nr_adr, + * di_pre_stru.di_mem_buf_dup_p->mtn_adr, + * di_pre_stru.di_mem_buf_dup_p->cnt_adr); + * pr_dbg("di_mem_start=%u\n",di_mem_start); + */ + vfs_fsync(filp, 0); + pr_info("write buffer 0x%lx to %s.\n", dump_adr, parm[1]); + if (bflg_vmap) + dim_unmap_phyaddr(buff); + + if (!(de_devp->flags & DI_MAP_FLAG)) + iounmap(buff); + dump_state_flag = 0; + filp_close(filp, NULL); + set_fs(old_fs); + kfree(buf_orig); + return len; +} + +static void recycle_vframe_type_pre(struct di_buf_s *di_buf, + unsigned int channel); +static void recycle_vframe_type_post(struct di_buf_s *di_buf, + unsigned int channel); +static void add_dummy_vframe_type_pre(struct di_buf_s *src_buf, + unsigned int channel); +#ifdef DI_BUFFER_DEBUG +static void +recycle_vframe_type_post_print(struct di_buf_s *di_buf, + const char *func, + const int line); +#endif + +static void dis2_di(void) +{ + ulong flags = 0, irq_flag2 = 0; + unsigned int channel = get_current_channel();/* debug only*/ + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + set_init_flag(channel, false);/*init_flag = 0;*/ + di_lock_irqfiq_save(irq_flag2); +/* vf_unreg_provider(&di_vf_prov); */ + pw_vf_light_unreg_provider(channel); + di_unlock_irqfiq_restore(irq_flag2); + set_reg_flag(channel, false); + spin_lock_irqsave(&plist_lock, flags); + di_lock_irqfiq_save(irq_flag2); + if (ppre->di_inp_buf) { + if (pvframe_in[ppre->di_inp_buf->index]) { + pw_vf_put(pvframe_in[ppre->di_inp_buf->index], + channel); + pvframe_in[ppre->di_inp_buf->index] = NULL; + pw_vf_notify_provider(channel, + VFRAME_EVENT_RECEIVER_PUT, NULL); + } + ppre->di_inp_buf->invert_top_bot_flag = 0; + + di_que_in(channel, QUE_IN_FREE, ppre->di_inp_buf); + ppre->di_inp_buf = NULL; + } + dim_uninit_buf(0, channel); + if (get_blackout_policy()) { + dim_DI_Wr(DI_CLKG_CTRL, 0x2); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + dimh_enable_di_post_mif(GATE_OFF); + dim_post_gate_control(false); + dim_top_gate_control(false, false); + } + } + + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) + dim_set_power_control(0); + + di_unlock_irqfiq_restore(irq_flag2); + spin_unlock_irqrestore(&plist_lock, flags); +} + +ssize_t +store_config(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc = 0; + char *parm[2] = { NULL }, *buf_orig; + unsigned int channel = get_current_channel();/* debug only*/ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + buf_orig = kstrdup(buf, GFP_KERNEL); + dim_parse_cmd_params(buf_orig, (char **)(&parm)); + + if (strncmp(buf, "disable", 7) == 0) { + dim_print("%s: disable\n", __func__); + + if (get_init_flag(channel)) {/*if (init_flag) {*/ + ppre->disable_req_flag = 1; + + while (ppre->disable_req_flag) + usleep_range(1000, 1001); + } + } else if (strncmp(buf, "dis2", 4) == 0) { + dis2_di(); + } else if (strcmp(parm[0], "hold_video") == 0) { + pr_info("%s(%s %s)\n", __func__, parm[0], parm[1]); + rc = kstrtouint(parm[1], 10, &hold_video); + } + kfree(buf_orig); + return count; +} + +static unsigned char is_progressive(vframe_t *vframe) +{ + unsigned char ret = 0; + + ret = ((vframe->type & VIDTYPE_TYPEMASK) == VIDTYPE_PROGRESSIVE); + return ret; +} + +static unsigned char is_source_change(vframe_t *vframe, unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + +#define VFRAME_FORMAT_MASK \ + (VIDTYPE_VIU_422 | VIDTYPE_VIU_SINGLE_PLANE | VIDTYPE_VIU_444 | \ + VIDTYPE_MVC) + if ((ppre->cur_width != vframe->width) || + (ppre->cur_height != vframe->height) || + (((ppre->cur_inp_type & VFRAME_FORMAT_MASK) != + (vframe->type & VFRAME_FORMAT_MASK)) && + (!is_handle_prog_frame_as_interlace(vframe))) || + (ppre->cur_source_type != vframe->source_type)) { + /* video format changed */ + return 1; + } else if (((ppre->cur_prog_flag != is_progressive(vframe)) && + (!is_handle_prog_frame_as_interlace(vframe))) || + ((ppre->cur_inp_type & VIDTYPE_VIU_FIELD) != + (vframe->type & VIDTYPE_VIU_FIELD)) + ) { + /* just scan mode changed */ + if (!ppre->force_interlace) + pr_dbg("DI I<->P.\n"); + return 2; + } + return 0; +} + +/* + * static unsigned char is_vframe_type_change(vframe_t* vframe) + * { + * if( + * (di_pre_stru.cur_prog_flag!=is_progressive(vframe))|| + * ((di_pre_stru.cur_inp_type&VFRAME_FORMAT_MASK)!= + * (vframe->type&VFRAME_FORMAT_MASK)) + * ) + * return 1; + * + * return 0; + * } + */ +static int trick_mode; + +unsigned char dim_is_bypass(vframe_t *vf_in, unsigned int channel) +{ + unsigned int vtype = 0; + int ret = 0; + static vframe_t vf_tmp; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (dimp_get(eDI_MP_di_debug_flag) & 0x10000) /* for debugging */ + return (dimp_get(eDI_MP_di_debug_flag) >> 17) & 0x1; + + if (di_cfgx_get(channel, eDI_CFGX_BYPASS_ALL)) + return 1; + if (ppre->cur_prog_flag && + ((ppre->cur_width > 1920) || + (ppre->cur_height > 1080) || + (ppre->cur_inp_type & VIDTYPE_VIU_444)) + ) + return 1; + + if ((ppre->cur_width < 16) || (ppre->cur_height < 16)) + return 1; + + if (ppre->cur_inp_type & VIDTYPE_MVC) + return 1; + + if (ppre->cur_source_type == VFRAME_SOURCE_TYPE_PPMGR) + return 1; + + if (dimp_get(eDI_MP_bypass_trick_mode)) { + int trick_mode_fffb = 0; + int trick_mode_i = 0; + + if (dimp_get(eDI_MP_bypass_trick_mode) & 0x1) + query_video_status(0, &trick_mode_fffb); + if (dimp_get(eDI_MP_bypass_trick_mode) & 0x2) + query_video_status(1, &trick_mode_i); + trick_mode = trick_mode_fffb | (trick_mode_i << 1); + if (trick_mode) + return 1; + } + + if (dimp_get(eDI_MP_bypass_3d) && + (ppre->source_trans_fmt != 0)) + return 1; + +/*prot is conflict with di post*/ + if (vf_in && vf_in->video_angle) + return 1; + if (vf_in && (vf_in->type & VIDTYPE_PIC)) + return 1; +#if 0 + if (vf_in && (vf_in->type & VIDTYPE_COMPRESS)) + return 1; +#endif + if ((dimp_get(eDI_MP_di_vscale_skip_enable) & 0x4) && + vf_in && !dimp_get(eDI_MP_post_wr_en)) { + /*--------------------------*/ + if (vf_in->type & VIDTYPE_COMPRESS) { + vf_tmp.width = vf_in->compWidth; + vf_tmp.height = vf_in->compHeight; + if (vf_tmp.width > 1920 || vf_tmp.height > 1088) + return 1; + } + /*--------------------------*/ + /*backup vtype,set type as progressive*/ + vtype = vf_in->type; + vf_in->type &= (~VIDTYPE_TYPEMASK); + vf_in->type &= (~VIDTYPE_VIU_NV21); + vf_in->type |= VIDTYPE_VIU_SINGLE_PLANE; + vf_in->type |= VIDTYPE_VIU_FIELD; + vf_in->type |= VIDTYPE_PRE_INTERLACE; + vf_in->type |= VIDTYPE_VIU_422; + ret = ext_ops.get_current_vscale_skip_count(vf_in); + /*di_vscale_skip_count = (ret&0xff);*/ + dimp_set(eDI_MP_di_vscale_skip_count, ret & 0xff); + /*vpp_3d_mode = ((ret>>8)&0xff);*/ + dimp_set(eDI_MP_vpp_3d_mode, ((ret >> 8) & 0xff)); + vf_in->type = vtype; + if (dimp_get(eDI_MP_di_vscale_skip_count) > 0 || + (dimp_get(eDI_MP_vpp_3d_mode) + #ifdef DET3D + && (!dimp_get(eDI_MP_det3d_en)) + #endif + ) + ) + return 1; + } + + return 0; +} + +static bool need_bypass(struct vframe_s *vf); + +/********************************** + *diff with dim_is_bypass + * delet di_vscale_skip_enable + * use vf_in replace ppre + **********************************/ +bool is_bypass2(struct vframe_s *vf_in, unsigned int ch) +{ + /*check debug info*/ + if (dimp_get(eDI_MP_di_debug_flag) & 0x10000) /* for debugging */ + return true; + + if (di_cfgx_get(ch, eDI_CFGX_BYPASS_ALL)) /*bypass_all*/ + return true; + + if (dimp_get(eDI_MP_bypass_trick_mode)) { + int trick_mode_fffb = 0; + int trick_mode_i = 0; + + if (dimp_get(eDI_MP_bypass_trick_mode) & 0x1) + query_video_status(0, &trick_mode_fffb); + if (dimp_get(eDI_MP_bypass_trick_mode) & 0x2) + query_video_status(1, &trick_mode_i); + trick_mode = trick_mode_fffb | (trick_mode_i << 1); + if (trick_mode) + return true; + } + /* check vframe */ + if (!vf_in) + return false; + + if (need_bypass(vf_in)) + return true; + + if ((vf_in->width < 16) || (vf_in->height < 16)) + return true; + + if (dimp_get(eDI_MP_bypass_3d) && + (vf_in->trans_fmt != 0)) + return true; + +/*prot is conflict with di post*/ + if (vf_in->video_angle) + return true; + + return false; +} + +static unsigned char is_bypass_post(unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (dimp_get(eDI_MP_di_debug_flag) & 0x40000) /* for debugging */ + return (dimp_get(eDI_MP_di_debug_flag) >> 19) & 0x1; + + /*prot is conflict with di post*/ + if (ppre->orientation) + return 1; + if (dimp_get(eDI_MP_bypass_post)) + return 1; + +#ifdef DET3D + if (ppre->vframe_interleave_flag != 0) + return 1; + +#endif + return 0; +} + +#ifdef RUN_DI_PROCESS_IN_IRQ +static unsigned char is_input2pre(void, unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (input2pre && + ppre->cur_prog_flag && + ppre->vdin_source && + (di_bypass_state_get(channel) == 0)) + return 1; + + return 0; +} +#endif + +#ifdef DI_USE_FIXED_CANVAS_IDX +static int di_post_idx[2][6]; +static int di_pre_idx[2][10]; +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC +static unsigned int di_inp_idx[3]; +#else +static int di_wr_idx; +#endif + +int dim_get_canvas(void) +{ + unsigned int pre_num = 7, post_num = 6; + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (dimp_get(eDI_MP_mcpre_en)) { + /* mem/chan2/nr/mtn/contrd/contrd2/ + * contw/mcinfrd/mcinfow/mcvecw + */ + pre_num = 10; + /* buf0/buf1/buf2/mtnp/mcvec */ + post_num = 6; + } + if (ext_ops.canvas_pool_alloc_canvas_table("di_pre", + &di_pre_idx[0][0], + pre_num, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocate di pre canvas error.\n", __func__); + return 1; + } + if (di_pre_rdma_enable) { + if (ext_ops.canvas_pool_alloc_canvas_table("di_pre", + &di_pre_idx[1][0], + pre_num, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocate di pre canvas error.\n", __func__); + return 1; + } + } else { + #if 0 + for (i = 0; i < pre_num; i++) + di_pre_idx[1][i] = di_pre_idx[0][i]; + #else + memcpy(&di_pre_idx[1][0], + &di_pre_idx[0][0], sizeof(int) * pre_num); + #endif + } + if (ext_ops.canvas_pool_alloc_canvas_table("di_post", + &di_post_idx[0][0], + post_num, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocate di post canvas error.\n", __func__); + return 1; + } + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (ext_ops.canvas_pool_alloc_canvas_table("di_post", + &di_post_idx[1][0], + post_num, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocate di post canvas error.\n", __func__); + return 1; + } +#else + for (i = 0; i < post_num; i++) + di_post_idx[1][i] = di_post_idx[0][i]; +#endif +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (ext_ops.canvas_pool_alloc_canvas_table("di_inp", &di_inp_idx[0], 3, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocat di inp canvas error.\n", __func__); + return 1; + } + pr_info("DI: support multi decoding %u~%u~%u.\n", + di_inp_idx[0], di_inp_idx[1], di_inp_idx[2]); +#endif + if (de_devp->post_wr_support == 0) + return 0; + +#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + if (ext_ops.canvas_pool_alloc_canvas_table("di_wr", + &di_wr_idx, 1, + CANVAS_MAP_TYPE_1)) { + PR_ERR("%s allocat di write back canvas error.\n", + __func__); + return 1; + } + pr_info("DI: support post write back %u.\n", di_wr_idx); +#endif + return 0; +} + +static void config_canvas_idx(struct di_buf_s *di_buf, int nr_canvas_idx, + int mtn_canvas_idx) +{ + unsigned int height = 0; + + if (!di_buf) + return; + if (di_buf->canvas_config_flag == 1) { + if (nr_canvas_idx >= 0) { + /* linked two interlace buffer should double height*/ + if (di_buf->di_wr_linked_buf) + height = (di_buf->canvas_height << 1); + else + height = di_buf->canvas_height; + di_buf->nr_canvas_idx = nr_canvas_idx; + canvas_config(nr_canvas_idx, di_buf->nr_adr, + di_buf->canvas_width[NR_CANVAS], + height, 0, 0); + } + } else if (di_buf->canvas_config_flag == 2) { + if (nr_canvas_idx >= 0) { + di_buf->nr_canvas_idx = nr_canvas_idx; + canvas_config(nr_canvas_idx, di_buf->nr_adr, + di_buf->canvas_width[NR_CANVAS], + di_buf->canvas_height, 0, 0); + } + if (mtn_canvas_idx >= 0) { + di_buf->mtn_canvas_idx = mtn_canvas_idx; + canvas_config(mtn_canvas_idx, di_buf->mtn_adr, + di_buf->canvas_width[MTN_CANVAS], + di_buf->canvas_height, 0, 0); + } + } + if (nr_canvas_idx >= 0) { + di_buf->vframe->canvas0Addr = di_buf->nr_canvas_idx; + di_buf->vframe->canvas1Addr = di_buf->nr_canvas_idx; + } +} + +static void config_cnt_canvas_idx(struct di_buf_s *di_buf, + unsigned int cnt_canvas_idx) +{ + if (!di_buf) + return; + + di_buf->cnt_canvas_idx = cnt_canvas_idx; + canvas_config(cnt_canvas_idx, di_buf->cnt_adr, + di_buf->canvas_width[MTN_CANVAS], + di_buf->canvas_height, 0, 0); +} + +static void config_mcinfo_canvas_idx(struct di_buf_s *di_buf, + int mcinfo_canvas_idx) +{ + if (!di_buf) + return; + + di_buf->mcinfo_canvas_idx = mcinfo_canvas_idx; + canvas_config(mcinfo_canvas_idx, + di_buf->mcinfo_adr, + di_buf->canvas_height_mc, 2, 0, 0); +} + +static void config_mcvec_canvas_idx(struct di_buf_s *di_buf, + int mcvec_canvas_idx) +{ + if (!di_buf) + return; + + di_buf->mcvec_canvas_idx = mcvec_canvas_idx; + canvas_config(mcvec_canvas_idx, + di_buf->mcvec_adr, + di_buf->canvas_width[MV_CANVAS], + di_buf->canvas_height, 0, 0); +} + +#else + +static void config_canvas(struct di_buf_s *di_buf) +{ + unsigned int height = 0; + + if (!di_buf) + return; + + if (di_buf->canvas_config_flag == 1) { + /* linked two interlace buffer should double height*/ + if (di_buf->di_wr_linked_buf) + height = (di_buf->canvas_height << 1); + else + height = di_buf->canvas_height; + canvas_config(di_buf->nr_canvas_idx, di_buf->nr_adr, + di_buf->canvas_width[NR_CANVAS], height, 0, 0); + di_buf->canvas_config_flag = 0; + } else if (di_buf->canvas_config_flag == 2) { + canvas_config(di_buf->nr_canvas_idx, di_buf->nr_adr, + di_buf->canvas_width[MV_CANVAS], + di_buf->canvas_height, 0, 0); + canvas_config(di_buf->mtn_canvas_idx, di_buf->mtn_adr, + di_buf->canvas_width[MTN_CANVAS], + di_buf->canvas_height, 0, 0); + di_buf->canvas_config_flag = 0; + } +} + +#endif + +#ifdef CONFIG_CMA +/********************************************************** + * ./include/linux/amlogic/media/codec_mm/codec_mm.h: + * unsigned long codec_mm_alloc_for_dma(const char *owner, + * int page_cnt, + * int align2n, + * int memflags); + * int codec_mm_free_for_dma(const char *owner, + * unsigned long phy_addr); + * void *codec_mm_phys_to_virt(unsigned long phy_addr); + ***********************************************************/ + +#define TVP_MEM_PAGES 0xffff +/********************************************************** + * alloc mm from codec mm + * o: out: + * return: + * true: seccuss + * false: failed + ***********************************************************/ +static bool mm_codec_alloc(const char *owner, size_t count, + int cma_mode, + struct dim_mm_s *o) +{ + int flags = 0; + bool istvp = false; + + if (codec_mm_video_tvp_enabled()) { + istvp = true; + flags |= CODEC_MM_FLAGS_TVP; + } else { + flags |= CODEC_MM_FLAGS_RESERVED | CODEC_MM_FLAGS_CPU; + } + + if (cma_mode == 4 && !istvp) + flags = CODEC_MM_FLAGS_CMA_FIRST | + CODEC_MM_FLAGS_CPU; + + o->addr = codec_mm_alloc_for_dma(owner, + count, + 0, + flags); + + if (o->addr == 0) { + /*failed*/ + PR_ERR("%s: failed\n", __func__); + return false; + } + + if (istvp) + o->ppage = (struct page *)TVP_MEM_PAGES; + else + o->ppage = codec_mm_phys_to_virt(o->addr); + + /*PR_INF("%s:page:0x%p,add:0x%lx\n", __func__, o->ppage, o->addr);*/ + return true; +} + +/********************************************************** + * ./include/linux/dma-contiguous.h: + * struct page *dma_alloc_from_contiguous(struct device *dev, + * size_t count, + * unsigned int order); + * bool dma_release_from_contiguous(struct device *dev, + * struct page *pages, + * int count); + * + ***********************************************************/ + +/********************************************************** + * alloc mm by cma + * o: out: + * return: + * true: seccuss + * false: failed + ***********************************************************/ +static bool mm_cma_alloc(struct device *dev, size_t count, + struct dim_mm_s *o) +{ + o->ppage = dma_alloc_from_contiguous(dev, count, 0); + if (o->ppage) { + o->addr = page_to_phys(o->ppage); + return true; + } + PR_ERR("%s: failed\n", __func__); + return false; +} + +bool dim_mm_alloc(int cma_mode, size_t count, struct dim_mm_s *o) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + bool ret; + + if (cma_mode == 3 || cma_mode == 4) + ret = mm_codec_alloc(DEVICE_NAME, + count, + cma_mode, + o); + else + ret = mm_cma_alloc(&de_devp->pdev->dev, count, o); + + return ret; +} + +bool dim_mm_release(int cma_mode, + struct page *pages, + int count, + unsigned long addr) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + bool ret = true; + + if (cma_mode == 3 || cma_mode == 4) + codec_mm_free_for_dma(DEVICE_NAME, addr); + else + ret = dma_release_from_contiguous(&de_devp->pdev->dev, + pages, + count); + return ret; +} + +/***********************************************************/ +unsigned int dim_cma_alloc_total(struct di_dev_s *de_devp) +{ + /*struct di_dev_s *de_devp = get_dim_de_devp();*/ + /*****************************************************/ + struct dim_mm_s omm; + bool ret; + + ret = dim_mm_alloc(de_devp->flag_cma, + de_devp->mem_size >> PAGE_SHIFT, &omm); + + if (!ret) /*failed*/ + return 0; + + de_devp->total_pages = omm.ppage; + de_devp->mem_start = omm.addr; + + if (de_devp->flag_cma != 0 && de_devp->nrds_enable) { + dim_nr_ds_buf_init(de_devp->flag_cma, 0, + &de_devp->pdev->dev); + } + + return 1; +} + +static unsigned int di_cma_alloc(struct di_dev_s *devp, unsigned int channel) +{ + unsigned int start_time, end_time, delta_time; + struct di_buf_s *buf_p = NULL; + int itmp, alloc_cnt = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + unsigned int tmpa[MAX_FIFO_SIZE]; /*new que*/ + unsigned int psize; /*new que*/ + struct di_mm_s *mm = dim_mm_get();/*mm-0705*/ + + bool aret; + struct dim_mm_s omm; + + start_time = jiffies_to_msecs(jiffies); + queue_for_each_entry(buf_p, channel, QUEUE_LOCAL_FREE, list) { + if (buf_p->pages) { + PR_ERR("1:%s:buf[%d] page:0x%p alloced skip\n", + __func__, buf_p->index, buf_p->pages); + continue; + } + + aret = dim_mm_alloc(devp->flag_cma, + devp->buffer_size >> PAGE_SHIFT, + &omm); + + if (!aret) { + buf_p->pages = NULL; + PR_ERR("2:%s: alloc failed %d fail.\n", + __func__, buf_p->index); + return 0; + } + + buf_p->pages = omm.ppage; + buf_p->nr_adr = omm.addr; + alloc_cnt++; + mm->sts.num_local++; + if (dimp_get(eDI_MP_cma_print)) + PR_INF("CMA allocate buf[%d]page:0x%p\n", + buf_p->index, buf_p->pages); + + if (dimp_get(eDI_MP_cma_print)) + pr_info(" addr 0x%lx ok.\n", buf_p->nr_adr); + if (ppre->buf_alloc_mode == 0) { + buf_p->mtn_adr = buf_p->nr_adr + + ppre->nr_size; + buf_p->cnt_adr = buf_p->nr_adr + + ppre->nr_size + + ppre->mtn_size; + if (mc_mem_alloc) { + buf_p->mcvec_adr = buf_p->nr_adr + + ppre->nr_size + + ppre->mtn_size + + ppre->count_size; + buf_p->mcinfo_adr = + buf_p->nr_adr + + ppre->nr_size + + ppre->mtn_size + + ppre->count_size + + ppre->mv_size; + } + } + } + PR_INF("%s:num_local[%d]\n", __func__, mm->sts.num_local); + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) { + di_que_list(channel, QUE_POST_FREE, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + buf_p = pw_qindex_2_buf(channel, tmpa[itmp]); + + if (buf_p->pages) { + PR_ERR("3:%s:buf[%d] page:0x%p skip\n", + __func__, + buf_p->index, buf_p->pages); + continue; + } + + aret = dim_mm_alloc(devp->flag_cma, + devp->post_buffer_size >> PAGE_SHIFT, + &omm); + + if (!aret) { + buf_p->pages = NULL; + PR_ERR("4:%s: alloc failed %d fail.\n", + __func__, buf_p->index); + return 0; + } + + buf_p->pages = omm.ppage; + buf_p->nr_adr = omm.addr; + mm->sts.num_post++; + alloc_cnt++; + if (dimp_get(eDI_MP_cma_print)) + PR_INF("%s:pbuf[%d]page:0x%p\n", + __func__, + buf_p->index, buf_p->pages); + if (dimp_get(eDI_MP_cma_print)) + pr_info(" addr 0x%lx ok.\n", buf_p->nr_adr); + } + PR_INF("%s:num_pst[%d]\n", __func__, mm->sts.num_post); + } + if (de_devp->flag_cma != 0 && de_devp->nrds_enable) { + dim_nr_ds_buf_init(de_devp->flag_cma, 0, + &de_devp->pdev->dev); + } + + end_time = jiffies_to_msecs(jiffies); + delta_time = end_time - start_time; + pr_info("%s:alloc %u buffer use %u ms(%u~%u)\n", + __func__, alloc_cnt, delta_time, start_time, end_time); + return 1; +} + +static void di_cma_release(struct di_dev_s *devp, unsigned int channel) +{ + unsigned int i, ii, rels_cnt = 0, start_time, end_time, delta_time; + struct di_buf_s *buf_p; + struct di_buf_s *pbuf_local = get_buf_local(channel); + struct di_buf_s *pbuf_post = get_buf_post(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + bool ret; + struct di_mm_s *mm = dim_mm_get(); + + start_time = jiffies_to_msecs(jiffies); + for (i = 0; (i < mm->cfg.num_local); i++) { + buf_p = &pbuf_local[i]; + ii = USED_LOCAL_BUF_MAX; + + if ((ii >= USED_LOCAL_BUF_MAX) && + buf_p->pages) { + ret = dim_mm_release(devp->flag_cma, buf_p->pages, + devp->buffer_size >> PAGE_SHIFT, + buf_p->nr_adr); + if (ret) { + buf_p->pages = NULL; + mm->sts.num_local--; + rels_cnt++; + if (dimp_get(eDI_MP_cma_print)) + pr_info( + "DI release buf[%d] ok.\n", i); + } else { + PR_ERR("%s:release buf[%d] fail.\n", + __func__, i); + } + } else { + if (!IS_ERR_OR_NULL(buf_p->pages) && + dimp_get(eDI_MP_cma_print)) { + pr_info("DI buf[%d] page:0x%p no release.\n", + buf_p->index, buf_p->pages); + } + } + } + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) { + /*mm-0705 for (i = 0; i < ppost->di_post_num; i++) {*/ + for (i = 0; i < mm->cfg.num_post; i++) { + buf_p = &pbuf_post[i]; + if (ppost->keep_buf_post && + i == ppost->keep_buf_post->index) + continue; + + if (!buf_p->pages) { + PR_ERR("2:%s:post buf[%d] is null\n", + __func__, i); + continue; + } + + ret = dim_mm_release(devp->flag_cma, + buf_p->pages, + devp->post_buffer_size >> PAGE_SHIFT, + buf_p->nr_adr); + if (ret) { + buf_p->pages = NULL; + mm->sts.num_post--; + rels_cnt++; + if (dimp_get(eDI_MP_cma_print)) + pr_info( + "DI release post buf[%d] ok.\n", i); + } else { + PR_ERR("%s:release post buf[%d] fail\n", + __func__, i); + } + } + } + if (de_devp->nrds_enable) { + dim_nr_ds_buf_uninit(de_devp->flag_cma, + &de_devp->pdev->dev); + } + if (mm->sts.num_local < 0 || mm->sts.num_post < 0) + PR_ERR("%s:mm:nub_local=%d,nub_post=%d\n", + __func__, + mm->sts.num_local, + mm->sts.num_post); + end_time = jiffies_to_msecs(jiffies); + delta_time = end_time - start_time; + pr_info("%s:release %u buffer use %u ms(%u~%u)\n", + __func__, rels_cnt, delta_time, start_time, end_time); +} +#endif + +bool dim_cma_top_alloc(unsigned int ch) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + bool ret = false; + +#ifdef CONFIG_CMA + + if (di_cma_alloc(de_devp, ch)) + ret = true; +#endif + return ret; +} + +bool dim_cma_top_release(unsigned int ch) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + +#ifdef CONFIG_CMA + di_cma_release(de_devp, ch); + +#endif + return true; +} + +/******************************************* + * + * + ******************************************/ +#define DI_KEEP_BUF_SIZE 3 +static struct di_buf_s *di_keep_buf[DI_KEEP_BUF_SIZE]; +static int di_keep_point; + +void keep_buf_clear(void) +{ + int i; + + for (i = 0; i < DI_KEEP_BUF_SIZE; i++) + di_keep_buf[i] = NULL; + + di_keep_point = -1; +} + +void keep_buf_in(struct di_buf_s *ready_buf) +{ + di_keep_point++; + if (di_keep_point >= DI_KEEP_BUF_SIZE) + di_keep_point = 0; + di_keep_buf[di_keep_point] = ready_buf; +} + +void keep_buf_in_full(struct di_buf_s *ready_buf) +{ + int i; + + keep_buf_in(ready_buf); + for (i = 0; i < DI_KEEP_BUF_SIZE; i++) { + if (!di_keep_buf[i]) + di_keep_buf[i] = ready_buf; + } +} + +int di_cnt_buf(int width, int height, int prog_flag, int mc_mm, + int bit10_support, int pack422) +{ + int canvas_height = height + 8; + unsigned int di_buf_size = 0, di_post_buf_size = 0, mtn_size = 0; + unsigned int nr_size = 0, count_size = 0, mv_size = 0, mc_size = 0; + unsigned int nr_width = width, mtn_width = width, mv_width = width; + unsigned int nr_canvas_width = width, mtn_canvas_width = width; + unsigned int mv_canvas_width = width, canvas_align_width = 32; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + canvas_align_width = 64; + + if (dimp_get(eDI_MP_nr10bit_support)) { + if (dimp_get(eDI_MP_full_422_pack)) + nr_width = (width * 5) / 4; + else + nr_width = (width * 3) / 2; + } else { + nr_width = width; + } + /* make sure canvas width must be divided by 256bit|32byte align */ + nr_canvas_width = nr_width << 1; + mtn_canvas_width = mtn_width >> 1; + mv_canvas_width = (mv_width << 1) / 5; + nr_canvas_width = roundup(nr_canvas_width, canvas_align_width); + mtn_canvas_width = roundup(mtn_canvas_width, canvas_align_width); + mv_canvas_width = roundup(mv_canvas_width, canvas_align_width); + nr_width = nr_canvas_width >> 1; + mtn_width = mtn_canvas_width << 1; + mv_width = (mv_canvas_width * 5) >> 1; + + if (prog_flag) { + di_buf_size = nr_width * canvas_height * 2; + di_buf_size = roundup(di_buf_size, PAGE_SIZE); + + } else { + /*pr_info("canvas_height=%d\n", canvas_height);*/ + + /*nr_size(bits)=w*active_h*8*2(yuv422) + * mtn(bits)=w*active_h*4 + * cont(bits)=w*active_h*4 mv(bits)=w*active_h/5*16 + * mcinfo(bits)=active_h*16 + */ + nr_size = (nr_width * canvas_height) * 8 * 2 / 16; + mtn_size = (mtn_width * canvas_height) * 4 / 16; + count_size = (mtn_width * canvas_height) * 4 / 16; + mv_size = (mv_width * canvas_height) / 5; + /*mc_size = canvas_height;*/ + mc_size = roundup(canvas_height >> 1, canvas_align_width) << 1; + if (mc_mm) { + di_buf_size = nr_size + mtn_size + count_size + + mv_size + mc_size; + } else { + di_buf_size = nr_size + mtn_size + count_size; + } + di_buf_size = roundup(di_buf_size, PAGE_SIZE); + } + + PR_INF("size:0x%x\n", di_buf_size); + PR_INF("\t%-15s:0x%x\n", "nr_size", nr_size); + PR_INF("\t%-15s:0x%x\n", "count", count_size); + PR_INF("\t%-15s:0x%x\n", "mtn", mtn_size); + PR_INF("\t%-15s:0x%x\n", "mv", mv_size); + PR_INF("\t%-15s:0x%x\n", "mcinfo", mc_size); + + di_post_buf_size = nr_width * canvas_height * 2; + /*PR_INF("size:post:0x%x\n", di_post_buf_size);*/ + di_post_buf_size = roundup(di_post_buf_size, PAGE_SIZE); + PR_INF("size:post:0x%x\n", di_post_buf_size); + + return 0; +} + +static int di_init_buf(int width, int height, unsigned char prog_flag, + unsigned int channel) +{ + int i; + int canvas_height = height + 8; + struct page *tmp_page = NULL; + unsigned int di_buf_size = 0, di_post_buf_size = 0, mtn_size = 0; + unsigned int nr_size = 0, count_size = 0, mv_size = 0, mc_size = 0; + unsigned int nr_width = width, mtn_width = width, mv_width = width; + unsigned int nr_canvas_width = width, mtn_canvas_width = width; + unsigned int mv_canvas_width = width, canvas_align_width = 32; + unsigned long di_post_mem = 0, nrds_mem = 0; + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct vframe_s *pvframe_in_dup = get_vframe_in_dup(channel); + struct vframe_s *pvframe_local = get_vframe_local(channel); + struct vframe_s *pvframe_post = get_vframe_post(channel); + struct di_buf_s *pbuf_local = get_buf_local(channel); + struct di_buf_s *pbuf_in = get_buf_in(channel); + struct di_buf_s *pbuf_post = get_buf_post(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_buf_s *keep_buf = ppost->keep_buf; + struct di_dev_s *de_devp = get_dim_de_devp(); + struct di_buf_s *keep_buf_post = ppost->keep_buf_post; + struct di_mm_s *mm = dim_mm_get(); /*mm-0705*/ + + unsigned int mem_st_local; + + /**********************************************/ + /* count buf info */ + /**********************************************/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + canvas_align_width = 64; + + pr_info("%s:begin\n", __func__); + frame_count = 0; + disp_frame_count = 0; + cur_post_ready_di_buf = NULL; + /* decoder'buffer had been releae no need put */ + for (i = 0; i < MAX_IN_BUF_NUM; i++) + pvframe_in[i] = NULL; + /*pre init*/ + memset(ppre, 0, sizeof(struct di_pre_stru_s)); + + if (dimp_get(eDI_MP_nr10bit_support)) { + if (dimp_get(eDI_MP_full_422_pack)) + nr_width = (width * 5) / 4; + else + nr_width = (width * 3) / 2; + } else { + nr_width = width; + } + /* make sure canvas width must be divided by 256bit|32byte align */ + nr_canvas_width = nr_width << 1; + mtn_canvas_width = mtn_width >> 1; + mv_canvas_width = (mv_width << 1) / 5; + nr_canvas_width = roundup(nr_canvas_width, canvas_align_width); + mtn_canvas_width = roundup(mtn_canvas_width, canvas_align_width); + mv_canvas_width = roundup(mv_canvas_width, canvas_align_width); + nr_width = nr_canvas_width >> 1; + mtn_width = mtn_canvas_width << 1; + mv_width = (mv_canvas_width * 5) >> 1; + + if (prog_flag) { + ppre->prog_proc_type = 1; + ppre->buf_alloc_mode = 1; + di_buf_size = nr_width * canvas_height * 2; + di_buf_size = roundup(di_buf_size, PAGE_SIZE); + } else { + /*pr_info("canvas_height=%d\n", canvas_height);*/ + ppre->prog_proc_type = 0; + ppre->buf_alloc_mode = 0; + /*nr_size(bits) = w * active_h * 8 * 2(yuv422) + * mtn(bits) = w * active_h * 4 + * cont(bits) = w * active_h * 4 mv(bits) = w * active_h / 5*16 + * mcinfo(bits) = active_h * 16 + */ + nr_size = (nr_width * canvas_height) * 8 * 2 / 16; + mtn_size = (mtn_width * canvas_height) * 4 / 16; + count_size = (mtn_width * canvas_height) * 4 / 16; + mv_size = (mv_width * canvas_height) / 5; + /*mc_size = canvas_height;*/ + mc_size = roundup(canvas_height >> 1, canvas_align_width) << 1; + if (mc_mem_alloc) { + di_buf_size = nr_size + mtn_size + count_size + + mv_size + mc_size; + } else { + di_buf_size = nr_size + mtn_size + count_size; + } + di_buf_size = roundup(di_buf_size, PAGE_SIZE); + } + de_devp->buffer_size = di_buf_size; + ppre->nr_size = nr_size; + ppre->count_size = count_size; + ppre->mtn_size = mtn_size; + ppre->mv_size = mv_size; + ppre->mcinfo_size = mc_size; + dimp_set(eDI_MP_same_field_top_count, 0); + same_field_bot_count = 0; + dbg_init("size:\n"); + dbg_init("\t%-15s:0x%x\n", "nr_size", ppre->nr_size); + dbg_init("\t%-15s:0x%x\n", "count", ppre->count_size); + dbg_init("\t%-15s:0x%x\n", "mtn", ppre->mtn_size); + dbg_init("\t%-15s:0x%x\n", "mv", ppre->mv_size); + dbg_init("\t%-15s:0x%x\n", "mcinfo", ppre->mcinfo_size); + + /**********************************************/ + /* que init */ + /**********************************************/ + + queue_init(channel, mm->cfg.num_local); + di_que_init(channel); /*new que*/ + + mem_st_local = di_get_mem_start(channel); + + /**********************************************/ + /* local buf init */ + /**********************************************/ + + for (i = 0; i < mm->cfg.num_local; i++) { + struct di_buf_s *di_buf = &pbuf_local[i]; + int ii = USED_LOCAL_BUF_MAX; + + if (!IS_ERR_OR_NULL(keep_buf)) { + for (ii = 0; ii < USED_LOCAL_BUF_MAX; ii++) { + if (di_buf == keep_buf->di_buf_dup_p[ii]) { + dim_print("%s skip %d\n", __func__, i); + break; + } + } + } + + if (ii >= USED_LOCAL_BUF_MAX) { + /* backup cma pages */ + tmp_page = di_buf->pages; + memset(di_buf, 0, sizeof(struct di_buf_s)); + di_buf->pages = tmp_page; + di_buf->type = VFRAME_TYPE_LOCAL; + di_buf->pre_ref_count = 0; + di_buf->post_ref_count = 0; + di_buf->canvas_width[NR_CANVAS] = nr_canvas_width; + di_buf->canvas_width[MTN_CANVAS] = mtn_canvas_width; + di_buf->canvas_width[MV_CANVAS] = mv_canvas_width; + if (prog_flag) { + di_buf->canvas_height = canvas_height; + di_buf->canvas_height_mc = canvas_height; + di_buf->nr_adr = mem_st_local + + di_buf_size * i; + di_buf->canvas_config_flag = 1; + } else { + di_buf->canvas_height = (canvas_height >> 1); + di_buf->canvas_height_mc = + roundup(di_buf->canvas_height, + canvas_align_width); + di_buf->nr_adr = mem_st_local + + di_buf_size * i; + di_buf->mtn_adr = mem_st_local + + di_buf_size * i + + nr_size; + di_buf->cnt_adr = mem_st_local + + di_buf_size * i + + nr_size + mtn_size; + + if (mc_mem_alloc) { + di_buf->mcvec_adr = mem_st_local + + di_buf_size * i + + nr_size + mtn_size + + count_size; + di_buf->mcinfo_adr = + mem_st_local + + di_buf_size * i + nr_size + + mtn_size + count_size + + mv_size; + } + di_buf->canvas_config_flag = 2; + } + di_buf->index = i; + di_buf->vframe = &pvframe_local[i]; + di_buf->vframe->private_data = di_buf; + di_buf->vframe->canvas0Addr = di_buf->nr_canvas_idx; + di_buf->vframe->canvas1Addr = di_buf->nr_canvas_idx; + di_buf->queue_index = -1; + di_buf->invert_top_bot_flag = 0; + di_buf->channel = channel; + queue_in(channel, di_buf, QUEUE_LOCAL_FREE); + dbg_init("buf[%d], addr=0x%lx\n", di_buf->index, + di_buf->nr_adr); + } + } + + if (de_devp->flag_cma == 1 || + de_devp->flag_cma == 4 || + de_devp->flag_cma == 3) { /*trig cma alloc*/ + dip_wq_cma_run(channel, true); + } + + dbg_init("one local buf size:0x%x\n", di_buf_size); + /*mm-0705 di_post_mem = mem_st_local +*/ + /*mm-0705 di_buf_size*de_devp->buf_num_avail;*/ + di_post_mem = mem_st_local + di_buf_size * mm->cfg.num_local; + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) { + di_post_buf_size = nr_width * canvas_height * 2; + #if 0 /*ary test for vout 25Hz*/ + /* pre buffer must 2 more than post buffer */ + if ((de_devp->buf_num_avail - 2) > MAX_POST_BUF_NUM) + ppost->di_post_num = MAX_POST_BUF_NUM; + else + ppost->di_post_num = (de_devp->buf_num_avail - 2); + #else + /*mm-0705 ppost->di_post_num = MAX_POST_BUF_NUM;*/ + #endif + dbg_init("DI: di post buffer size 0x%x byte.\n", + di_post_buf_size); + } else { + /*mm-0705 ppost->di_post_num = MAX_POST_BUF_NUM;*/ + di_post_buf_size = 0; + } + de_devp->post_buffer_size = di_post_buf_size; + + /**********************************************/ + /* input buf init */ + /**********************************************/ + + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + struct di_buf_s *di_buf = &pbuf_in[i]; + + if (di_buf) { + memset(di_buf, 0, sizeof(struct di_buf_s)); + di_buf->type = VFRAME_TYPE_IN; + di_buf->pre_ref_count = 0; + di_buf->post_ref_count = 0; + di_buf->vframe = &pvframe_in_dup[i]; + di_buf->vframe->private_data = di_buf; + di_buf->index = i; + di_buf->queue_index = -1; + di_buf->invert_top_bot_flag = 0; + di_buf->channel = channel; + di_que_in(channel, QUE_IN_FREE, di_buf); + } + } + /**********************************************/ + /* post buf init */ + /**********************************************/ + /*mm-0705 for (i = 0; i < ppost->di_post_num; i++) {*/ + for (i = 0; i < mm->cfg.num_post; i++) { + struct di_buf_s *di_buf = &pbuf_post[i]; + + if (di_buf) { + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) { + /*ary:for keep buf*/ + if (keep_buf_post && di_buf == keep_buf_post) { + dbg_reg("%s:post keep buf %d:%d\n", + __func__, + i, keep_buf_post->index); + continue; + } + } + + memset(di_buf, 0, sizeof(struct di_buf_s)); + di_buf->type = VFRAME_TYPE_POST; + di_buf->index = i; + di_buf->vframe = &pvframe_post[i]; + di_buf->vframe->private_data = di_buf; + di_buf->queue_index = -1; + di_buf->invert_top_bot_flag = 0; + di_buf->channel = channel; + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) { + di_buf->canvas_width[NR_CANVAS] = + (nr_width << 1); + di_buf->canvas_height = canvas_height; + di_buf->canvas_config_flag = 1; + di_buf->nr_adr = di_post_mem + + di_post_buf_size * i; + dbg_init("[%d]post buf:%d: addr=0x%lx\n", i, + di_buf->index, di_buf->nr_adr); + } + + di_que_in(channel, QUE_POST_FREE, di_buf); + + } else { + PR_ERR("%s:%d:post buf is null\n", __func__, i); + } + } + if (de_devp->flag_cma == 0 && de_devp->nrds_enable) { + nrds_mem = di_post_mem + mm->cfg.num_post * di_post_buf_size; + /*mm-0705 ppost->di_post_num * di_post_buf_size;*/ + dim_nr_ds_buf_init(de_devp->flag_cma, nrds_mem, + &de_devp->pdev->dev); + } + return 0; +} + +void dim_keep_mirror_buffer(unsigned int channel) /*not use*/ +{ + struct di_buf_s *p = NULL; + int i = 0, ii = 0, itmp; + struct di_post_stru_s *ppost = get_post_stru(channel); + + queue_for_each_entry(p, channel, QUEUE_DISPLAY, list) { + if (p->di_buf[0]->type != VFRAME_TYPE_IN && + (p->process_fun_index != PROCESS_FUN_NULL) && + (ii < USED_LOCAL_BUF_MAX) && + (p->index == ppost->cur_disp_index)) { + ppost->keep_buf = p; + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + if (IS_ERR_OR_NULL(p->di_buf_dup_p[i])) + continue; + /* prepare for recycle + * the keep buffer + */ + p->di_buf_dup_p[i]->pre_ref_count = 0; + p->di_buf_dup_p[i]->post_ref_count = 0; + if ((p->di_buf_dup_p[i]->queue_index >= 0) && + (p->di_buf_dup_p[i]->queue_index < QUEUE_NUM)) { + if (is_in_queue(channel, + p->di_buf_dup_p[i], + p->di_buf_dup_p[i]->queue_index + )) + queue_out(channel, p->di_buf_dup_p[i]); + /*which que?*/ + } + ii++; + if (p->di_buf_dup_p[i]->di_wr_linked_buf) + p->di_buf_dup_p[i + 1] = + p->di_buf_dup_p[i]->di_wr_linked_buf; + } + queue_out(channel, p); /*which que?*/ + break; + } + } +} + +void dim_post_keep_mirror_buffer(unsigned int channel) +{ + struct di_buf_s *p = NULL; + int itmp; + bool flg = false; + struct di_post_stru_s *ppost = get_post_stru(channel); + + queue_for_each_entry(p, channel, QUEUE_DISPLAY, list) { + if (p->type != VFRAME_TYPE_POST || + !p->process_fun_index) { + dbg_reg("%s:not post buf:%d\n", + __func__, p->type); + continue; + } + + ppost->keep_buf_post = p; /*only keep one*/ + flg = true; + dbg_reg("%s %d\n", __func__, p->index); + } + + if (flg && ppost->keep_buf_post) { + ppost->keep_buf_post->queue_index = -1; + ppost->keep_buf_post->invert_top_bot_flag = 0; + } +} + +void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel) +{ + /*int i = 0;*/ + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (!queue_empty(channel, QUEUE_DISPLAY) || disable_mirror) + ppost->keep_buf = NULL; +#if 0 + if (disable_mirror != 1) + dim_keep_mirror_buffer(); + + if (!IS_ERR_OR_NULL(di_post_stru.keep_buf)) { + keep_buf = di_post_stru.keep_buf; + pr_dbg("%s keep cur di_buf %d (", + __func__, keep_buf->index); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + if (!IS_ERR_OR_NULL(keep_buf->di_buf_dup_p[i])) + pr_dbg("%d\t", + keep_buf->di_buf_dup_p[i]->index); + } + pr_dbg(")\n"); + } +#else + if (!disable_mirror) + dim_post_keep_mirror_buffer(channel); +#endif + queue_init(channel, 0); + di_que_init(channel); /*new que*/ + + /* decoder'buffer had been releae no need put */ + #if 0 + for (i = 0; i < MAX_IN_BUF_NUM; i++) + pvframe_in[i] = NULL; + #else + memset(pvframe_in, 0, sizeof(*pvframe_in) * MAX_IN_BUF_NUM); + #endif + ppre->pre_de_process_flag = 0; + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) { + ppost->cur_post_buf = NULL; + ppost->post_de_busy = 0; + ppost->de_post_process_done = 0; + ppost->post_wr_cnt = 0; + } + if (de_devp->flag_cma == 0 && de_devp->nrds_enable) { + dim_nr_ds_buf_uninit(de_devp->flag_cma, + &de_devp->pdev->dev); + } +} + +void dim_log_buffer_state(unsigned char *tag, unsigned int channel) +{ + struct di_pre_stru_s *ppre; + unsigned int tmpa[MAX_FIFO_SIZE]; /*new que*/ + unsigned int psize; /*new que*/ + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_BUFFER_STATE) { + struct di_buf_s *p = NULL;/* , *ptmp; */ + int itmp; + int in_free = 0; + int local_free = 0; + int pre_ready = 0; + int post_free = 0; + int post_ready = 0; + int post_ready_ext = 0; + int display = 0; + int display_ext = 0; + int recycle = 0; + int di_inp = 0; + int di_wr = 0; + ulong irq_flag2 = 0; + + ppre = get_pre_stru(channel); + + di_lock_irqfiq_save(irq_flag2); + in_free = di_que_list_count(channel, QUE_IN_FREE); + local_free = list_count(channel, QUEUE_LOCAL_FREE); + pre_ready = di_que_list_count(channel, QUE_PRE_READY); + post_free = di_que_list_count(channel, QUE_POST_FREE); + post_ready = di_que_list_count(channel, QUE_POST_READY); + + di_que_list(channel, QUE_POST_READY, &tmpa[0], &psize); + /*di_que_for_each(channel, p, psize, &tmpa[0]) {*/ + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + if (p->di_buf[0]) + post_ready_ext++; + + if (p->di_buf[1]) + post_ready_ext++; + } + queue_for_each_entry(p, channel, QUEUE_DISPLAY, list) { + display++; + if (p->di_buf[0]) + display_ext++; + + if (p->di_buf[1]) + display_ext++; + } + recycle = list_count(channel, QUEUE_RECYCLE); + + if (ppre->di_inp_buf) + di_inp++; + if (ppre->di_wr_buf) + di_wr++; + + if (dimp_get(eDI_MP_buf_state_log_threshold) == 0) + buf_state_log_start = 0; + else if (post_ready < dimp_get(eDI_MP_buf_state_log_threshold)) + buf_state_log_start = 1; + + if (buf_state_log_start) { + dim_print( + "[%s]i i_f %d/%d, l_f %d, pre_r %d, post_f %d/%d,", + tag, + in_free, MAX_IN_BUF_NUM, + local_free, + pre_ready, + post_free, MAX_POST_BUF_NUM); + dim_print( + "post_r (%d:%d), disp (%d:%d),rec %d, di_i %d, di_w %d\n", + post_ready, post_ready_ext, + display, display_ext, + recycle, + di_inp, di_wr + ); + } + di_unlock_irqfiq_restore(irq_flag2); + } +} + +static void dump_state(unsigned int channel) +{ + struct di_buf_s *p = NULL, *keep_buf; + int itmp, i; + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + unsigned int tmpa[MAX_FIFO_SIZE]; /*new que*/ + unsigned int psize; /*new que*/ + struct di_mm_s *mm = dim_mm_get(); /*mm-0705*/ + + dump_state_flag = 1; + pr_info("version %s, init_flag %d, is_bypass %d\n", + version_s, get_init_flag(channel), + dim_is_bypass(NULL, channel)); + pr_info("recovery_flag = %d, recovery_log_reason=%d, di_blocking=%d", + recovery_flag, recovery_log_reason, di_blocking); + pr_info("recovery_log_queue_idx=%d, recovery_log_di_buf=0x%p\n", + recovery_log_queue_idx, recovery_log_di_buf); + pr_info("buffer_size=%d, mem_flag=%s, cma_flag=%d\n", + /*atomic_read(&de_devp->mem_flag)*/ + de_devp->buffer_size, di_cma_dbg_get_st_name(channel), + de_devp->flag_cma); + keep_buf = ppost->keep_buf; + pr_info("used_post_buf_index %d(0x%p),", + IS_ERR_OR_NULL(keep_buf) ? + -1 : keep_buf->index, keep_buf); +#if 0 + if (!IS_ERR_OR_NULL(keep_buf)) { + pr_info("used_local_buf_index:\n"); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + p = keep_buf->di_buf_dup_p[i]; + pr_info("%d(0x%p) ", + IS_ERR_OR_NULL(p) ? -1 : p->index, p); + } + } +#endif + pr_info("\nin_free_list (max %d):\n", MAX_IN_BUF_NUM); + + di_que_list(channel, QUE_IN_FREE, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + pr_info("index %2d, 0x%p, type %d\n", + p->index, p, p->type); + } + pr_info("local_free_list (max %d):\n", mm->cfg.num_local); + queue_for_each_entry(p, channel, QUEUE_LOCAL_FREE, list) { + pr_info("index %2d, 0x%p, type %d\n", p->index, p, p->type); + } + + pr_info("post_doing_list:\n"); + queue_for_each_entry(p, channel, QUEUE_POST_DOING, list) { + dim_print_di_buf(p, 2); + } + pr_info("pre_ready_list:\n"); + + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + dim_print_di_buf(p, 2); + } + pr_info("post_free_list (max %d):\n", mm->cfg.num_post); + + di_que_list(channel, QUE_POST_FREE, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + + pr_info("index %2d, 0x%p, type %d, vframetype 0x%x\n", + p->index, p, p->type, p->vframe->type); + } + pr_info("post_ready_list:\n"); + + di_que_list(channel, QUE_POST_READY, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + + dim_print_di_buf(p, 2); + dim_print_di_buf(p->di_buf[0], 1); + dim_print_di_buf(p->di_buf[1], 1); + } + pr_info("display_list:\n"); + queue_for_each_entry(p, channel, QUEUE_DISPLAY, list) { + dim_print_di_buf(p, 2); + dim_print_di_buf(p->di_buf[0], 1); + dim_print_di_buf(p->di_buf[1], 1); + } + pr_info("recycle_list:\n"); + queue_for_each_entry(p, channel, QUEUE_RECYCLE, list) { + pr_info( +"index %d, 0x%p, type %d, vframetype 0x%x pre_ref_count %d post_ref_count %d\n", + p->index, p, p->type, + p->vframe->type, + p->pre_ref_count, + p->post_ref_count); + if (p->di_wr_linked_buf) { + pr_info( + "linked index %2d, 0x%p, type %d pre_ref_count %d post_ref_count %d\n", + p->di_wr_linked_buf->index, + p->di_wr_linked_buf, + p->di_wr_linked_buf->type, + p->di_wr_linked_buf->pre_ref_count, + p->di_wr_linked_buf->post_ref_count); + } + } + if (ppre->di_inp_buf) { + pr_info("di_inp_buf:index %d, 0x%p, type %d\n", + ppre->di_inp_buf->index, + ppre->di_inp_buf, + ppre->di_inp_buf->type); + } else { + pr_info("di_inp_buf: NULL\n"); + } + if (ppre->di_wr_buf) { + pr_info("di_wr_buf:index %d, 0x%p, type %d\n", + ppre->di_wr_buf->index, + ppre->di_wr_buf, + ppre->di_wr_buf->type); + } else { + pr_info("di_wr_buf: NULL\n"); + } + dim_dump_pre_stru(ppre); + dim_dump_post_stru(ppost); + pr_info("vframe_in[]:"); + + for (i = 0; i < MAX_IN_BUF_NUM; i++) + pr_info("0x%p ", pvframe_in[i]); + + pr_info("\n"); + pr_info("vf_peek()=>0x%p, video_peek_cnt = %d\n", + pw_vf_peek(channel), di_sum_get(channel, eDI_SUM_O_PEEK_CNT)); + pr_info("reg_unreg_timerout = %lu\n", reg_unreg_timeout_cnt); + dump_state_flag = 0; +} + +unsigned char dim_check_di_buf(struct di_buf_s *di_buf, int reason, + unsigned int channel) +{ + int error = 0; + struct vframe_s *pvframe_in_dup = get_vframe_in_dup(channel); + struct vframe_s *pvframe_local = get_vframe_local(channel); + struct vframe_s *pvframe_post = get_vframe_post(channel); + + if (!di_buf) { + PR_ERR("%s: %d, di_buf is NULL\n", __func__, reason); + return 1; + } + + if (di_buf->type == VFRAME_TYPE_IN) { + if (di_buf->vframe != &pvframe_in_dup[di_buf->index]) + error = 1; + } else if (di_buf->type == VFRAME_TYPE_LOCAL) { + if (di_buf->vframe != &pvframe_local[di_buf->index]) + error = 1; + } else if (di_buf->type == VFRAME_TYPE_POST) { + if (di_buf->vframe != &pvframe_post[di_buf->index]) + error = 1; + } else { + error = 1; + } + + if (error) { + PR_ERR("%s: %d, di_buf wrong\n", __func__, reason); + if (recovery_flag == 0) + recovery_log_reason = reason; + recovery_flag++; + dim_dump_di_buf(di_buf); + return 1; + } + + return 0; +} + +/* + * di pre process + */ +static void +config_di_mcinford_mif(struct DI_MC_MIF_s *di_mcinford_mif, + struct di_buf_s *di_buf) +{ + if (di_buf) { + di_mcinford_mif->size_x = (di_buf->vframe->height + 2) / 4 - 1; + di_mcinford_mif->size_y = 1; + di_mcinford_mif->canvas_num = di_buf->mcinfo_canvas_idx; + } +} + +static void +config_di_pre_mc_mif(struct DI_MC_MIF_s *di_mcinfo_mif, + struct DI_MC_MIF_s *di_mcvec_mif, + struct di_buf_s *di_buf) +{ + unsigned int pre_size_w = 0, pre_size_h = 0; + + if (di_buf) { + pre_size_w = di_buf->vframe->width; + pre_size_h = (di_buf->vframe->height + 1) / 2; + di_mcinfo_mif->size_x = (pre_size_h + 1) / 2 - 1; + di_mcinfo_mif->size_y = 1; + di_mcinfo_mif->canvas_num = di_buf->mcinfo_canvas_idx; + + di_mcvec_mif->size_x = (pre_size_w + 4) / 5 - 1; + di_mcvec_mif->size_y = pre_size_h - 1; + di_mcvec_mif->canvas_num = di_buf->mcvec_canvas_idx; + } +} + +static void config_di_cnt_mif(struct DI_SIM_MIF_s *di_cnt_mif, + struct di_buf_s *di_buf) +{ + if (di_buf) { + di_cnt_mif->start_x = 0; + di_cnt_mif->end_x = di_buf->vframe->width - 1; + di_cnt_mif->start_y = 0; + di_cnt_mif->end_y = di_buf->vframe->height / 2 - 1; + di_cnt_mif->canvas_num = di_buf->cnt_canvas_idx; + } +} + +static void +config_di_wr_mif(struct DI_SIM_MIF_s *di_nrwr_mif, + struct DI_SIM_MIF_s *di_mtnwr_mif, + struct di_buf_s *di_buf, unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + vframe_t *vf = di_buf->vframe; + + di_nrwr_mif->canvas_num = di_buf->nr_canvas_idx; + di_nrwr_mif->start_x = 0; + di_nrwr_mif->end_x = vf->width - 1; + di_nrwr_mif->start_y = 0; + if (di_buf->vframe->bitdepth & BITDEPTH_Y10) + di_nrwr_mif->bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? + 3 : 1; + else + di_nrwr_mif->bit_mode = 0; + if (ppre->prog_proc_type == 0) + di_nrwr_mif->end_y = vf->height / 2 - 1; + else + di_nrwr_mif->end_y = vf->height - 1; + if (ppre->prog_proc_type == 0) { + di_mtnwr_mif->start_x = 0; + di_mtnwr_mif->end_x = vf->width - 1; + di_mtnwr_mif->start_y = 0; + di_mtnwr_mif->end_y = vf->height / 2 - 1; + di_mtnwr_mif->canvas_num = di_buf->mtn_canvas_idx; + } +} + +static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf, + unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (!di_buf) + return; + di_mif->canvas0_addr0 = + di_buf->vframe->canvas0Addr & 0xff; + di_mif->canvas0_addr1 = + (di_buf->vframe->canvas0Addr >> 8) & 0xff; + di_mif->canvas0_addr2 = + (di_buf->vframe->canvas0Addr >> 16) & 0xff; + + di_mif->nocompress = (di_buf->vframe->type & VIDTYPE_COMPRESS) ? 0 : 1; + + if (di_buf->vframe->bitdepth & BITDEPTH_Y10) { + if (di_buf->vframe->type & VIDTYPE_VIU_444) + di_mif->bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? + 3 : 2; + else if (di_buf->vframe->type & VIDTYPE_VIU_422) + di_mif->bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? + 3 : 1; + } else { + di_mif->bit_mode = 0; + } + if (di_buf->vframe->type & VIDTYPE_VIU_422) { + /* from vdin or local vframe */ + if ((!is_progressive(di_buf->vframe)) || + (ppre->prog_proc_type)) { + di_mif->video_mode = 0; + di_mif->set_separate_en = 0; + di_mif->src_field_mode = 0; + di_mif->output_field_num = 0; + di_mif->luma_x_start0 = 0; + di_mif->luma_x_end0 = + di_buf->vframe->width - 1; + di_mif->luma_y_start0 = 0; + if (ppre->prog_proc_type) + di_mif->luma_y_end0 = + di_buf->vframe->height - 1; + else + di_mif->luma_y_end0 = + di_buf->vframe->height / 2 - 1; + di_mif->chroma_x_start0 = 0; + di_mif->chroma_x_end0 = 0; + di_mif->chroma_y_start0 = 0; + di_mif->chroma_y_end0 = 0; + di_mif->canvas0_addr0 = + di_buf->vframe->canvas0Addr & 0xff; + di_mif->canvas0_addr1 = + (di_buf->vframe->canvas0Addr >> 8) & 0xff; + di_mif->canvas0_addr2 = + (di_buf->vframe->canvas0Addr >> 16) & 0xff; + } + } else { + if (di_buf->vframe->type & VIDTYPE_VIU_444) + di_mif->video_mode = 1; + else + di_mif->video_mode = 0; + if (di_buf->vframe->type & VIDTYPE_VIU_NV21) + di_mif->set_separate_en = 2; + else + di_mif->set_separate_en = 1; + + if (is_progressive(di_buf->vframe) && + (ppre->prog_proc_type)) { + di_mif->src_field_mode = 0; + di_mif->output_field_num = 0; /* top */ + di_mif->luma_x_start0 = 0; + di_mif->luma_x_end0 = + di_buf->vframe->width - 1; + di_mif->luma_y_start0 = 0; + di_mif->luma_y_end0 = + di_buf->vframe->height - 1; + di_mif->chroma_x_start0 = 0; + di_mif->chroma_x_end0 = + di_buf->vframe->width / 2 - 1; + di_mif->chroma_y_start0 = 0; + di_mif->chroma_y_end0 = + di_buf->vframe->height / 2 - 1; + } else { + /*move to mp di_mif->src_prog = force_prog?1:0;*/ + if (ppre->cur_inp_type & VIDTYPE_INTERLACE) + di_mif->src_prog = 0; + else + di_mif->src_prog + = dimp_get(eDI_MP_force_prog) ? 1 : 0; + di_mif->src_field_mode = 1; + if ( + (di_buf->vframe->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) { + di_mif->output_field_num = 0; /* top */ + di_mif->luma_x_start0 = 0; + di_mif->luma_x_end0 = + di_buf->vframe->width - 1; + di_mif->luma_y_start0 = 0; + di_mif->luma_y_end0 = + di_buf->vframe->height - 2; + di_mif->chroma_x_start0 = 0; + di_mif->chroma_x_end0 = + di_buf->vframe->width / 2 - 1; + di_mif->chroma_y_start0 = 0; + di_mif->chroma_y_end0 = + di_buf->vframe->height / 2 + - (di_mif->src_prog ? 1 : 2); + } else { + di_mif->output_field_num = 1; + /* bottom */ + di_mif->luma_x_start0 = 0; + di_mif->luma_x_end0 = + di_buf->vframe->width - 1; + di_mif->luma_y_start0 = 1; + di_mif->luma_y_end0 = + di_buf->vframe->height - 1; + di_mif->chroma_x_start0 = 0; + di_mif->chroma_x_end0 = + di_buf->vframe->width / 2 - 1; + di_mif->chroma_y_start0 = + (di_mif->src_prog ? 0 : 1); + di_mif->chroma_y_end0 = + di_buf->vframe->height / 2 - 1; + } + } + } +} + +static void di_pre_size_change(unsigned short width, + unsigned short height, + unsigned short vf_type, + unsigned int channel); + +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC +static void pre_inp_canvas_config(struct vframe_s *vf); +#endif +void dim_pre_de_process(unsigned int channel) +{ + ulong irq_flag2 = 0; + unsigned short pre_width = 0, pre_height = 0; + unsigned char chan2_field_num = 1; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + int canvases_idex = ppre->field_count_for_cont % 2; + unsigned short cur_inp_field_type = VIDTYPE_TYPEMASK; + unsigned short int_mask = 0x7f; + struct di_dev_s *de_devp = get_dim_de_devp(); + + ppre->pre_de_process_flag = 1; + dim_ddbg_mod_save(eDI_DBG_MOD_PRE_SETB, channel, ppre->in_seq);/*dbg*/ + + #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + pre_inp_canvas_config(ppre->di_inp_buf->vframe); + #endif + + config_di_mif(&ppre->di_inp_mif, ppre->di_inp_buf, channel); + /* pr_dbg("set_separate_en=%d vframe->type %d\n", + * di_pre_stru.di_inp_mif.set_separate_en, + * di_pre_stru.di_inp_buf->vframe->type); + */ +#ifdef DI_USE_FIXED_CANVAS_IDX + if (ppre->di_mem_buf_dup_p && + ppre->di_mem_buf_dup_p != ppre->di_inp_buf) { + config_canvas_idx(ppre->di_mem_buf_dup_p, + di_pre_idx[canvases_idex][0], -1); + config_cnt_canvas_idx(ppre->di_mem_buf_dup_p, + di_pre_idx[canvases_idex][1]); + } else { + config_cnt_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][1]); + config_di_cnt_mif(&ppre->di_contp2rd_mif, + ppre->di_wr_buf); + } + if (ppre->di_chan2_buf_dup_p) { + config_canvas_idx(ppre->di_chan2_buf_dup_p, + di_pre_idx[canvases_idex][2], -1); + config_cnt_canvas_idx(ppre->di_chan2_buf_dup_p, + di_pre_idx[canvases_idex][3]); + } else { + config_cnt_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][3]); + } + config_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][4], + di_pre_idx[canvases_idex][5]); + config_cnt_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][6]); + if (dimp_get(eDI_MP_mcpre_en)) { + if (ppre->di_chan2_buf_dup_p) + config_mcinfo_canvas_idx(ppre->di_chan2_buf_dup_p, + di_pre_idx[canvases_idex][7]); + else + config_mcinfo_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][7]); + + config_mcinfo_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][8]); + config_mcvec_canvas_idx(ppre->di_wr_buf, + di_pre_idx[canvases_idex][9]); + } +#endif + config_di_mif(&ppre->di_mem_mif, ppre->di_mem_buf_dup_p, channel); + if (!ppre->di_chan2_buf_dup_p) { + config_di_mif(&ppre->di_chan2_mif, + ppre->di_inp_buf, channel); + } else + config_di_mif(&ppre->di_chan2_mif, + ppre->di_chan2_buf_dup_p, channel); + config_di_wr_mif(&ppre->di_nrwr_mif, &ppre->di_mtnwr_mif, + ppre->di_wr_buf, channel); + + if (ppre->di_chan2_buf_dup_p) + config_di_cnt_mif(&ppre->di_contprd_mif, + ppre->di_chan2_buf_dup_p); + else + config_di_cnt_mif(&ppre->di_contprd_mif, + ppre->di_wr_buf); + + config_di_cnt_mif(&ppre->di_contwr_mif, ppre->di_wr_buf); + if (dimp_get(eDI_MP_mcpre_en)) { + if (ppre->di_chan2_buf_dup_p) + config_di_mcinford_mif(&ppre->di_mcinford_mif, + ppre->di_chan2_buf_dup_p); + else + config_di_mcinford_mif(&ppre->di_mcinford_mif, + ppre->di_wr_buf); + + config_di_pre_mc_mif(&ppre->di_mcinfowr_mif, + &ppre->di_mcvecwr_mif, ppre->di_wr_buf); + } + + if ((ppre->di_chan2_buf_dup_p) && + ((ppre->di_chan2_buf_dup_p->vframe->type & VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP)) + chan2_field_num = 0; + + pre_width = ppre->di_nrwr_mif.end_x + 1; + pre_height = ppre->di_nrwr_mif.end_y + 1; + if (ppre->input_size_change_flag) { + cur_inp_field_type = + (ppre->di_inp_buf->vframe->type & VIDTYPE_TYPEMASK); + cur_inp_field_type = + ppre->cur_prog_flag ? VIDTYPE_PROGRESSIVE : cur_inp_field_type; + /*di_async_reset2();*/ + di_pre_size_change(pre_width, pre_height, + cur_inp_field_type, channel); + ppre->input_size_change_flag = false; + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (de_devp->nrds_enable) { + dim_nr_ds_mif_config(); + dim_nr_ds_hw_ctrl(true); + int_mask = 0x3f; + } else { + dim_nr_ds_hw_ctrl(false); + } + } + + /* set interrupt mask for pre module. + * we need to only leave one mask open + * to prevent multiple entry for dim_irq + */ + + /*dim_dbg_pre_cnt(channel, "s2");*/ + + dimh_enable_di_pre_aml(&ppre->di_inp_mif, + &ppre->di_mem_mif, + &ppre->di_chan2_mif, + &ppre->di_nrwr_mif, + &ppre->di_mtnwr_mif, + &ppre->di_contp2rd_mif, + &ppre->di_contprd_mif, + &ppre->di_contwr_mif, + ppre->madi_enable, + chan2_field_num, + ppre->vdin2nr); + + dimh_enable_afbc_input(ppre->di_inp_buf->vframe); + + if (dimp_get(eDI_MP_mcpre_en)) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dimh_enable_mc_di_pre_g12(&ppre->di_mcinford_mif, + &ppre->di_mcinfowr_mif, + &ppre->di_mcvecwr_mif, + ppre->mcdi_enable); + else + dimh_enable_mc_di_pre(&ppre->di_mcinford_mif, + &ppre->di_mcinfowr_mif, + &ppre->di_mcvecwr_mif, + ppre->mcdi_enable); + } + + ppre->field_count_for_cont++; + dimh_txl_patch_prog(ppre->cur_prog_flag, + ppre->field_count_for_cont, + dimp_get(eDI_MP_mcpre_en)); + +#ifdef SUPPORT_MPEG_TO_VDIN + if (mpeg2vdin_flag) { + struct vdin_arg_s vdin_arg; + struct vdin_v4l2_ops_s *vdin_ops = get_vdin_v4l2_ops(); + + vdin_arg.cmd = VDIN_CMD_FORCE_GO_FIELD; + if (vdin_ops->tvin_vdin_func) + vdin_ops->tvin_vdin_func(0, &vdin_arg); + } +#endif + /* must make sure follow part issue without interrupts, + * otherwise may cause watch dog reboot + */ + di_lock_irqfiq_save(irq_flag2); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dim_pre_frame_reset_g12(ppre->madi_enable, + ppre->mcdi_enable); + else + dim_pre_frame_reset(); + + /* enable mc pre mif*/ + dimh_enable_di_pre_mif(true, dimp_get(eDI_MP_mcpre_en)); + /*dbg_set_DI_PRE_CTRL();*/ + di_pre_wait_irq_set(true); + di_unlock_irqfiq_restore(irq_flag2); + /*reinit pre busy flag*/ + ppre->pre_de_busy = 1; + + #ifdef SUPPORT_MPEG_TO_VDIN + if (mpeg2vdin_flag) + dim_RDMA_WR_BITS(DI_PRE_CTRL, 1, 13, 1); + #endif + dim_dbg_pre_cnt(channel, "s3"); + ppre->irq_time[0] = cur_to_msecs(); + ppre->irq_time[1] = cur_to_msecs(); + dim_ddbg_mod_save(eDI_DBG_MOD_PRE_SETE, channel, ppre->in_seq);/*dbg*/ + dim_tr_ops.pre_set(ppre->di_wr_buf->vframe->omx_index); +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (di_pre_rdma_enable & 0x2) + rdma_config(de_devp->rdma_handle, RDMA_TRIGGER_MANUAL); + else if (di_pre_rdma_enable & 1) + rdma_config(de_devp->rdma_handle, RDMA_DEINT_IRQ); +#endif + ppre->pre_de_process_flag = 0; +} + +void dim_pre_de_done_buf_clear(unsigned int channel) +{ + struct di_buf_s *wr_buf = NULL; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (ppre->di_wr_buf) { + wr_buf = ppre->di_wr_buf; + if ((ppre->prog_proc_type == 2) && + wr_buf->di_wr_linked_buf) { + wr_buf->di_wr_linked_buf->pre_ref_count = 0; + wr_buf->di_wr_linked_buf->post_ref_count = 0; + queue_in(channel, wr_buf->di_wr_linked_buf, + QUEUE_RECYCLE); + wr_buf->di_wr_linked_buf = NULL; + } + wr_buf->pre_ref_count = 0; + wr_buf->post_ref_count = 0; + queue_in(channel, wr_buf, QUEUE_RECYCLE); + ppre->di_wr_buf = NULL; + } + if (ppre->di_inp_buf) { + if (ppre->di_mem_buf_dup_p == ppre->di_inp_buf) + ppre->di_mem_buf_dup_p = NULL; + + queue_in(channel, ppre->di_inp_buf, QUEUE_RECYCLE); + ppre->di_inp_buf = NULL; + } +} + +static void top_bot_config(struct di_buf_s *di_buf) +{ + vframe_t *vframe = di_buf->vframe; + + if (((invert_top_bot & 0x1) != 0) && (!is_progressive(vframe))) { + if (di_buf->invert_top_bot_flag == 0) { + if ((vframe->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) { + vframe->type &= (~VIDTYPE_TYPEMASK); + vframe->type |= VIDTYPE_INTERLACE_BOTTOM; + } else { + vframe->type &= (~VIDTYPE_TYPEMASK); + vframe->type |= VIDTYPE_INTERLACE_TOP; + } + di_buf->invert_top_bot_flag = 1; + } + } +} + +void dim_pre_de_done_buf_config(unsigned int channel, bool flg_timeout) +{ + ulong irq_flag2 = 0; + int tmp_cur_lev; + struct di_buf_s *post_wr_buf = NULL; + unsigned int glb_frame_mot_num = 0; + unsigned int glb_field_mot_num = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + dim_dbg_pre_cnt(channel, "d1"); + dim_ddbg_mod_save(eDI_DBG_MOD_PRE_DONEB, channel, ppre->in_seq);/*dbg*/ + if (ppre->di_wr_buf) { + dim_tr_ops.pre_ready(ppre->di_wr_buf->vframe->omx_index); + if (ppre->pre_throw_flag > 0) { + ppre->di_wr_buf->throw_flag = 1; + ppre->pre_throw_flag--; + } else { + ppre->di_wr_buf->throw_flag = 0; + } +#ifdef DET3D + if (ppre->di_wr_buf->vframe->trans_fmt == 0 && + ppre->det3d_trans_fmt != 0 && + dimp_get(eDI_MP_det3d_en)) { + ppre->di_wr_buf->vframe->trans_fmt = + ppre->det3d_trans_fmt; + set3d_view(ppre->det3d_trans_fmt, + ppre->di_wr_buf->vframe); + } +#endif + if (!di_pre_rdma_enable) + ppre->di_post_wr_buf = ppre->di_wr_buf; + post_wr_buf = ppre->di_post_wr_buf; + + if (post_wr_buf && !ppre->cur_prog_flag && + !flg_timeout) { + dim_read_pulldown_info(&glb_frame_mot_num, + &glb_field_mot_num); + if (dimp_get(eDI_MP_pulldown_enable)) + /*pulldown_detection*/ + get_ops_pd()->detection(&post_wr_buf->pd_config, + ppre->mtn_status, + overturn, + ppre->di_inp_buf->vframe); + /*if (combing_fix_en)*/ + /*if (dimp_get(eDI_MP_combing_fix_en)) {*/ + if (ppre->combing_fix_en) { + tmp_cur_lev /*cur_lev*/ + = get_ops_mtn()->adaptive_combing_fixing( + ppre->mtn_status, + glb_field_mot_num, + glb_frame_mot_num, + dimp_get(eDI_MP_di_force_bit_mode)); + dimp_set(eDI_MP_cur_lev, tmp_cur_lev); + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + get_ops_nr()->adaptive_cue_adjust( + glb_frame_mot_num, + glb_field_mot_num); + dim_pulldown_info_clear_g12a(); + } + + if (ppre->cur_prog_flag) { + if (ppre->prog_proc_type == 0) { + /* di_mem_buf_dup->vfrme + * is either local vframe, + * or bot field of vframe from in_list + */ + ppre->di_mem_buf_dup_p->pre_ref_count = 0; + ppre->di_mem_buf_dup_p + = ppre->di_chan2_buf_dup_p; + ppre->di_chan2_buf_dup_p + = ppre->di_wr_buf; +#ifdef DI_BUFFER_DEBUG + dim_print("%s:set di_mem to di_chan2,", __func__); + dim_print("%s:set di_chan2 to di_wr_buf\n", __func__); +#endif + } else { + ppre->di_mem_buf_dup_p->pre_ref_count = 0; + /*recycle the progress throw buffer*/ + if (ppre->di_wr_buf->throw_flag) { + ppre->di_wr_buf-> + pre_ref_count = 0; + ppre->di_mem_buf_dup_p = NULL; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s set throw %s[%d] pre_ref_count to 0.\n", + __func__, + vframe_type_name[ppre->di_wr_buf->type], + ppre->di_wr_buf->index); +#endif + } else { + ppre->di_mem_buf_dup_p + = ppre->di_wr_buf; + } +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: set di_mem_buf_dup_p to di_wr_buf\n", + __func__); +#endif + } + + ppre->di_wr_buf->seq + = ppre->pre_ready_seq++; + ppre->di_wr_buf->post_ref_count = 0; + ppre->di_wr_buf->left_right + = ppre->left_right; + if (ppre->source_change_flag) { + ppre->di_wr_buf->new_format_flag = 1; + ppre->source_change_flag = 0; + } else { + ppre->di_wr_buf->new_format_flag = 0; + } + if (di_bypass_state_get(channel) == 1) { + ppre->di_wr_buf->new_format_flag = 1; + /*bypass_state = 0;*/ + di_bypass_state_set(channel, false); +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s:bypass_state->0, is_bypass() %d\n", + __func__, dim_is_bypass(NULL, channel)); + dim_print( + "trick_mode %d bypass_all %d\n", + trick_mode, di_cfgx_get(channel, eDI_CFGX_BYPASS_ALL)); +#endif + } + if (ppre->di_post_wr_buf) + di_que_in(channel, QUE_PRE_READY, + ppre->di_post_wr_buf); + +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: %s[%d] => pre_ready_list\n", __func__, + vframe_type_name[ppre->di_wr_buf->type], + ppre->di_wr_buf->index); +#endif + if (ppre->di_wr_buf) { + if (di_pre_rdma_enable) + ppre->di_post_wr_buf = + ppre->di_wr_buf; + else + ppre->di_post_wr_buf = NULL; + ppre->di_wr_buf = NULL; + } + } else { + ppre->di_mem_buf_dup_p->pre_ref_count = 0; + ppre->di_mem_buf_dup_p = NULL; + if (ppre->di_chan2_buf_dup_p) { + ppre->di_mem_buf_dup_p = + ppre->di_chan2_buf_dup_p; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: di_mem_buf_dup_p = di_chan2_buf_dup_p\n", + __func__); +#endif + } + ppre->di_chan2_buf_dup_p = ppre->di_wr_buf; + + if (ppre->source_change_flag) { + /* add dummy buf, will not be displayed */ + add_dummy_vframe_type_pre(post_wr_buf, + channel); + } + ppre->di_wr_buf->seq = ppre->pre_ready_seq++; + ppre->di_wr_buf->left_right = ppre->left_right; + ppre->di_wr_buf->post_ref_count = 0; + + if (ppre->source_change_flag) { + ppre->di_wr_buf->new_format_flag = 1; + ppre->source_change_flag = 0; + } else { + ppre->di_wr_buf->new_format_flag = 0; + } + if (di_bypass_state_get(channel) == 1) { + ppre->di_wr_buf->new_format_flag = 1; + /*bypass_state = 0;*/ + di_bypass_state_set(channel, false); + +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s:bypass_state->0, is_bypass() %d\n", + __func__, dim_is_bypass(NULL, channel)); + dim_print( + "trick_mode %d bypass_all %d\n", + trick_mode, di_cfgx_get(channel, eDI_CFGX_BYPASS_ALL)); +#endif + } + + if (ppre->di_post_wr_buf) + di_que_in(channel, QUE_PRE_READY, + ppre->di_post_wr_buf); + + dim_print("%s: %s[%d] => pre_ready_list\n", __func__, + vframe_type_name[ppre->di_wr_buf->type], + ppre->di_wr_buf->index); + + if (ppre->di_wr_buf) { + if (di_pre_rdma_enable) + ppre->di_post_wr_buf = ppre->di_wr_buf; + else + ppre->di_post_wr_buf = NULL; + + ppre->di_wr_buf = NULL; + } + } + } + if (ppre->di_post_inp_buf && di_pre_rdma_enable) { +#ifdef DI_BUFFER_DEBUG + dim_print("%s: %s[%d] => recycle_list\n", __func__, + vframe_type_name[ppre->di_post_inp_buf->type], + ppre->di_post_inp_buf->index); +#endif + di_lock_irqfiq_save(irq_flag2); + queue_in(channel, ppre->di_post_inp_buf, QUEUE_RECYCLE); + ppre->di_post_inp_buf = NULL; + di_unlock_irqfiq_restore(irq_flag2); + } + if (ppre->di_inp_buf) { + if (!di_pre_rdma_enable) { +#ifdef DI_BUFFER_DEBUG + dim_print("%s: %s[%d] => recycle_list\n", __func__, + vframe_type_name[ppre->di_inp_buf->type], + ppre->di_inp_buf->index); +#endif + di_lock_irqfiq_save(irq_flag2); + queue_in(channel, ppre->di_inp_buf, QUEUE_RECYCLE); + ppre->di_inp_buf = NULL; + di_unlock_irqfiq_restore(irq_flag2); + } else { + ppre->di_post_inp_buf = ppre->di_inp_buf; + ppre->di_inp_buf = NULL; + } + } + dim_ddbg_mod_save(eDI_DBG_MOD_PRE_DONEE, channel, ppre->in_seq);/*dbg*/ + + dim_dbg_pre_cnt(channel, "d2"); +} + +static void recycle_vframe_type_pre(struct di_buf_s *di_buf, + unsigned int channel) +{ + ulong irq_flag2 = 0; + + di_lock_irqfiq_save(irq_flag2); + + queue_in(channel, di_buf, QUEUE_RECYCLE); + + di_unlock_irqfiq_restore(irq_flag2); +} + +/* + * add dummy buffer to pre ready queue + */ +static void add_dummy_vframe_type_pre(struct di_buf_s *src_buf, + unsigned int channel) +{ + struct di_buf_s *di_buf_tmp = NULL; + + if (!queue_empty(channel, QUEUE_LOCAL_FREE)) { + di_buf_tmp = get_di_buf_head(channel, QUEUE_LOCAL_FREE); + if (di_buf_tmp) { + queue_out(channel, di_buf_tmp); + di_buf_tmp->pre_ref_count = 0; + di_buf_tmp->post_ref_count = 0; + di_buf_tmp->post_proc_flag = 3; + di_buf_tmp->new_format_flag = 0; + if (!IS_ERR_OR_NULL(src_buf)) + memcpy(di_buf_tmp->vframe, src_buf->vframe, + sizeof(vframe_t)); + + di_que_in(channel, QUE_PRE_READY, di_buf_tmp); + #ifdef DI_BUFFER_DEBUG + dim_print("%s: dummy %s[%d] => pre_ready_list\n", + __func__, + vframe_type_name[di_buf_tmp->type], + di_buf_tmp->index); + #endif + } + } +} + +/* + * it depend on local buffer queue type is 2 + */ +static int peek_free_linked_buf(unsigned int channel) +{ + struct di_buf_s *p = NULL; + int itmp, p_index = -2; + + if (list_count(channel, QUEUE_LOCAL_FREE) < 2) + return -1; + + queue_for_each_entry(p, channel, QUEUE_LOCAL_FREE, list) { + if (abs(p->index - p_index) == 1) + return min(p->index, p_index); + p_index = p->index; + } + return -1; +} + +/* + * it depend on local buffer queue type is 2 + */ +static struct di_buf_s *get_free_linked_buf(int idx, unsigned int channel) +{ + struct di_buf_s *di_buf = NULL, *di_buf_linked = NULL; + int pool_idx = 0, di_buf_idx = 0; + struct queue_s *pqueue = get_queue(channel); + struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel); + + queue_t *q = &pqueue[QUEUE_LOCAL_FREE]; + + if (list_count(channel, QUEUE_LOCAL_FREE) < 2) + return NULL; + if (q->pool[idx] != 0 && q->pool[idx + 1] != 0) { + pool_idx = ((q->pool[idx] >> 8) & 0xff) - 1; + di_buf_idx = q->pool[idx] & 0xff; + if (pool_idx < VFRAME_TYPE_NUM) { + if (di_buf_idx < pbuf_pool[pool_idx].size) { + di_buf = &(pbuf_pool[pool_idx]. + di_buf_ptr[di_buf_idx]); + queue_out(channel, di_buf); + } + } + pool_idx = ((q->pool[idx + 1] >> 8) & 0xff) - 1; + di_buf_idx = q->pool[idx + 1] & 0xff; + if (pool_idx < VFRAME_TYPE_NUM) { + if (di_buf_idx < pbuf_pool[pool_idx].size) { + di_buf_linked = &(pbuf_pool[pool_idx]. + di_buf_ptr[di_buf_idx]); + queue_out(channel, di_buf_linked); + } + } + if (IS_ERR_OR_NULL(di_buf)) + return NULL; + di_buf->di_wr_linked_buf = di_buf_linked; + } + return di_buf; +} + +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC +static void pre_inp_canvas_config(struct vframe_s *vf) +{ + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(di_inp_idx[0], + &vf->canvas0_config[0]); + canvas_config_config(di_inp_idx[1], + &vf->canvas0_config[1]); + vf->canvas0Addr = (di_inp_idx[1] << 8) | (di_inp_idx[0]); + if (vf->plane_num == 2) { + vf->canvas0Addr |= (di_inp_idx[1] << 16); + } else if (vf->plane_num == 3) { + canvas_config_config(di_inp_idx[2], + &vf->canvas0_config[2]); + vf->canvas0Addr |= (di_inp_idx[2] << 16); + } + vf->canvas1Addr = vf->canvas0Addr; + } +} +#endif + +#if 0 +bool di_get_pre_hsc_down_en(void) +{ + return pre_hsc_down_en; +} +#endif +bool dbg_first_frame; /*debug */ +unsigned int dbg_first_cnt_pre; +unsigned int dbg_first_cnt_post; +#define DI_DBG_CNT (2) +void dim_dbg_pre_cnt(unsigned int channel, char *item) +{ + bool flgs = false; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (ppre->field_count_for_cont < DI_DBG_CNT) { + dbg_first_frame("%d:%s:%d\n", channel, item, + ppre->field_count_for_cont); + dbg_first_frame = true; + flgs = true; + dbg_first_cnt_pre = DI_DBG_CNT * 5; + dbg_first_cnt_post = DI_DBG_CNT * 4 + 1; + } else if (ppre->field_count_for_cont == DI_DBG_CNT) {/*don't use >=*/ + dbg_first_frame = false; + dbg_first_cnt_pre = 0; + dbg_first_cnt_post = 0; + } + + if ((dbg_first_frame) && !flgs && dbg_first_cnt_pre) { + dbg_first_frame("%d:n%s:%d\n", channel, item, + ppre->field_count_for_cont); + dbg_first_cnt_pre--; + } +} + +static void dbg_post_cnt(unsigned int ch, char *item) +{ + struct di_post_stru_s *ppost = get_post_stru(ch); + + if (dbg_first_cnt_post) { + dbg_first_frame("%d:%s:%d\n", ch, item, + ppost->frame_cnt); + dbg_first_cnt_post--; + } +} + +#if 0 +/*must been called when dim_pre_de_buf_config return true*/ +void pre_p_asi_set_next(unsigned int ch) +{ + struct di_pre_stru_s *ppre = get_pre_stru(ch); + + ppre->p_asi_next = ppre->di_inp_buf; +} +#endif + +unsigned char pre_p_asi_de_buf_config(unsigned int ch) +{ + struct di_pre_stru_s *ppre = get_pre_stru(ch); + +#if 0 + if (di_blocking || !dip_cma_st_is_ready(ch)) + return 0; + + if (di_que_list_count(ch, QUE_IN_FREE) < 1) + return 0; + + if (queue_empty(ch, QUEUE_LOCAL_FREE)) + return 0; +#endif + ppre->di_inp_buf = ppre->di_inp_buf_next; + ppre->di_inp_buf_next = NULL; + + if (!ppre->di_mem_buf_dup_p) {/* use n */ + ppre->di_mem_buf_dup_p = ppre->di_inp_buf; + } + + return 1; +} + +/*for first frame no need to ready buf*/ +bool dim_bypass_first_frame(unsigned int ch) +{ + struct di_buf_s *di_buf = NULL; + struct di_buf_s *di_buf_post = NULL; + struct vframe_s *vframe; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + struct vframe_s **pvframe_in = get_vframe_in(ch); + ulong irq_flag2 = 0; + + vframe = pw_vf_peek(ch); + + if (!vframe) + return false; + if (di_que_is_empty(ch, QUE_POST_FREE)) + return false; + + vframe = pw_vf_get(ch); + + di_buf = di_que_out_to_di_buf(ch, QUE_IN_FREE); + + if (dim_check_di_buf(di_buf, 10, ch)) + return 0; + + memcpy(di_buf->vframe, vframe, sizeof(struct vframe_s)); + di_buf->vframe->private_data = di_buf; + pvframe_in[di_buf->index] = vframe; + di_buf->seq = ppre->in_seq; + ppre->in_seq++; + + #if 0 + + if (vframe->type & VIDTYPE_COMPRESS) { /*?*/ + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight; + } + + di_que_in(ch, QUE_PRE_READY, di_buf); + #endif + + di_buf_post = di_que_out_to_di_buf(ch, QUE_POST_FREE); + memcpy(di_buf_post->vframe, vframe, sizeof(struct vframe_s)); + di_buf_post->vframe->private_data = di_buf_post; + di_lock_irqfiq_save(irq_flag2); + + di_que_in(ch, QUE_POST_READY, di_buf_post); + + di_unlock_irqfiq_restore(irq_flag2); + pw_vf_notify_receiver(ch, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + + PR_INF("%s:ok\n", __func__); + return true; +} + +unsigned char dim_pre_de_buf_config(unsigned int channel) +{ + struct di_buf_s *di_buf = NULL; + struct vframe_s *vframe; + int i, di_linked_buf_idx = -1; + unsigned char change_type = 0; + unsigned char change_type2 = 0; + bool bit10_pack_patch = false; + unsigned int width_roundup = 2; + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + int cfg_prog_proc = dimp_get(eDI_MP_prog_proc_config); + bool flg_1080i = false; + bool flg_480i = false; + + if (di_blocking || !dip_cma_st_is_ready(channel)) + return 0; + + if (di_que_list_count(channel, QUE_IN_FREE) < 1) + return 0; + + if ((di_que_list_count(channel, QUE_IN_FREE) < 2 && + (!ppre->di_inp_buf_next)) || + (queue_empty(channel, QUEUE_LOCAL_FREE))) + return 0; + + if (di_que_list_count(channel, QUE_PRE_READY) >= DI_PRE_READY_LIMIT) + return 0; + + if (dim_is_bypass(NULL, channel)) { + /* some provider has problem if receiver + * get all buffers of provider + */ + int in_buf_num = 0; + /*cur_lev = 0;*/ + dimp_set(eDI_MP_cur_lev, 0); + for (i = 0; i < MAX_IN_BUF_NUM; i++) + if (pvframe_in[i]) + in_buf_num++; + if (in_buf_num > BYPASS_GET_MAX_BUF_NUM +#ifdef DET3D + && (ppre->vframe_interleave_flag == 0) +#endif + ) + return 0; + + dimh_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + } else if (ppre->prog_proc_type == 2) { + di_linked_buf_idx = peek_free_linked_buf(channel); + if (di_linked_buf_idx == -1 && + !IS_ERR_OR_NULL(ppost->keep_buf)) { + recycle_keep_buffer(channel); + pr_info("%s: recycle keep buffer for peek null linked buf\n", + __func__); + return 0; + } + } + if (ppre->di_inp_buf_next) { + ppre->di_inp_buf = ppre->di_inp_buf_next; + ppre->di_inp_buf_next = NULL; +#ifdef DI_BUFFER_DEBUG + dim_print("%s: di_inp_buf_next %s[%d] => di_inp_buf\n", + __func__, + vframe_type_name[ppre->di_inp_buf->type], + ppre->di_inp_buf->index); +#endif + if (!ppre->di_mem_buf_dup_p) {/* use n */ + ppre->di_mem_buf_dup_p = ppre->di_inp_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: set di_mem_buf_dup_p to be di_inp_buf\n", + __func__); +#endif + } + } else { + /* check if source change */ + vframe = pw_vf_peek(channel); + + if (vframe && is_from_vdin(vframe)) { +#ifdef RUN_DI_PROCESS_IN_IRQ + ppre->vdin2nr = is_input2pre(channel); +#endif + } + + vframe = pw_vf_get(channel); + + if (!vframe) + return 0; + + dim_tr_ops.pre_get(vframe->omx_index); + didbg_vframe_in_copy(channel, vframe); + + if (vframe->type & VIDTYPE_COMPRESS) { + vframe->width = vframe->compWidth; + vframe->height = vframe->compHeight; + } + dim_print("DI:ch[%d] get %dth vf[0x%p] from frontend %u ms.\n", + channel, + ppre->in_seq, vframe, + jiffies_to_msecs(jiffies_64 - + vframe->ready_jiffies64)); + vframe->prog_proc_config + = (cfg_prog_proc & 0x20) >> 5; + + if (vframe->width > 10000 || vframe->height > 10000 || + hold_video || ppre->bad_frame_throw_count > 0) { + if (vframe->width > 10000 || vframe->height > 10000) + ppre->bad_frame_throw_count = 10; + ppre->bad_frame_throw_count--; + pw_vf_put(vframe, channel); + pw_vf_notify_provider( + channel, VFRAME_EVENT_RECEIVER_PUT, NULL); + return 0; + } + bit10_pack_patch = (is_meson_gxtvbb_cpu() || + is_meson_gxl_cpu() || + is_meson_gxm_cpu()); + width_roundup = bit10_pack_patch ? 16 : width_roundup; + if (dimp_get(eDI_MP_di_force_bit_mode) == 10) + dimp_set(eDI_MP_force_width, + roundup(vframe->width, width_roundup)); + else + dimp_set(eDI_MP_force_width, 0); + ppre->source_trans_fmt = vframe->trans_fmt; + ppre->left_right = ppre->left_right ? 0 : 1; + ppre->invert_flag = + (vframe->type & TB_DETECT_MASK) ? true : false; + vframe->type &= ~TB_DETECT_MASK; + + if ((((invert_top_bot & 0x2) != 0) || + ppre->invert_flag) && + (!is_progressive(vframe))) { + if ( + (vframe->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) { + vframe->type &= (~VIDTYPE_TYPEMASK); + vframe->type |= VIDTYPE_INTERLACE_BOTTOM; + } else { + vframe->type &= (~VIDTYPE_TYPEMASK); + vframe->type |= VIDTYPE_INTERLACE_TOP; + } + } + ppre->width_bk = vframe->width; + if (dimp_get(eDI_MP_force_width)) + vframe->width = dimp_get(eDI_MP_force_width); + if (dimp_get(eDI_MP_force_height)) + vframe->height = dimp_get(eDI_MP_force_height); + + /* backup frame motion info */ + vframe->combing_cur_lev = dimp_get(eDI_MP_cur_lev);/*cur_lev;*/ + + dim_print("%s: vf_get => 0x%p\n", __func__, vframe); + + di_buf = di_que_out_to_di_buf(channel, QUE_IN_FREE); + + if (dim_check_di_buf(di_buf, 10, channel)) + return 0; + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_VFRAME) + dim_dump_vframe(vframe); + +#ifdef SUPPORT_MPEG_TO_VDIN + if ( + (!is_from_vdin(vframe)) && + (vframe->sig_fmt == TVIN_SIG_FMT_NULL) && + mpeg2vdin_flag) { + struct vdin_arg_s vdin_arg; + struct vdin_v4l2_ops_s *vdin_ops = get_vdin_v4l2_ops(); + + vdin_arg.cmd = VDIN_CMD_GET_HISTGRAM; + vdin_arg.private = (unsigned int)vframe; + if (vdin_ops->tvin_vdin_func) + vdin_ops->tvin_vdin_func(0, &vdin_arg); + } +#endif + memcpy(di_buf->vframe, vframe, sizeof(vframe_t)); + dim_dbg_pre_cnt(channel, "cf1"); + di_buf->width_bk = ppre->width_bk; /*ary.sui 2019-04-23*/ + di_buf->vframe->private_data = di_buf; + pvframe_in[di_buf->index] = vframe; + di_buf->seq = ppre->in_seq; + ppre->in_seq++; + + pre_vinfo_set(channel, vframe); + change_type = is_source_change(vframe, channel); + #if 0 + if (!change_type) + change_type = is_vinfo_change(channel); + #endif + /* source change, when i mix p,force p as i*/ + if (change_type == 1 || (change_type == 2 && + ppre->cur_prog_flag == 1)) { + if (ppre->di_mem_buf_dup_p) { + /*avoid only 2 i field then p field*/ + if ( + (ppre->cur_prog_flag == 0) && + dimp_get(eDI_MP_use_2_interlace_buff)) + ppre->di_mem_buf_dup_p-> + post_proc_flag = -1; + ppre->di_mem_buf_dup_p->pre_ref_count = 0; + ppre->di_mem_buf_dup_p = NULL; + } + if (ppre->di_chan2_buf_dup_p) { + /*avoid only 1 i field then p field*/ + if ( + (ppre->cur_prog_flag == 0) && + dimp_get(eDI_MP_use_2_interlace_buff)) + ppre->di_chan2_buf_dup_p-> + post_proc_flag = -1; + ppre->di_chan2_buf_dup_p->pre_ref_count = + 0; + ppre->di_chan2_buf_dup_p = NULL; + } + #if 0 + /* channel change will occur between atv and dtv, + * that need mirror + */ + if (!IS_ERR_OR_NULL(di_post_stru.keep_buf)) { + if (di_post_stru.keep_buf->vframe + ->source_type != + di_buf->vframe->source_type) { + recycle_keep_buffer(); + pr_info("%s: source type changed recycle buffer!!!\n", + __func__); + } + } + #endif + pr_info( + "%s:ch[%d]:%ums %dth source change: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n", + __func__, + channel, + jiffies_to_msecs(jiffies_64), + ppre->in_seq, + ppre->cur_inp_type, + ppre->cur_width, + ppre->cur_height, + ppre->cur_source_type, + di_buf->vframe->type, + di_buf->vframe->width, + di_buf->vframe->height, + di_buf->vframe->source_type); + if (di_buf->type & VIDTYPE_COMPRESS) { + ppre->cur_width = + di_buf->vframe->compWidth; + ppre->cur_height = + di_buf->vframe->compHeight; + } else { + ppre->cur_width = di_buf->vframe->width; + ppre->cur_height = di_buf->vframe->height; + } + ppre->cur_prog_flag = + is_progressive(di_buf->vframe); + if (ppre->cur_prog_flag) { + if ((dimp_get(eDI_MP_use_2_interlace_buff)) && + !(cfg_prog_proc & 0x10)) + ppre->prog_proc_type = 2; + else + ppre->prog_proc_type + = cfg_prog_proc & 0x10; + } else { + ppre->prog_proc_type = 0; + } + ppre->cur_inp_type = di_buf->vframe->type; + ppre->cur_source_type = + di_buf->vframe->source_type; + ppre->cur_sig_fmt = di_buf->vframe->sig_fmt; + ppre->orientation = di_buf->vframe->video_angle; + ppre->source_change_flag = 1; + ppre->input_size_change_flag = true; +#ifdef SUPPORT_MPEG_TO_VDIN + if ((!is_from_vdin(vframe)) && + (vframe->sig_fmt == TVIN_SIG_FMT_NULL) && + (mpeg2vdin_en)) { + struct vdin_arg_s vdin_arg; + struct vdin_v4l2_ops_s *vdin_ops = + get_vdin_v4l2_ops(); + vdin_arg.cmd = VDIN_CMD_MPEGIN_START; + vdin_arg.h_active = ppre->cur_width; + vdin_arg.v_active = ppre->cur_height; + if (vdin_ops->tvin_vdin_func) + vdin_ops->tvin_vdin_func(0, &vdin_arg); + mpeg2vdin_flag = 1; + } +#endif + ppre->field_count_for_cont = 0; + } else if (ppre->cur_prog_flag == 0) { + /* check if top/bot interleaved */ + if (change_type == 2) + /* source is i interleaves p fields */ + ppre->force_interlace = true; + if ((ppre->cur_inp_type & + VIDTYPE_TYPEMASK) == (di_buf->vframe->type & + VIDTYPE_TYPEMASK)) { + if ((di_buf->vframe->type & + VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP) + same_field_top_count++; + else + same_field_bot_count++; + } + ppre->cur_inp_type = di_buf->vframe->type; + } else { + ppre->cur_inp_type = di_buf->vframe->type; + } + /*--------------------------*/ + if (!change_type) { + change_type2 = is_vinfo_change(channel); + if (change_type2) { + /*ppre->source_change_flag = 1;*/ + ppre->input_size_change_flag = true; + } + } + + /*--------------------------*/ + if (dim_is_bypass(di_buf->vframe, channel) + /*|| is_bypass_i_p()*/ + /*|| ((ppre->pre_ready_seq % 5)== 0)*/ + /*|| (ppre->pre_ready_seq == 10)*/ + ) { + /* bypass progressive */ + di_buf->seq = ppre->pre_ready_seq++; + di_buf->post_ref_count = 0; + /*cur_lev = 0;*/ + dimp_set(eDI_MP_cur_lev, 0); + if (ppre->source_change_flag) { + di_buf->new_format_flag = 1; + ppre->source_change_flag = 0; + } else { + di_buf->new_format_flag = 0; + } + + if (di_bypass_state_get(channel) == 0) { + if (ppre->di_mem_buf_dup_p) { + ppre->di_mem_buf_dup_p->pre_ref_count = 0; + ppre->di_mem_buf_dup_p = NULL; + } + if (ppre->di_chan2_buf_dup_p) { + ppre->di_chan2_buf_dup_p->pre_ref_count = 0; + ppre->di_chan2_buf_dup_p = NULL; + } + + if (ppre->di_wr_buf) { + ppre->di_wr_buf->pre_ref_count = 0; + ppre->di_wr_buf->post_ref_count = 0; + recycle_vframe_type_pre( + ppre->di_wr_buf, channel); +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: %s[%d] => recycle_list\n", + __func__, + vframe_type_name[ppre->di_wr_buf->type], + ppre->di_wr_buf->index); +#endif + ppre->di_wr_buf = NULL; + } + + di_buf->new_format_flag = 1; + di_bypass_state_set(channel, true);/*bypass_state:1;*/ + + dim_print( + "%s:bypass_state = 1, is_bypass() %d\n", + __func__, dim_is_bypass(NULL, channel)); +#ifdef DI_BUFFER_DEBUG + + dim_print( + "trick_mode %d bypass_all %d\n", + trick_mode, + di_cfgx_get(channel, eDI_CFGX_BYPASS_ALL)); +#endif + } + + top_bot_config(di_buf); + + di_que_in(channel, QUE_PRE_READY, di_buf); + /*if previous isn't bypass post_wr_buf not recycled */ + if (ppre->di_post_wr_buf && di_pre_rdma_enable) { + queue_in(channel, ppre->di_post_inp_buf, + QUEUE_RECYCLE); + ppre->di_post_inp_buf = NULL; + } + + if ((bypass_pre & 0x2) && !ppre->cur_prog_flag) + di_buf->post_proc_flag = -2; + else + di_buf->post_proc_flag = 0; + + dim_print("di:cfg:post_proc_flag=%d\n", + di_buf->post_proc_flag); +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: %s[%d] => pre_ready_list\n", __func__, + vframe_type_name[di_buf->type], di_buf->index); +#endif + return 0; + } else if (is_progressive(di_buf->vframe)) { + if (is_handle_prog_frame_as_interlace(vframe) && + is_progressive(vframe)) { + struct di_buf_s *di_buf_tmp = NULL; + + pvframe_in[di_buf->index] = NULL; + di_buf->vframe->type &= + (~VIDTYPE_TYPEMASK); + di_buf->vframe->type |= + VIDTYPE_INTERLACE_TOP; + di_buf->post_proc_flag = 0; + + di_buf_tmp = di_que_out_to_di_buf(channel, QUE_IN_FREE); + if (dim_check_di_buf(di_buf_tmp, 10, channel)) { + recycle_vframe_type_pre(di_buf, channel); + PR_ERR("DI:no free in_buffer for progressive skip.\n"); + return 0; + } + + di_buf_tmp->vframe->private_data = di_buf_tmp; + di_buf_tmp->seq = ppre->in_seq; + ppre->in_seq++; + pvframe_in[di_buf_tmp->index] = vframe; + memcpy(di_buf_tmp->vframe, vframe, + sizeof(vframe_t)); + ppre->di_inp_buf_next = di_buf_tmp; + di_buf_tmp->vframe->type &= + (~VIDTYPE_TYPEMASK); + di_buf_tmp->vframe->type |= + VIDTYPE_INTERLACE_BOTTOM; + di_buf_tmp->post_proc_flag = 0; + + ppre->di_inp_buf = di_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: %s[%d] => di_inp_buf; %s[%d] => di_inp_buf_next\n", + __func__, + vframe_type_name[di_buf->type], + di_buf->index, + vframe_type_name[di_buf_tmp->type], + di_buf_tmp->index); +#endif + if (!ppre->di_mem_buf_dup_p) { + ppre->di_mem_buf_dup_p = di_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: set di_mem_buf_dup_p to be di_inp_buf\n", + __func__); +#endif + } + } else { + di_buf->post_proc_flag = 0; + if ((cfg_prog_proc & 0x40) || + ppre->force_interlace) + di_buf->post_proc_flag = 1; + + ppre->di_inp_buf = di_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: %s[%d] => di_inp_buf\n", + __func__, + vframe_type_name[di_buf->type], + di_buf->index); +#endif + if (!ppre->di_mem_buf_dup_p) { + /* use n */ + ppre->di_mem_buf_dup_p = di_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: set di_mem_buf_dup_p to be di_inp_buf\n", + __func__); +#endif + } + } + } else { + /*********************************/ + if ((di_buf->vframe->width >= 1920) && + (di_buf->vframe->height >= 1080)) + flg_1080i = true; + else if ((di_buf->vframe->width == 720) && + (di_buf->vframe->height == 480)) + flg_480i = true; + + /*********************************/ + + if (!ppre->di_chan2_buf_dup_p) { + ppre->field_count_for_cont = 0; + /* ignore contp2rd and contprd */ + } + di_buf->post_proc_flag = 1; + ppre->di_inp_buf = di_buf; + dim_print("%s: %s[%d] => di_inp_buf\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index); + + if (!ppre->di_mem_buf_dup_p) {/* use n */ + ppre->di_mem_buf_dup_p = di_buf; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: set di_mem_buf_dup_p to be di_inp_buf\n", + __func__); +#endif + } + } + } + /*dim_dbg_pre_cnt(channel, "cfg");*/ + /* di_wr_buf */ + if (ppre->prog_proc_type == 2) { + di_linked_buf_idx = peek_free_linked_buf(channel); + if (di_linked_buf_idx != -1) + di_buf = get_free_linked_buf(di_linked_buf_idx, + channel); + else + di_buf = NULL; + if (!di_buf) { + /* recycle_vframe_type_pre(di_pre_stru.di_inp_buf); + *save for next process + */ + recycle_keep_buffer(channel); + ppre->di_inp_buf_next = ppre->di_inp_buf; + return 0; + } + di_buf->post_proc_flag = 0; + di_buf->di_wr_linked_buf->pre_ref_count = 0; + di_buf->di_wr_linked_buf->post_ref_count = 0; + di_buf->canvas_config_flag = 1; + } else { + di_buf = get_di_buf_head(channel, QUEUE_LOCAL_FREE); + if (dim_check_di_buf(di_buf, 11, channel)) { + /* recycle_keep_buffer(); + * pr_dbg("%s:recycle keep buffer\n", __func__); + */ + recycle_vframe_type_pre(ppre->di_inp_buf, channel); + return 0; + } + queue_out(channel, di_buf);/*QUEUE_LOCAL_FREE*/ + if (ppre->prog_proc_type & 0x10) + di_buf->canvas_config_flag = 1; + else + di_buf->canvas_config_flag = 2; + di_buf->di_wr_linked_buf = NULL; + } + + ppre->di_wr_buf = di_buf; + ppre->di_wr_buf->pre_ref_count = 1; + +#ifdef DI_BUFFER_DEBUG + dim_print("%s: %s[%d] => di_wr_buf\n", __func__, + vframe_type_name[di_buf->type], di_buf->index); + if (di_buf->di_wr_linked_buf) + dim_print("%s: linked %s[%d] => di_wr_buf\n", __func__, + vframe_type_name[di_buf->di_wr_linked_buf->type], + di_buf->di_wr_linked_buf->index); +#endif + if (ppre->cur_inp_type & VIDTYPE_COMPRESS) { + ppre->di_inp_buf->vframe->width = + ppre->di_inp_buf->vframe->compWidth; + ppre->di_inp_buf->vframe->height = + ppre->di_inp_buf->vframe->compHeight; + } + + memcpy(di_buf->vframe, + ppre->di_inp_buf->vframe, sizeof(vframe_t)); + di_buf->vframe->private_data = di_buf; + di_buf->vframe->canvas0Addr = di_buf->nr_canvas_idx; + di_buf->vframe->canvas1Addr = di_buf->nr_canvas_idx; + /* set vframe bit info */ + di_buf->vframe->bitdepth &= ~(BITDEPTH_YMASK); + di_buf->vframe->bitdepth &= ~(FULL_PACK_422_MODE); + if (de_devp->pps_enable && dimp_get(eDI_MP_pps_position)) { + if (dimp_get(eDI_MP_pps_dstw) != di_buf->vframe->width) { + di_buf->vframe->width = dimp_get(eDI_MP_pps_dstw); + ppre->width_bk = dimp_get(eDI_MP_pps_dstw); + } + if (dimp_get(eDI_MP_pps_dsth) != di_buf->vframe->height) + di_buf->vframe->height = dimp_get(eDI_MP_pps_dsth); + } else if (de_devp->h_sc_down_en) { + if (di_mp_uit_get(eDI_MP_pre_hsc_down_width) + != di_buf->vframe->width) { + pr_info("di: hscd %d to %d\n", di_buf->vframe->width, + di_mp_uit_get(eDI_MP_pre_hsc_down_width)); + di_buf->vframe->width = + di_mp_uit_get(eDI_MP_pre_hsc_down_width); + /*di_pre_stru.width_bk = pre_hsc_down_width;*/ + di_buf->width_bk = + di_mp_uit_get(eDI_MP_pre_hsc_down_width); + } + } + if (dimp_get(eDI_MP_di_force_bit_mode) == 10) { + di_buf->vframe->bitdepth |= (BITDEPTH_Y10); + if (dimp_get(eDI_MP_full_422_pack)) + di_buf->vframe->bitdepth |= (FULL_PACK_422_MODE); + } else { + di_buf->vframe->bitdepth |= (BITDEPTH_Y8); + } + di_buf->width_bk = ppre->width_bk; /*ary:2019-04-23*/ + if (ppre->prog_proc_type) { + di_buf->vframe->type = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD; + if (ppre->cur_inp_type & VIDTYPE_PRE_INTERLACE) + di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE; + } else { + if ( + ((ppre->di_inp_buf->vframe->type & + VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP)) + di_buf->vframe->type = VIDTYPE_INTERLACE_TOP | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD; + else + di_buf->vframe->type = VIDTYPE_INTERLACE_BOTTOM | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD; + /*add for vpp skip line ref*/ + if (di_bypass_state_get(channel) == 0) + di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE; + } + + if (is_bypass_post(channel)) { + if (dimp_get(eDI_MP_bypass_post_state) == 0) + ppre->source_change_flag = 1; + + dimp_set(eDI_MP_bypass_post_state, 1); + } else { + if (dimp_get(eDI_MP_bypass_post_state)) + ppre->source_change_flag = 1; + + dimp_set(eDI_MP_bypass_post_state, 0); + } + + if (ppre->di_inp_buf->post_proc_flag == 0) { + ppre->madi_enable = 0; + ppre->mcdi_enable = 0; + di_buf->post_proc_flag = 0; + dimh_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + } else if (dimp_get(eDI_MP_bypass_post_state)) { + ppre->madi_enable = 0; + ppre->mcdi_enable = 0; + di_buf->post_proc_flag = 0; + dimh_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + } else { + ppre->madi_enable = (dimp_get(eDI_MP_pre_enable_mask) & 1); + ppre->mcdi_enable = + ((dimp_get(eDI_MP_pre_enable_mask) >> 1) & 1); + di_buf->post_proc_flag = 1; + dimh_patch_post_update_mc_sw(DI_MC_SW_OTHER, + dimp_get(eDI_MP_mcpre_en));/*en*/ + } + if ((ppre->di_mem_buf_dup_p == ppre->di_wr_buf) || + (ppre->di_chan2_buf_dup_p == ppre->di_wr_buf)) { + pr_dbg("+++++++++++++++++++++++\n"); + if (recovery_flag == 0) + recovery_log_reason = 12; + + recovery_flag++; + return 0; + } + if (is_meson_tl1_cpu() && + ppre->comb_mode && + flg_1080i) { + ppre->combing_fix_en = false; + get_ops_mtn()->fix_tl1_1080i_patch_sel(ppre->comb_mode); + } else { + ppre->combing_fix_en = di_mpr(combing_fix_en); + } + + if (ppre->combing_fix_en) { + if (flg_1080i) + get_ops_mtn()->com_patch_pre_sw_set(1); + else if (flg_480i) + get_ops_mtn()->com_patch_pre_sw_set(2); + else + get_ops_mtn()->com_patch_pre_sw_set(0); + } + return 1; +} + +int dim_check_recycle_buf(unsigned int channel) +{ + struct di_buf_s *di_buf = NULL;/* , *ptmp; */ + int itmp; + int ret = 0; + struct vframe_s **pvframe_in = get_vframe_in(channel); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (di_blocking) + return ret; + queue_for_each_entry(di_buf, channel, QUEUE_RECYCLE, list) { + if ((di_buf->pre_ref_count == 0) && + (di_buf->post_ref_count <= 0)) { /*ary maybe <=*/ + if (di_buf->type == VFRAME_TYPE_IN) { + queue_out(channel, di_buf); + if (pvframe_in[di_buf->index]) { + pw_vf_put( + pvframe_in[di_buf->index], + channel); + pw_vf_notify_provider(channel, + VFRAME_EVENT_RECEIVER_PUT, + NULL); + dim_print( + "%sch[%d]vfpt(%d)0x%p,%ums\n", + __func__, channel, + ppre->recycle_seq, + pvframe_in[di_buf->index], + jiffies_to_msecs(jiffies_64 - + pvframe_in[di_buf->index]-> + ready_jiffies64)); + pvframe_in[di_buf->index] = NULL; + } + di_buf->invert_top_bot_flag = 0; + + di_que_in(channel, QUE_IN_FREE, di_buf); + ppre->recycle_seq++; + ret |= 1; + } else { + queue_out(channel, di_buf); + di_buf->invert_top_bot_flag = 0; + queue_in(channel, di_buf, QUEUE_LOCAL_FREE); + di_buf->post_ref_count = 0;/*ary maybe*/ + if (di_buf->di_wr_linked_buf) { + queue_in(channel, + di_buf->di_wr_linked_buf, + QUEUE_LOCAL_FREE); +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s: linked %s[%d]=>recycle_list\n", + __func__, + vframe_type_name[ + di_buf->di_wr_linked_buf->type], + di_buf->di_wr_linked_buf->index + ); +#endif + di_buf->di_wr_linked_buf = NULL; + } + ret |= 2; + } +#ifdef DI_BUFFER_DEBUG + dim_print("%s: recycle %s[%d]\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index); +#endif + } + } + return ret; +} + +#ifdef DET3D +static void set3d_view(enum tvin_trans_fmt trans_fmt, struct vframe_s *vf) +{ + struct vframe_view_s *left_eye, *right_eye; + + left_eye = &vf->left_eye; + right_eye = &vf->right_eye; + + switch (trans_fmt) { + case TVIN_TFMT_3D_DET_LR: + case TVIN_TFMT_3D_LRH_OLOR: + left_eye->start_x = 0; + left_eye->start_y = 0; + left_eye->width = vf->width >> 1; + left_eye->height = vf->height; + right_eye->start_x = vf->width >> 1; + right_eye->start_y = 0; + right_eye->width = vf->width >> 1; + right_eye->height = vf->height; + break; + case TVIN_TFMT_3D_DET_TB: + case TVIN_TFMT_3D_TB: + left_eye->start_x = 0; + left_eye->start_y = 0; + left_eye->width = vf->width; + left_eye->height = vf->height >> 1; + right_eye->start_x = 0; + right_eye->start_y = vf->height >> 1; + right_eye->width = vf->width; + right_eye->height = vf->height >> 1; + break; + case TVIN_TFMT_3D_DET_INTERLACE: + left_eye->start_x = 0; + left_eye->start_y = 0; + left_eye->width = vf->width; + left_eye->height = vf->height >> 1; + right_eye->start_x = 0; + right_eye->start_y = 0; + right_eye->width = vf->width; + right_eye->height = vf->height >> 1; + break; + case TVIN_TFMT_3D_DET_CHESSBOARD: +/*** + * LRLRLR LRLRLR + * LRLRLR or RLRLRL + * LRLRLR LRLRLR + * LRLRLR RLRLRL + */ + break; + default: /* 2D */ + left_eye->start_x = 0; + left_eye->start_y = 0; + left_eye->width = 0; + left_eye->height = 0; + right_eye->start_x = 0; + right_eye->start_y = 0; + right_eye->width = 0; + right_eye->height = 0; + break; + } +} + +/* + * static int get_3d_info(struct vframe_s *vf) + * { + * int ret = 0; + * + * vf->trans_fmt = det3d_fmt_detect(); + * pr_dbg("[det3d..]new 3d fmt: %d\n", vf->trans_fmt); + * + * vdin_set_view(vf->trans_fmt, vf); + * + * return ret; + * } + */ +static unsigned int det3d_frame_cnt = 50; +module_param_named(det3d_frame_cnt, det3d_frame_cnt, uint, 0644); +static void det3d_irq(unsigned int channel) +{ + unsigned int data32 = 0, likely_val = 0; + unsigned long frame_sum = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (!dimp_get(eDI_MP_det3d_en)) + return; + + data32 = get_ops_3d()->det3d_fmt_detect();/*det3d_fmt_detect();*/ + switch (data32) { + case TVIN_TFMT_3D_DET_LR: + case TVIN_TFMT_3D_LRH_OLOR: + ppre->det_lr++; + break; + case TVIN_TFMT_3D_DET_TB: + case TVIN_TFMT_3D_TB: + ppre->det_tp++; + break; + case TVIN_TFMT_3D_DET_INTERLACE: + ppre->det_la++; + break; + default: + ppre->det_null++; + break; + } + + if (det3d_mode != data32) { + det3d_mode = data32; + dim_print("[det3d..]new 3d fmt: %d\n", det3d_mode); + } + if (frame_count > 20) { + frame_sum = ppre->det_lr + ppre->det_tp + + ppre->det_la + + ppre->det_null; + if ((frame_count % det3d_frame_cnt) || (frame_sum > UINT_MAX)) + return; + likely_val = max3(ppre->det_lr, + ppre->det_tp, + ppre->det_la); + if (ppre->det_null >= likely_val) + det3d_mode = 0; + else if (likely_val == ppre->det_lr) + det3d_mode = TVIN_TFMT_3D_LRH_OLOR; + else if (likely_val == ppre->det_tp) + det3d_mode = TVIN_TFMT_3D_TB; + else + det3d_mode = TVIN_TFMT_3D_DET_INTERLACE; + ppre->det3d_trans_fmt = det3d_mode; + } else { + ppre->det3d_trans_fmt = 0; + } +} +#endif + +static unsigned int ro_mcdi_col_cfd[26]; +static void get_mcinfo_from_reg_in_irq(unsigned int channel) +{ + unsigned int i = 0, ncolcrefsum = 0, blkcount = 0, *reg = NULL; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + +/*get info for current field process by post*/ + ppre->di_wr_buf->curr_field_mcinfo.highvertfrqflg = + (Rd(MCDI_RO_HIGH_VERT_FRQ_FLG) & 0x1); +/* post:MCDI_MC_REL_GAIN_OFFST_0 */ + ppre->di_wr_buf->curr_field_mcinfo.motionparadoxflg = + (Rd(MCDI_RO_MOTION_PARADOX_FLG) & 0x1); +/* post:MCDI_MC_REL_GAIN_OFFST_0 */ + reg = ppre->di_wr_buf->curr_field_mcinfo.regs; + for (i = 0; i < 26; i++) { + ro_mcdi_col_cfd[i] = Rd(0x2fb0 + i); + ppre->di_wr_buf->curr_field_mcinfo.regs[i] = 0; + if (!dimp_get(eDI_MP_calc_mcinfo_en)) + *(reg + i) = ro_mcdi_col_cfd[i]; + } + if (dimp_get(eDI_MP_calc_mcinfo_en)) { + blkcount = (ppre->cur_width + 4) / 5; + for (i = 0; i < blkcount; i++) { + ncolcrefsum += + ((ro_mcdi_col_cfd[i / 32] >> (i % 32)) & 0x1); + if ( + ((ncolcrefsum + (blkcount >> 1)) << 8) / + blkcount > dimp_get(eDI_MP_colcfd_thr)) + for (i = 0; i < blkcount; i++) + *(reg + i / 32) += (1 << (i % 32)); + } + } +} + +static unsigned int bit_reverse(unsigned int val) +{ + unsigned int i = 0, res = 0; + + for (i = 0; i < 16; i++) { + res |= (((val & (1 << i)) >> i) << (31 - i)); + res |= (((val & (1 << (31 - i))) << i) >> (31 - i)); + } + return res; +} + +static void set_post_mcinfo(struct mcinfo_pre_s *curr_field_mcinfo) +{ + unsigned int i = 0, value = 0; + + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_REL_GAIN_OFFST_0, + curr_field_mcinfo->highvertfrqflg, 24, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_REL_GAIN_OFFST_0, + curr_field_mcinfo->motionparadoxflg, 25, 1); + for (i = 0; i < 26; i++) { + if (overturn) + value = bit_reverse(curr_field_mcinfo->regs[i]); + else + value = curr_field_mcinfo->regs[i]; + dim_VSYNC_WR_MPEG_REG(0x2f78 + i, value); + } +} + +static unsigned char intr_mode; + +irqreturn_t dim_irq(int irq, void *dev_instance) +{ + unsigned int channel; + struct di_pre_stru_s *ppre; + struct di_dev_s *de_devp = get_dim_de_devp(); + struct di_hpre_s *pre = get_hw_pre(); + +#ifndef CHECK_DI_DONE + unsigned int data32 = Rd(DI_INTR_CTRL); + unsigned int mask32 = (data32 >> 16) & 0x3ff; + unsigned int flag = 0; + + channel = pre->curr_ch; + ppre = pre->pres; + + data32 &= 0x3fffffff; + if ((data32 & 1) == 0 && dimp_get(eDI_MP_di_dbg_mask) & 8) + pr_info("irq[%d]pre|post=0 write done.\n", irq); + if (ppre->pre_de_busy) { + /* only one inetrrupr mask should be enable */ + if ((data32 & 2) && !(mask32 & 2)) { + dim_print("irq pre MTNWR ==ch[%d]\n", channel); + flag = 1; + } else if ((data32 & 1) && !(mask32 & 1)) { + dim_print("irq pre NRWR ==ch[%d]\n", channel); + flag = 1; + } else { + dim_print("irq pre DI IRQ 0x%x ==\n", data32); + flag = 0; + } + } + +#else + channel = pre->curr_ch; + ppre = pre->pres; +#endif + +#ifdef DET3D + if (dimp_get(eDI_MP_det3d_en)) { + if ((data32 & 0x100) && !(mask32 & 0x100) && flag) { + dim_DI_Wr(DI_INTR_CTRL, data32); + det3d_irq(channel); + } else { + goto end; + } + } else { + dim_DI_Wr(DI_INTR_CTRL, data32); + } +#else + if (flag) + dim_DI_Wr(DI_INTR_CTRL, + (data32 & 0xfffffffb) | (intr_mode << 30)); +#endif + + /*if (ppre->pre_de_busy == 0) {*/ + if (!di_pre_wait_irq_get()) { + PR_ERR("%s:ch[%d]:enter:reg[0x%x]= 0x%x,dtab[%d]\n", __func__, + channel, + DI_INTR_CTRL, + Rd(DI_INTR_CTRL), + pre->sdt_mode.op_crr); + return IRQ_HANDLED; + } + + if (flag) { + ppre->irq_time[0] = + (cur_to_msecs() - ppre->irq_time[0]); + + dim_tr_ops.pre(ppre->field_count_for_cont, ppre->irq_time[0]); + + /*add from valsi wang.feng*/ + dim_arb_sw(false); + dim_arb_sw(true); + if (dimp_get(eDI_MP_mcpre_en)) { + get_mcinfo_from_reg_in_irq(channel); + if ((is_meson_gxlx_cpu() && + ppre->field_count_for_cont >= 4) || + is_meson_txhd_cpu()) + dimh_mc_pre_mv_irq(); + dimh_calc_lmv_base_mcinfo((ppre->cur_height >> 1), + ppre->di_wr_buf->mcinfo_adr, + ppre->mcinfo_size); + } + get_ops_nr()->nr_process_in_irq(); + if ((data32 & 0x200) && de_devp->nrds_enable) + dim_nr_ds_irq(); + /* disable mif */ + dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en)); + + ppre->pre_de_busy = 0; + + if (get_init_flag(channel)) + /* pr_dbg("%s:up di sema\n", __func__); */ + task_send_ready(); + + pre->flg_int_done = 1; + } + + return IRQ_HANDLED; +} + +irqreturn_t dim_post_irq(int irq, void *dev_instance) +{ + unsigned int data32 = Rd(DI_INTR_CTRL); + unsigned int channel; + struct di_post_stru_s *ppost; + struct di_hpst_s *pst = get_hw_pst(); + + channel = pst->curr_ch; + ppost = pst->psts; + + data32 &= 0x3fffffff; + if ((data32 & 4) == 0) { + if (dimp_get(eDI_MP_di_dbg_mask) & 8) + pr_info("irq[%d]post write undone.\n", irq); + return IRQ_HANDLED; + } + + if (pst->state != eDI_PST_ST_WAIT_INT) { + PR_ERR("%s:ch[%d]:s[%d]\n", __func__, channel, pst->state); + ddbg_sw(eDI_LOG_TYPE_MOD, false); + return IRQ_HANDLED; + } + dim_ddbg_mod_save(eDI_DBG_MOD_POST_IRQB, pst->curr_ch, + ppost->frame_cnt); + dim_tr_ops.post_ir(0); + + if ((dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) && + (data32 & 0x4)) { + ppost->de_post_process_done = 1; + ppost->post_de_busy = 0; + ppost->irq_time = + (cur_to_msecs() - ppost->irq_time); + + dim_tr_ops.post(ppost->post_wr_cnt, ppost->irq_time); + + dim_DI_Wr(DI_INTR_CTRL, + (data32 & 0xffff0004) | (intr_mode << 30)); + /* disable wr back avoid pps sreay in g12a */ + dim_DI_Wr_reg_bits(DI_POST_CTRL, 0, 7, 1); + di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP); /*dbg a*/ + dim_print("irq p ch[%d]done\n", channel); + pst->flg_int_done = true; + } + dim_ddbg_mod_save(eDI_DBG_MOD_POST_IRQE, pst->curr_ch, + ppost->frame_cnt); + + if (get_init_flag(channel)) + task_send_ready(); + + return IRQ_HANDLED; +} + +/* + * di post process + */ +static void inc_post_ref_count(struct di_buf_s *di_buf) +{ + int i; /*debug only:*/ + + /* int post_blend_mode; */ + if (IS_ERR_OR_NULL(di_buf)) { + PR_ERR("%s:\n", __func__); + if (recovery_flag == 0) + recovery_log_reason = 13; + + recovery_flag++; + return; + } + + if (di_buf->di_buf_dup_p[1]) + di_buf->di_buf_dup_p[1]->post_ref_count++; + + if (di_buf->di_buf_dup_p[0]) + di_buf->di_buf_dup_p[0]->post_ref_count++; + + if (di_buf->di_buf_dup_p[2]) + di_buf->di_buf_dup_p[2]->post_ref_count++; + + /*debug only:*/ + for (i = 0; i < 3; i++) { + if (di_buf->di_buf_dup_p[i]) + dbg_post_ref("%s:pst_buf[%d],dup_p[%d],pref[%d]\n", + __func__, + di_buf->index, + i, + di_buf->di_buf_dup_p[i]->post_ref_count); + } +} + +static void dec_post_ref_count(struct di_buf_s *di_buf) +{ + int i; /*debug only:*/ + + if (IS_ERR_OR_NULL(di_buf)) { + PR_ERR("%s:\n", __func__); + if (recovery_flag == 0) + recovery_log_reason = 14; + + recovery_flag++; + return; + } + if (di_buf->pd_config.global_mode == PULL_DOWN_BUF1) + return; + if (di_buf->di_buf_dup_p[1]) + di_buf->di_buf_dup_p[1]->post_ref_count--; + + if (di_buf->di_buf_dup_p[0] && + di_buf->di_buf_dup_p[0]->post_proc_flag != -2) + di_buf->di_buf_dup_p[0]->post_ref_count--; + + if (di_buf->di_buf_dup_p[2]) + di_buf->di_buf_dup_p[2]->post_ref_count--; + + /*debug only:*/ + for (i = 0; i < 3; i++) { + if (di_buf->di_buf_dup_p[i]) + dbg_post_ref("%s:pst_buf[%d],dup_p[%d],pref[%d]\n", + __func__, + di_buf->index, + i, + di_buf->di_buf_dup_p[i]->post_ref_count); + } +} + +#if 0 /*no use*/ +static void vscale_skip_disable_post(struct di_buf_s *di_buf, + vframe_t *disp_vf, unsigned int channel) +{ + struct di_buf_s *di_buf_i = NULL; + int canvas_height = di_buf->di_buf[0]->canvas_height; + struct di_post_stru_s *ppost = get_post_stru(channel); + + if (di_vscale_skip_enable & 0x2) {/* drop the bottom field */ + if ((di_buf->di_buf_dup_p[0]) && (di_buf->di_buf_dup_p[1])) + di_buf_i = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_TOP ? di_buf->di_buf_dup_p[1] + : di_buf->di_buf_dup_p[0]; + else + di_buf_i = di_buf->di_buf[0]; + } else { + if ((di_buf->di_buf[0]->post_proc_flag > 0) && + (di_buf->di_buf_dup_p[1])) + di_buf_i = di_buf->di_buf_dup_p[1]; + else + di_buf_i = di_buf->di_buf[0]; + } + disp_vf->type = di_buf_i->vframe->type; + /* pr_dbg("%s (%x %x) (%x %x)\n", __func__, + * disp_vf, disp_vf->type, di_buf_i->vframe, + * di_buf_i->vframe->type); + */ + disp_vf->width = di_buf_i->vframe->width; + disp_vf->height = di_buf_i->vframe->height; + disp_vf->duration = di_buf_i->vframe->duration; + disp_vf->pts = di_buf_i->vframe->pts; + disp_vf->flag = di_buf_i->vframe->flag; + disp_vf->canvas0Addr = di_post_idx[ppost->canvas_id][0]; + disp_vf->canvas1Addr = di_post_idx[ppost->canvas_id][0]; + canvas_config( + di_post_idx[ppost->canvas_id][0], + di_buf_i->nr_adr, di_buf_i->canvas_width[NR_CANVAS], + canvas_height, 0, 0); + dimh_disable_post_deinterlace_2(); + ppost->vscale_skip_flag = true; +} +#endif + +/*early_process_fun*/ +static int early_NONE(void) +{ + return 0; +} + +int dim_do_post_wr_fun(void *arg, vframe_t *disp_vf) +{ + #if 0 + struct di_post_stru_s *ppost; + int i; + + for (i = 0; i < DI_CHANNEL_NUB; i++) { + ppost = get_post_stru(i); + + ppost->toggle_flag = true; + } + return 1; + #else + return early_NONE(); + #endif +} + +static int de_post_disable_fun(void *arg, vframe_t *disp_vf) +{ + #if 0 + struct di_buf_s *di_buf = (struct di_buf_s *)arg; + unsigned int channel = di_buf->channel; + struct di_post_stru_s *ppost = get_post_stru(channel); + + ppost->vscale_skip_flag = false; + ppost->toggle_flag = true; + + PR_ERR("%s------------------------------\n", __func__); + + process_vscale_skip(di_buf, disp_vf, channel); +/* for atv static image flickering */ + if (di_buf->process_fun_index == PROCESS_FUN_NULL) + dimh_disable_post_deinterlace_2(); + + return 1; +/* called for new_format_flag, make + * video set video_property_changed + */ + #else + return early_NONE(); + #endif +} + +static int do_nothing_fun(void *arg, vframe_t *disp_vf) +{ + #if 0 + struct di_buf_s *di_buf = (struct di_buf_s *)arg; + unsigned int channel = di_buf->channel; + struct di_post_stru_s *ppost = get_post_stru(channel); + + ppost->vscale_skip_flag = false; + ppost->toggle_flag = true; + + PR_ERR("%s------------------------------\n", __func__); + + process_vscale_skip(di_buf, disp_vf, channel); + + if (di_buf->process_fun_index == PROCESS_FUN_NULL) { + if (Rd(DI_IF1_GEN_REG) & 0x1 || Rd(DI_POST_CTRL) & 0xf) + dimh_disable_post_deinterlace_2(); + /*if(di_buf->pulldown_mode == PULL_DOWN_EI && Rd(DI_IF1_GEN_REG)&0x1) + * dim_VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, 0x3 << 30); + */ + } + return 0; + #else + return early_NONE(); + #endif +} + +static int do_pre_only_fun(void *arg, vframe_t *disp_vf) +{ + #if 0 + unsigned int channel; + struct di_post_stru_s *ppost; + + PR_ERR("%s------------------------------\n", __func__); +#ifdef DI_USE_FIXED_CANVAS_IDX + if (arg) { + struct di_buf_s *di_buf = (struct di_buf_s *)arg; + vframe_t *vf = di_buf->vframe; + int width, canvas_height; + + channel = di_buf->channel; + ppost = get_post_stru(channel); + + ppost->vscale_skip_flag = false; + ppost->toggle_flag = true; + + if (!vf || !di_buf->di_buf[0]) { + dim_print("error:%s,NULL point!!\n", __func__); + return 0; + } + width = di_buf->di_buf[0]->canvas_width[NR_CANVAS]; + /* linked two interlace buffer should double height*/ + if (di_buf->di_buf[0]->di_wr_linked_buf) + canvas_height = + (di_buf->di_buf[0]->canvas_height << 1); + else + canvas_height = + di_buf->di_buf[0]->canvas_height; +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + ppost->canvas_id = ppost->next_canvas_id; + } else { + ppost->canvas_id = 0; + ppost->next_canvas_id = 1; + if (post_wr_en && post_wr_support) + ppost->canvas_id = ppost->next_canvas_id; + } +#endif + + canvas_config( + di_post_idx[ppost->canvas_id][0], + di_buf->di_buf[0]->nr_adr, + di_buf->di_buf[0]->canvas_width[NR_CANVAS], + canvas_height, 0, 0); + + vf->canvas0Addr = + di_post_idx[ppost->canvas_id][0]; + vf->canvas1Addr = + di_post_idx[ppost->canvas_id][0]; +#ifdef DET3D + if (ppre->vframe_interleave_flag && di_buf->di_buf[1]) { + canvas_config( + di_post_idx[ppost->canvas_id][1], + di_buf->di_buf[1]->nr_adr, + di_buf->di_buf[1]->canvas_width[NR_CANVAS], + canvas_height, 0, 0); + vf->canvas1Addr = + di_post_idx[ppost->canvas_id][1]; + vf->duration <<= 1; + } +#endif + ppost->next_canvas_id = ppost->canvas_id ? 0 : 1; + + if (di_buf->process_fun_index == PROCESS_FUN_NULL) { + if (Rd(DI_IF1_GEN_REG) & 0x1 || + Rd(DI_POST_CTRL) & 0x10f) + dimh_disable_post_deinterlace_2(); + } + } +#endif + + return 0; +#else + return early_NONE(); +#endif +} + +static void get_vscale_skip_count(unsigned int par) +{ + /*di_vscale_skip_count_real = (par >> 24) & 0xff;*/ + dimp_set(eDI_MP_di_vscale_skip_count_real, + (par >> 24) & 0xff); +} + +#define get_vpp_reg_update_flag(par) (((par) >> 16) & 0x1) + +static unsigned int pldn_dly = 1; + +int dim_post_process(void *arg, unsigned int zoom_start_x_lines, + unsigned int zoom_end_x_lines, + unsigned int zoom_start_y_lines, + unsigned int zoom_end_y_lines, + vframe_t *disp_vf) +{ + struct di_buf_s *di_buf = (struct di_buf_s *)arg; + struct di_buf_s *di_pldn_buf = NULL; + unsigned int di_width, di_height, di_start_x, di_end_x, mv_offset; + unsigned int di_start_y, di_end_y, hold_line; + unsigned int post_blend_en = 0, post_blend_mode = 0, + blend_mtn_en = 0, ei_en = 0, post_field_num = 0; + int di_vpp_en, di_ddr_en; + unsigned char mc_pre_flag = 0; + bool invert_mv = false; + static int post_index = -1; + unsigned char tmp_idx = 0; + struct di_dev_s *de_devp = get_dim_de_devp(); + struct di_hpst_s *pst = get_hw_pst(); + + unsigned char channel = pst->curr_ch; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + + dimp_inc(eDI_MP_post_cnt); + if (ppost->vscale_skip_flag) + return 0; + + get_vscale_skip_count(zoom_start_x_lines); + + if (IS_ERR_OR_NULL(di_buf)) + return 0; + else if (IS_ERR_OR_NULL(di_buf->di_buf_dup_p[0])) + return 0; + + hold_line = dimp_get(eDI_MP_post_hold_line); + di_pldn_buf = di_buf->di_buf_dup_p[pldn_dly]; + + if (di_que_is_in_que(channel, QUE_POST_FREE, di_buf) && + post_index != di_buf->index) { + post_index = di_buf->index; + PR_ERR("%s:post_buf[%d] is in post free list.\n", + __func__, di_buf->index); + return 0; + } + hpst_dbg_mem_pd_trig(0); + + if (ppost->toggle_flag && di_buf->di_buf_dup_p[1]) + top_bot_config(di_buf->di_buf_dup_p[1]); + + ppost->toggle_flag = false; + + ppost->cur_disp_index = di_buf->index; + + if (get_vpp_reg_update_flag(zoom_start_x_lines) || + dimp_get(eDI_MP_post_refresh)) + ppost->update_post_reg_flag = 1; + + zoom_start_x_lines = zoom_start_x_lines & 0xffff; + zoom_end_x_lines = zoom_end_x_lines & 0xffff; + zoom_start_y_lines = zoom_start_y_lines & 0xffff; + zoom_end_y_lines = zoom_end_y_lines & 0xffff; + + if (!get_init_flag(channel) && IS_ERR_OR_NULL(ppost->keep_buf)) { + PR_ERR("%s 2:\n", __func__); + return 0; + } + if (di_buf->vframe) + dim_tr_ops.post_set(di_buf->vframe->omx_index); + else + return 0; + /*dbg*/ + dim_ddbg_mod_save(eDI_DBG_MOD_POST_SETB, channel, ppost->frame_cnt); + dbg_post_cnt(channel, "ps1"); + di_start_x = zoom_start_x_lines; + di_end_x = zoom_end_x_lines; + di_width = di_end_x - di_start_x + 1; + di_start_y = zoom_start_y_lines; + di_end_y = zoom_end_y_lines; + di_height = di_end_y - di_start_y + 1; + di_height + = di_height / (dimp_get(eDI_MP_di_vscale_skip_count_real) + 1); + /* make sure the height is even number */ + if (di_height % 2) { + /*for skip mode,post only half line-1*/ + if (!dimp_get(eDI_MP_post_wr_en) && + ((di_height > 150) && + (di_height < 1080)) && + dimp_get(eDI_MP_di_vscale_skip_count_real)) + di_height = di_height - 3; + else + di_height++; + } + #if 0 + dimh_post_ctrl(DI_HW_POST_CTRL_INIT, + (post_wr_en && post_wr_support)); + #endif + + if (Rd(DI_POST_SIZE) != ((di_width - 1) | ((di_height - 1) << 16)) || + ppost->buf_type != di_buf->di_buf_dup_p[0]->type || + (ppost->di_buf0_mif.luma_x_start0 != di_start_x) || + (ppost->di_buf0_mif.luma_y_start0 != di_start_y / 2)) { + dim_ddbg_mod_save(eDI_DBG_MOD_POST_RESIZE, channel, + ppost->frame_cnt);/*dbg*/ + ppost->buf_type = di_buf->di_buf_dup_p[0]->type; + + dimh_initial_di_post_2(di_width, di_height, + hold_line, + (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support))); + + if (!di_buf->di_buf_dup_p[0]->vframe) { + PR_ERR("%s 3:\n", __func__); + return 0; + } + /* bit mode config */ + if (di_buf->vframe->bitdepth & BITDEPTH_Y10) { + if (di_buf->vframe->type & VIDTYPE_VIU_444) { + ppost->di_buf0_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 2; + ppost->di_buf1_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 2; + ppost->di_buf2_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 2; + ppost->di_diwr_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 2; + + } else { + ppost->di_buf0_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 1; + ppost->di_buf1_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 1; + ppost->di_buf2_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 1; + ppost->di_diwr_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE) ? 3 : 1; + } + } else { + ppost->di_buf0_mif.bit_mode = 0; + ppost->di_buf1_mif.bit_mode = 0; + ppost->di_buf2_mif.bit_mode = 0; + ppost->di_diwr_mif.bit_mode = 0; + } + if (di_buf->vframe->type & VIDTYPE_VIU_444) { + ppost->di_buf0_mif.video_mode = 1; + ppost->di_buf1_mif.video_mode = 1; + ppost->di_buf2_mif.video_mode = 1; + } else { + ppost->di_buf0_mif.video_mode = 0; + ppost->di_buf1_mif.video_mode = 0; + ppost->di_buf2_mif.video_mode = 0; + } + if (ppost->buf_type == VFRAME_TYPE_IN && + !(di_buf->di_buf_dup_p[0]->vframe->type & + VIDTYPE_VIU_FIELD)) { + if (di_buf->vframe->type & VIDTYPE_VIU_NV21) { + ppost->di_buf0_mif.set_separate_en = 1; + ppost->di_buf1_mif.set_separate_en = 1; + ppost->di_buf2_mif.set_separate_en = 1; + } else { + ppost->di_buf0_mif.set_separate_en = 0; + ppost->di_buf1_mif.set_separate_en = 0; + ppost->di_buf2_mif.set_separate_en = 0; + } + ppost->di_buf0_mif.luma_y_start0 = di_start_y; + ppost->di_buf0_mif.luma_y_end0 = di_end_y; + } else { /* from vdin or local vframe process by di pre */ + ppost->di_buf0_mif.set_separate_en = 0; + ppost->di_buf0_mif.luma_y_start0 = + di_start_y >> 1; + ppost->di_buf0_mif.luma_y_end0 = di_end_y >> 1; + ppost->di_buf1_mif.set_separate_en = 0; + ppost->di_buf1_mif.luma_y_start0 = + di_start_y >> 1; + ppost->di_buf1_mif.luma_y_end0 = di_end_y >> 1; + ppost->di_buf2_mif.set_separate_en = 0; + ppost->di_buf2_mif.luma_y_end0 = di_end_y >> 1; + ppost->di_buf2_mif.luma_y_start0 = + di_start_y >> 1; + } + ppost->di_buf0_mif.luma_x_start0 = di_start_x; + ppost->di_buf0_mif.luma_x_end0 = di_end_x; + ppost->di_buf1_mif.luma_x_start0 = di_start_x; + ppost->di_buf1_mif.luma_x_end0 = di_end_x; + ppost->di_buf2_mif.luma_x_start0 = di_start_x; + ppost->di_buf2_mif.luma_x_end0 = di_end_x; + + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) { + if (de_devp->pps_enable && + dimp_get(eDI_MP_pps_position) == 0) { + dim_pps_config(0, di_width, di_height, + dimp_get(eDI_MP_pps_dstw), + dimp_get(eDI_MP_pps_dsth)); + ppost->di_diwr_mif.start_x = 0; + ppost->di_diwr_mif.end_x + = dimp_get(eDI_MP_pps_dstw) - 1; + ppost->di_diwr_mif.start_y = 0; + ppost->di_diwr_mif.end_y + = dimp_get(eDI_MP_pps_dsth) - 1; + } else { + ppost->di_diwr_mif.start_x = di_start_x; + ppost->di_diwr_mif.end_x = di_end_x; + ppost->di_diwr_mif.start_y = di_start_y; + ppost->di_diwr_mif.end_y = di_end_y; + } + } + + ppost->di_mtnprd_mif.start_x = di_start_x; + ppost->di_mtnprd_mif.end_x = di_end_x; + ppost->di_mtnprd_mif.start_y = di_start_y >> 1; + ppost->di_mtnprd_mif.end_y = di_end_y >> 1; + if (dimp_get(eDI_MP_mcpre_en)) { + ppost->di_mcvecrd_mif.start_x = di_start_x / 5; + mv_offset = (di_start_x % 5) ? (5 - di_start_x % 5) : 0; + ppost->di_mcvecrd_mif.vecrd_offset = + overturn ? (di_end_x + 1) % 5 : mv_offset; + ppost->di_mcvecrd_mif.start_y = + (di_start_y >> 1); + ppost->di_mcvecrd_mif.size_x = + (di_end_x + 1 + 4) / 5 - 1 - di_start_x / 5; + ppost->di_mcvecrd_mif.end_y = + (di_end_y >> 1); + } + ppost->update_post_reg_flag = 1; + /* if height decrease, mtn will not enough */ + if (di_buf->pd_config.global_mode != PULL_DOWN_BUF1 && + !dimp_get(eDI_MP_post_wr_en)) + di_buf->pd_config.global_mode = PULL_DOWN_EI; + } + +#ifdef DI_USE_FIXED_CANVAS_IDX +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA + if (is_vsync_rdma_enable()) { + ppost->canvas_id = ppost->next_canvas_id; + } else { + ppost->canvas_id = 0; + ppost->next_canvas_id = 1; + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) + ppost->canvas_id = + ppost->next_canvas_id; + } +#endif + /*post_blend = di_buf->pd_config.global_mode;*/ + dimp_set(eDI_MP_post_blend, di_buf->pd_config.global_mode); + dim_print("%s:ch[%d]\n", __func__, channel); + switch (dimp_get(eDI_MP_post_blend)) { + case PULL_DOWN_BLEND_0: + case PULL_DOWN_NORMAL: + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_post_idx[ppost->canvas_id][0], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[2], -1, + di_post_idx[ppost->canvas_id][2]); + config_canvas_idx( + di_buf->di_buf_dup_p[0], + di_post_idx[ppost->canvas_id][1], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[2], + di_post_idx[ppost->canvas_id][3], -1); + if (dimp_get(eDI_MP_mcpre_en)) + config_mcvec_canvas_idx( + di_buf->di_buf_dup_p[2], + di_post_idx[ppost->canvas_id][4]); + break; + case PULL_DOWN_BLEND_2: + case PULL_DOWN_NORMAL_2: + config_canvas_idx( + di_buf->di_buf_dup_p[0], + di_post_idx[ppost->canvas_id][3], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_post_idx[ppost->canvas_id][0], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[2], -1, + di_post_idx[ppost->canvas_id][2]); + config_canvas_idx( + di_buf->di_buf_dup_p[2], + di_post_idx[ppost->canvas_id][1], -1); + if (dimp_get(eDI_MP_mcpre_en)) + config_mcvec_canvas_idx( + di_buf->di_buf_dup_p[2], + di_post_idx[ppost->canvas_id][4]); + break; + case PULL_DOWN_MTN: + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_post_idx[ppost->canvas_id][0], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[2], -1, + di_post_idx[ppost->canvas_id][2]); + config_canvas_idx( + di_buf->di_buf_dup_p[0], + di_post_idx[ppost->canvas_id][1], -1); + break; + case PULL_DOWN_BUF1:/* wave with buf1 */ + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_post_idx[ppost->canvas_id][0], -1); + config_canvas_idx( + di_buf->di_buf_dup_p[1], -1, + di_post_idx[ppost->canvas_id][2]); + config_canvas_idx( + di_buf->di_buf_dup_p[0], + di_post_idx[ppost->canvas_id][1], -1); + break; + case PULL_DOWN_EI: + if (di_buf->di_buf_dup_p[1]) + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_post_idx[ppost->canvas_id][0], -1); + break; + default: + break; + } + ppost->next_canvas_id = ppost->canvas_id ? 0 : 1; +#endif + if (!di_buf->di_buf_dup_p[1]) { + PR_ERR("%s 4:\n", __func__); + return 0; + } + if (!di_buf->di_buf_dup_p[1]->vframe || + !di_buf->di_buf_dup_p[0]->vframe) { + PR_ERR("%s 5:\n", __func__); + return 0; + } + + if (is_meson_txl_cpu() && overturn && di_buf->di_buf_dup_p[2]) { + /*sync from kernel 3.14 txl*/ + if (dimp_get(eDI_MP_post_blend) == PULL_DOWN_BLEND_2) + dimp_set(eDI_MP_post_blend, PULL_DOWN_BLEND_0); + else if (dimp_get(eDI_MP_post_blend) == PULL_DOWN_BLEND_0) + dimp_set(eDI_MP_post_blend, PULL_DOWN_BLEND_2); + } + + switch (dimp_get(eDI_MP_post_blend)) { + case PULL_DOWN_BLEND_0: + case PULL_DOWN_NORMAL: + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + ppost->di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + ppost->di_buf1_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[0]->nr_canvas_idx; + ppost->di_buf2_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[2]->nr_canvas_idx; + ppost->di_mtnprd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mtn_canvas_idx; + /*mc_pre_flag = is_meson_txl_cpu()?2:(overturn?0:1);*/ + if (is_meson_txl_cpu() && overturn) { + /* swap if1&if2 mean negation of mv for normal di*/ + tmp_idx = ppost->di_buf1_mif.canvas0_addr0; + ppost->di_buf1_mif.canvas0_addr0 = + ppost->di_buf2_mif.canvas0_addr0; + ppost->di_buf2_mif.canvas0_addr0 = tmp_idx; + } + mc_pre_flag = overturn ? 0 : 1; + if (di_buf->pd_config.global_mode == PULL_DOWN_NORMAL) { + post_blend_mode = 3; + /*if pulldown, mcdi_mcpreflag is 1,*/ + /*it means use previous field for MC*/ + /*else not pulldown,mcdi_mcpreflag is 2*/ + /*it means use forward & previous field for MC*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + mc_pre_flag = 2; + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + mc_pre_flag = 1; + post_blend_mode = 1; + } + if (is_meson_txl_cpu() && overturn) + mc_pre_flag = 1; + + if (dimp_get(eDI_MP_mcpre_en)) { + ppost->di_mcvecrd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; + } + blend_mtn_en = 1; + ei_en = 1; + dimp_set(eDI_MP_post_ei, 1); + post_blend_en = 1; + break; + case PULL_DOWN_BLEND_2: + case PULL_DOWN_NORMAL_2: + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + ppost->di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + ppost->di_buf1_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[2]->nr_canvas_idx; + ppost->di_buf2_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[0]->nr_canvas_idx; + ppost->di_mtnprd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mtn_canvas_idx; + if (is_meson_txl_cpu() && overturn) { + ppost->di_buf1_mif.canvas0_addr0 = + ppost->di_buf2_mif.canvas0_addr0; + } + if (dimp_get(eDI_MP_mcpre_en)) { + ppost->di_mcvecrd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; + mc_pre_flag = is_meson_txl_cpu() ? 0 : + (overturn ? 1 : 0); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) + invert_mv = true; + else if (!overturn) + ppost->di_buf2_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[2]->nr_canvas_idx; + } + if (di_buf->pd_config.global_mode == PULL_DOWN_NORMAL_2) { + post_blend_mode = 3; + /*if pulldown, mcdi_mcpreflag is 1,*/ + /*it means use previous field for MC*/ + /*else not pulldown,mcdi_mcpreflag is 2*/ + /*it means use forward & previous field for MC*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + mc_pre_flag = 2; + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + mc_pre_flag = 1; + post_blend_mode = 1; + } + blend_mtn_en = 1; + ei_en = 1; + dimp_set(eDI_MP_post_ei, 1); + post_blend_en = 1; + break; + case PULL_DOWN_MTN: + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + ppost->di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + ppost->di_buf1_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[0]->nr_canvas_idx; + ppost->di_mtnprd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mtn_canvas_idx; + post_blend_mode = 0; + blend_mtn_en = 1; + ei_en = 1; + dimp_set(eDI_MP_post_ei, 1); + post_blend_en = 1; + break; + case PULL_DOWN_BUF1: + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + ppost->di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + ppost->di_mtnprd_mif.canvas_num = + di_buf->di_buf_dup_p[1]->mtn_canvas_idx; + ppost->di_buf1_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[0]->nr_canvas_idx; + post_blend_mode = 1; + blend_mtn_en = 0; + ei_en = 0; + dimp_set(eDI_MP_post_ei, 0); + post_blend_en = 0; + break; + case PULL_DOWN_EI: + if (di_buf->di_buf_dup_p[1]) { + ppost->di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + } else { + post_field_num = + (di_buf->di_buf_dup_p[0]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + ppost->di_buf0_mif.src_field_mode + = post_field_num; + } + post_blend_mode = 2; + blend_mtn_en = 0; + ei_en = 1; + dimp_set(eDI_MP_post_ei, 1); + post_blend_en = 0; + break; + default: + break; + } + + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) { + config_canvas_idx(di_buf, + di_post_idx[ppost->canvas_id][5], -1); + ppost->di_diwr_mif.canvas_num = di_buf->nr_canvas_idx; + di_vpp_en = 0; + di_ddr_en = 1; + } else { + di_vpp_en = 1; + di_ddr_en = 0; + } + + /* if post size < MIN_POST_WIDTH, force ei */ + if ((di_width < MIN_BLEND_WIDTH) && + (di_buf->pd_config.global_mode == PULL_DOWN_BLEND_0 || + di_buf->pd_config.global_mode == PULL_DOWN_BLEND_2 || + di_buf->pd_config.global_mode == PULL_DOWN_NORMAL + )) { + post_blend_mode = 1; + blend_mtn_en = 0; + ei_en = 0; + dimp_set(eDI_MP_post_ei, 0); + post_blend_en = 0; + } + + if (dimp_get(eDI_MP_mcpre_en)) + ppost->di_mcvecrd_mif.blend_en = post_blend_en; + invert_mv = overturn ? (!invert_mv) : invert_mv; + if (ppost->update_post_reg_flag) { + dimh_enable_di_post_2( + &ppost->di_buf0_mif, + &ppost->di_buf1_mif, + &ppost->di_buf2_mif, + &ppost->di_diwr_mif, + &ppost->di_mtnprd_mif, + ei_en, /* ei enable */ + post_blend_en, /* blend enable */ + blend_mtn_en, /* blend mtn enable */ + post_blend_mode, /* blend mode. */ + di_vpp_en, /* di_vpp_en. */ + di_ddr_en, /* di_ddr_en. */ + post_field_num, /* 1 bottom generate top */ + hold_line, + dimp_get(eDI_MP_post_urgent), + (invert_mv ? 1 : 0), + dimp_get(eDI_MP_di_vscale_skip_count_real) + ); + if (dimp_get(eDI_MP_mcpre_en)) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dimh_enable_mc_di_post_g12( + &ppost->di_mcvecrd_mif, + dimp_get(eDI_MP_post_urgent), + overturn, (invert_mv ? 1 : 0)); + else + dimh_enable_mc_di_post( + &ppost->di_mcvecrd_mif, + dimp_get(eDI_MP_post_urgent), + overturn, (invert_mv ? 1 : 0)); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + } + } else { + dimh_post_switch_buffer( + &ppost->di_buf0_mif, + &ppost->di_buf1_mif, + &ppost->di_buf2_mif, + &ppost->di_diwr_mif, + &ppost->di_mtnprd_mif, + &ppost->di_mcvecrd_mif, + ei_en, /* ei enable */ + post_blend_en, /* blend enable */ + blend_mtn_en, /* blend mtn enable */ + post_blend_mode, /* blend mode. */ + di_vpp_en, /* di_vpp_en. */ + di_ddr_en, /* di_ddr_en. */ + post_field_num, /* 1 bottom generate top */ + hold_line, + dimp_get(eDI_MP_post_urgent), + (invert_mv ? 1 : 0), + dimp_get(eDI_MP_pulldown_enable), + dimp_get(eDI_MP_mcpre_en), + dimp_get(eDI_MP_di_vscale_skip_count_real) + ); + } + + if (is_meson_gxtvbb_cpu() || + is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { + if (di_cfg_top_get(eDI_CFG_ref_2) && + mc_pre_flag && + dimp_get(eDI_MP_post_wr_en)) { /*OTT-3210*/ + dbg_once("mc_old=%d\n", mc_pre_flag); + mc_pre_flag = 1; + } + dim_post_read_reverse_irq(overturn, mc_pre_flag, + post_blend_en ? dimp_get(eDI_MP_mcpre_en) : false); + /* disable mc for first 2 fieldes mv unreliable */ + if (di_buf->seq < 2) + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + } + if (dimp_get(eDI_MP_mcpre_en)) { + if (di_buf->di_buf_dup_p[2]) + set_post_mcinfo(&di_buf->di_buf_dup_p[2] + ->curr_field_mcinfo); + } else if (is_meson_gxlx_cpu() || + is_meson_txl_cpu() || + is_meson_txlx_cpu()) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + } + +/* set pull down region (f(t-1) */ + + if (di_pldn_buf && + dimp_get(eDI_MP_pulldown_enable) && + !ppre->cur_prog_flag) { + unsigned short offset = (di_start_y >> 1); + + if (overturn) + offset = ((di_buf->vframe->height - di_end_y) >> 1); + else + offset = 0; + /*pulldown_vof_win_vshift*/ + get_ops_pd()->vof_win_vshift(&di_pldn_buf->pd_config, offset); + dimh_pulldown_vof_win_config(&di_pldn_buf->pd_config); + } + post_mif_sw(true); /*position?*/ + /*dimh_post_ctrl(DI_HW_POST_CTRL_RESET, di_ddr_en);*/ + /*add by wangfeng 2018-11-15*/ + dim_VSYNC_WR_MPEG_REG_BITS(DI_DIWR_CTRL, 1, 31, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_DIWR_CTRL, 0, 31, 1); + /*ary add for post crash*/ + di_post_set_flow((dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)), + eDI_POST_FLOW_STEP2_START); + + if (ppost->update_post_reg_flag > 0) + ppost->update_post_reg_flag--; + + /*dbg*/ + dim_ddbg_mod_save(eDI_DBG_MOD_POST_SETE, channel, ppost->frame_cnt); + dbg_post_cnt(channel, "ps2"); + ppost->frame_cnt++; + + return 0; +} + +#ifndef DI_DEBUG_POST_BUF_FLOW +static void post_ready_buf_set(unsigned int ch, struct di_buf_s *di_buf) +{ + vframe_t *vframe_ret = NULL; + struct di_buf_s *nr_buf = NULL; + + vframe_ret = di_buf->vframe; + nr_buf = di_buf->di_buf_dup_p[1]; + if ((dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) && + (di_buf->process_fun_index != PROCESS_FUN_NULL)) { + #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + vframe_ret->canvas0_config[0].phy_addr = + di_buf->nr_adr; + vframe_ret->canvas0_config[0].width = + di_buf->canvas_width[NR_CANVAS], + vframe_ret->canvas0_config[0].height = + di_buf->canvas_height; + vframe_ret->canvas0_config[0].block_mode = 0; + vframe_ret->plane_num = 1; + vframe_ret->canvas0Addr = -1; + vframe_ret->canvas1Addr = -1; + if (di_mp_uit_get(eDI_MP_show_nrwr)) { + vframe_ret->canvas0_config[0].phy_addr = + nr_buf->nr_adr; + vframe_ret->canvas0_config[0].width = + nr_buf->canvas_width[NR_CANVAS]; + vframe_ret->canvas0_config[0].height = + nr_buf->canvas_height; + } + #else + config_canvas_idx(di_buf, di_wr_idx, -1); + vframe_ret->canvas0Addr = di_buf->nr_canvas_idx; + vframe_ret->canvas1Addr = di_buf->nr_canvas_idx; + if (di_mp_uit_get(eDI_MP_show_nrwr)) { + config_canvas_idx(nr_buf, + di_wr_idx, -1); + vframe_ret->canvas0Addr = di_wr_idx; + vframe_ret->canvas1Addr = di_wr_idx; + } + #endif + vframe_ret->early_process_fun = dim_do_post_wr_fun; + vframe_ret->process_fun = NULL; + + /* 2019-04-22 Suggestions from brian.zhu*/ + vframe_ret->mem_handle = NULL; + vframe_ret->type |= VIDTYPE_DI_PW; + /* 2019-04-22 */ + } +} + +#endif +void dim_post_de_done_buf_config(unsigned int channel) +{ + ulong irq_flag2 = 0; + struct di_buf_s *di_buf = NULL; + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (!ppost->cur_post_buf) + return; + dbg_post_cnt(channel, "pd1"); + /*dbg*/ + dim_ddbg_mod_save(eDI_DBG_MOD_POST_DB, channel, ppost->frame_cnt); + + di_lock_irqfiq_save(irq_flag2); + queue_out(channel, ppost->cur_post_buf);/*? which que?post free*/ + di_buf = ppost->cur_post_buf; + + if (de_devp->pps_enable && dimp_get(eDI_MP_pps_position) == 0) { + di_buf->vframe->width = dimp_get(eDI_MP_pps_dstw); + di_buf->vframe->height = dimp_get(eDI_MP_pps_dsth); + } + + #ifdef DI_DEBUG_POST_BUF_FLOW + #else + post_ready_buf_set(channel, di_buf); + #endif + di_que_in(channel, QUE_POST_READY, ppost->cur_post_buf); + + #ifdef DI_DEBUG_POST_BUF_FLOW + #else + /*add by ary:*/ + recycle_post_ready_local(ppost->cur_post_buf, channel); + #endif + di_unlock_irqfiq_restore(irq_flag2); + dim_tr_ops.post_ready(di_buf->vframe->omx_index); + pw_vf_notify_receiver(channel, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + ppost->cur_post_buf = NULL; + /*dbg*/ + dim_ddbg_mod_save(eDI_DBG_MOD_POST_DE, channel, ppost->frame_cnt); + dbg_post_cnt(channel, "pd2"); +} + +#if 0 +static void di_post_process(unsigned int channel) +{ + struct di_buf_s *di_buf = NULL; + vframe_t *vf_p = NULL; + struct di_post_stru_s *ppost = get_post_stru(channel); + + if (ppost->post_de_busy) + return; + if (queue_empty(channel, QUEUE_POST_DOING)) { + ppost->post_peek_underflow++; + return; + } + + di_buf = get_di_buf_head(channel, QUEUE_POST_DOING); + if (dim_check_di_buf(di_buf, 20, channel)) + return; + vf_p = di_buf->vframe; + if (ppost->run_early_proc_fun_flag) { + if (vf_p->early_process_fun) + vf_p->early_process_fun = dim_do_post_wr_fun; + } + if (di_buf->process_fun_index) { + ppost->post_wr_cnt++; + dim_post_process(di_buf, 0, vf_p->width - 1, + 0, vf_p->height - 1, vf_p); + ppost->post_de_busy = 1; + ppost->irq_time = cur_to_msecs(); + } else { + ppost->de_post_process_done = 1; + } + ppost->cur_post_buf = di_buf; +} +#endif + +static void recycle_vframe_type_post(struct di_buf_s *di_buf, + unsigned int channel) +{ + int i; + + if (!di_buf) { + PR_ERR("%s:\n", __func__); + if (recovery_flag == 0) + recovery_log_reason = 15; + + recovery_flag++; + return; + } + if (di_buf->process_fun_index == PROCESS_FUN_DI) + dec_post_ref_count(di_buf); + + for (i = 0; i < 2; i++) { + if (di_buf->di_buf[i]) { + queue_in(channel, di_buf->di_buf[i], QUEUE_RECYCLE); + dim_print("%s: ch[%d]:di_buf[%d],type=%d\n", __func__, + channel, di_buf->di_buf[i]->index, + di_buf->di_buf[i]->type); + } + } + queue_out(channel, di_buf); /* remove it from display_list_head */ + if (di_buf->queue_index != -1) { + PR_ERR("qout err:index[%d],typ[%d],qindex[%d]\n", + di_buf->index, di_buf->type, di_buf->queue_index); + /* queue_out_dbg(channel, di_buf);*/ + } + di_buf->invert_top_bot_flag = 0; + di_que_in(channel, QUE_POST_FREE, di_buf); +} + +void recycle_post_ready_local(struct di_buf_s *di_buf, unsigned int channel) +{ + int i; + + if (di_buf->type != VFRAME_TYPE_POST) + return; + + if (di_buf->process_fun_index == PROCESS_FUN_NULL) /*bypass?*/ + return; + + if (di_buf->process_fun_index == PROCESS_FUN_DI) + dec_post_ref_count(di_buf); + + for (i = 0; i < 2; i++) { + if (di_buf->di_buf[i]) { + queue_in(channel, di_buf->di_buf[i], QUEUE_RECYCLE); + dim_print("%s: ch[%d]:di_buf[%d],type=%d\n", + __func__, + channel, + di_buf->di_buf[i]->index, + di_buf->di_buf[i]->type); + di_buf->di_buf[i] = NULL; + } + } +} + +#ifdef DI_BUFFER_DEBUG +static void +recycle_vframe_type_post_print(struct di_buf_s *di_buf, + const char *func, + const int line) +{ + int i; + + dim_print("%s:%d ", func, line); + for (i = 0; i < 2; i++) { + if (di_buf->di_buf[i]) + dim_print("%s[%d]<%d>=>recycle_list; ", + vframe_type_name[di_buf->di_buf[i]->type], + di_buf->di_buf[i]->index, i); + } + dim_print("%s[%d] =>post_free_list\n", + vframe_type_name[di_buf->type], di_buf->index); +} +#endif + +static unsigned int pldn_dly1 = 1; +static void set_pulldown_mode(struct di_buf_s *di_buf, unsigned int channel) +{ + struct di_buf_s *pre_buf_p = di_buf->di_buf_dup_p[pldn_dly1]; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXBB)) { + if (dimp_get(eDI_MP_pulldown_enable) && + !ppre->cur_prog_flag) { + if (pre_buf_p) { + di_buf->pd_config.global_mode = + pre_buf_p->pd_config.global_mode; + } else { + /* ary add 2019-06-19*/ + di_buf->pd_config.global_mode + = PULL_DOWN_EI; + PR_ERR("[%s]: index out of range.\n", + __func__); + } + } else { + di_buf->pd_config.global_mode + = PULL_DOWN_NORMAL; + } + } +} + +static void drop_frame(int check_drop, int throw_flag, struct di_buf_s *di_buf, + unsigned int channel) +{ + ulong irq_flag2 = 0; + int i = 0, drop_flag = 0; + struct di_post_stru_s *ppost = get_post_stru(channel); + + di_lock_irqfiq_save(irq_flag2); + if ((frame_count == 0) && check_drop) + ppost->start_pts = di_buf->vframe->pts; + if ((check_drop && + (frame_count < dimp_get(eDI_MP_start_frame_drop_count))) || + throw_flag) { + drop_flag = 1; + } else { + if (check_drop && (frame_count + == dimp_get(eDI_MP_start_frame_drop_count))) { + if ((ppost->start_pts) && + (di_buf->vframe->pts == 0)) + di_buf->vframe->pts = ppost->start_pts; + ppost->start_pts = 0; + } + for (i = 0; i < 3; i++) { + if (di_buf->di_buf_dup_p[i]) { + if (di_buf->di_buf_dup_p[i]->vframe->bitdepth != + di_buf->vframe->bitdepth) { + pr_info("%s buf[%d] not match bit mode\n", + __func__, i); + drop_flag = 1; + break; + } + } + } + } + if (drop_flag) { + queue_in(channel, di_buf, QUEUE_TMP); + recycle_vframe_type_post(di_buf, channel); +#ifdef DI_BUFFER_DEBUG + recycle_vframe_type_post_print( + di_buf, __func__, + __LINE__); +#endif + } else { + dim_print("%s:wr_en[%d],support[%d]\n", __func__, + dimp_get(eDI_MP_post_wr_en), + dimp_get(eDI_MP_post_wr_support)); + + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) + queue_in(channel, di_buf, QUEUE_POST_DOING); + else + di_que_in(channel, QUE_POST_READY, di_buf); + + dim_tr_ops.post_do(di_buf->vframe->omx_index); + dim_print("di:ch[%d]:%dth %s[%d] => post ready %u ms.\n", + channel, + frame_count, + vframe_type_name[di_buf->type], di_buf->index, + jiffies_to_msecs(jiffies_64 - + di_buf->vframe->ready_jiffies64)); + } + di_unlock_irqfiq_restore(irq_flag2); +} + +int dim_process_post_vframe(unsigned int channel) +{ +/* + * 1) get buf from post_free_list, config it according to buf + * in pre_ready_list, send it to post_ready_list + * (it will be send to post_free_list in di_vf_put()) + * 2) get buf from pre_ready_list, attach it to buf from post_free_list + * (it will be send to recycle_list in di_vf_put() ) + */ + ulong irq_flag2 = 0; + int i = 0; + int ret = 0; + int buffer_keep_count = 3; + struct di_buf_s *di_buf = NULL; + struct di_buf_s *ready_di_buf; + struct di_buf_s *p = NULL;/* , *ptmp; */ + int itmp; + /* new que int ready_count = list_count(channel, QUEUE_PRE_READY);*/ + int ready_count = di_que_list_count(channel, QUE_PRE_READY); + bool check_drop = false; + unsigned int tmpa[MAX_FIFO_SIZE]; /*new que*/ + unsigned int psize; /*new que*/ + +#if 1 + if (di_que_is_empty(channel, QUE_POST_FREE)) + return 0; + /*add : for now post buf only 3.*/ + if (list_count(channel, QUEUE_POST_DOING) > 2) + return 0; +#else + /*for post write mode ,need reserved a post free buf;*/ + if (di_que_list_count(channel, QUE_POST_FREE) < 2) + return 0; +#endif + if (ready_count == 0) + return 0; + + ready_di_buf = di_que_peek(channel, QUE_PRE_READY); + if (!ready_di_buf || !ready_di_buf->vframe) { + pr_dbg("%s:Error1\n", __func__); + + if (recovery_flag == 0) + recovery_log_reason = 16; + + recovery_flag++; + return 0; + } + dim_print("%s:1 ready_count[%d]:post_proc_flag[%d]\n", __func__, + ready_count, ready_di_buf->post_proc_flag); + if ((ready_di_buf->post_proc_flag) && + (ready_count >= buffer_keep_count)) { + i = 0; + + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + /* if(p->post_proc_flag == 0){ */ + if (p->type == VFRAME_TYPE_IN) { + ready_di_buf->post_proc_flag = -1; + ready_di_buf->new_format_flag = 1; + } + i++; + if (i > 2) + break; + } + } + if (ready_di_buf->post_proc_flag > 0) { + if (ready_count >= buffer_keep_count) { + di_lock_irqfiq_save(irq_flag2); + + di_buf = di_que_out_to_di_buf(channel, QUE_POST_FREE); + if (dim_check_di_buf(di_buf, 17, channel)) { + di_unlock_irqfiq_restore(irq_flag2); + return 0; + } + + di_unlock_irqfiq_restore(irq_flag2); + + i = 0; + + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + dim_print("di:keep[%d]:t[%d]:idx[%d]\n", + i, tmpa[itmp], p->index); + di_buf->di_buf_dup_p[i++] = p; + + if (i >= buffer_keep_count) + break; + } + if (i < buffer_keep_count) { + PR_ERR("%s:3\n", __func__); + + if (recovery_flag == 0) + recovery_log_reason = 18; + recovery_flag++; + return 0; + } + + memcpy(di_buf->vframe, + di_buf->di_buf_dup_p[1]->vframe, + sizeof(vframe_t)); + di_buf->vframe->private_data = di_buf; + if (di_buf->di_buf_dup_p[1]->post_proc_flag == 3) { + /* dummy, not for display */ + inc_post_ref_count(di_buf); + di_buf->di_buf[0] = di_buf->di_buf_dup_p[0]; + di_buf->di_buf[1] = NULL; + queue_out(channel, di_buf->di_buf[0]); + di_lock_irqfiq_save(irq_flag2); + queue_in(channel, di_buf, QUEUE_TMP); + recycle_vframe_type_post(di_buf, channel); + + di_unlock_irqfiq_restore(irq_flag2); + dim_print("%s : ", __func__); +#ifdef DI_BUFFER_DEBUG + dim_print("%s : ", __func__); +#endif + } else { + if (di_buf->di_buf_dup_p[1]->post_proc_flag + == 2) { + di_buf->pd_config.global_mode + = PULL_DOWN_BLEND_2; + /* blend with di_buf->di_buf_dup_p[2] */ + } else { + set_pulldown_mode(di_buf, channel); + } + di_buf->vframe->type = + VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; + + di_buf->vframe->width + = di_buf->di_buf_dup_p[1]->width_bk; + + if (di_buf->di_buf_dup_p[1]->new_format_flag) { + /* if (di_buf->di_buf_dup_p[1] + * ->post_proc_flag == 2) { + */ + di_buf->vframe->early_process_fun = + de_post_disable_fun; + } else { + di_buf->vframe->early_process_fun = + do_nothing_fun; + } + + if (di_buf->di_buf_dup_p[1]->type == VFRAME_TYPE_IN) { + /* next will be bypass */ + di_buf->vframe->type + = VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; + di_buf->vframe->height >>= 1; + di_buf->vframe->canvas0Addr = + di_buf->di_buf_dup_p[0] + ->nr_canvas_idx; /* top */ + di_buf->vframe->canvas1Addr = + di_buf->di_buf_dup_p[0] + ->nr_canvas_idx; + di_buf->vframe->process_fun = + NULL; + di_buf->process_fun_index = PROCESS_FUN_NULL; + } else { + /*for debug*/ + if (dimp_get(eDI_MP_debug_blend_mode) != -1) + di_buf->pd_config.global_mode + = dimp_get(eDI_MP_debug_blend_mode); + + di_buf->vframe->process_fun = +((dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) ? + NULL : dim_post_process); + di_buf->process_fun_index = PROCESS_FUN_DI; + inc_post_ref_count(di_buf); + } + di_buf->di_buf[0] /*ary:di_buf_di_buf*/ + = di_buf->di_buf_dup_p[0]; + di_buf->di_buf[1] = NULL; + queue_out(channel, di_buf->di_buf[0]); + + drop_frame(true, + (di_buf->di_buf_dup_p[0]->throw_flag) || + (di_buf->di_buf_dup_p[1]->throw_flag) || + (di_buf->di_buf_dup_p[2]->throw_flag), + di_buf, channel); + + frame_count++; +#ifdef DI_BUFFER_DEBUG + dim_print("%s : ", __func__); +#endif + if (!(dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support))) + pw_vf_notify_receiver(channel, +VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } + ret = 1; + } + } else { + if (is_progressive(ready_di_buf->vframe) || + ready_di_buf->type == VFRAME_TYPE_IN || + ready_di_buf->post_proc_flag < 0 || + dimp_get(eDI_MP_bypass_post_state) + ){ + int vframe_process_count = 1; +#ifdef DET3D + int dual_vframe_flag = 0; + + if ((ppre->vframe_interleave_flag && + ready_di_buf->left_right) || + (dimp_get(eDI_MP_bypass_post) & 0x100)) { + dual_vframe_flag = 1; + vframe_process_count = 2; + } +#endif + if (dimp_get(eDI_MP_skip_top_bot) && + (!is_progressive(ready_di_buf->vframe))) + vframe_process_count = 2; + + if (ready_count >= vframe_process_count) { + struct di_buf_s *di_buf_i; + + di_lock_irqfiq_save(irq_flag2); + + di_buf = di_que_out_to_di_buf(channel, QUE_POST_FREE); + if (dim_check_di_buf(di_buf, 19, channel)) { + di_unlock_irqfiq_restore(irq_flag2); + return 0; + } + + di_unlock_irqfiq_restore(irq_flag2); + + i = 0; + + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, + tmpa[itmp]); + di_buf->di_buf_dup_p[i++] = p; + if (i >= vframe_process_count) { + di_buf->di_buf_dup_p[i] + = NULL; + di_buf->di_buf_dup_p[i + 1] + = NULL; + break; + } + } + if (i < vframe_process_count) { + PR_ERR("%s:6\n", __func__); + if (recovery_flag == 0) + recovery_log_reason = 22; + + recovery_flag++; + return 0; + } + + di_buf_i = di_buf->di_buf_dup_p[0]; + if (!is_progressive(ready_di_buf->vframe) && + ((dimp_get(eDI_MP_skip_top_bot) == 1) || + (dimp_get(eDI_MP_skip_top_bot) == 2))) { + unsigned int frame_type = + di_buf->di_buf_dup_p[1]-> + vframe->type & + VIDTYPE_TYPEMASK; + if (dimp_get(eDI_MP_skip_top_bot) + == 1) { + di_buf_i = (frame_type == + VIDTYPE_INTERLACE_TOP) + ? di_buf->di_buf_dup_p[1] + : di_buf->di_buf_dup_p[0]; + } else if ( + dimp_get(eDI_MP_skip_top_bot) + == 2) { + di_buf_i = (frame_type == + VIDTYPE_INTERLACE_BOTTOM) + ? di_buf->di_buf_dup_p[1] + : di_buf->di_buf_dup_p[0]; + } + } + + memcpy(di_buf->vframe, di_buf_i->vframe, + sizeof(vframe_t)); + + di_buf->vframe->width = di_buf_i->width_bk; + di_buf->vframe->private_data = di_buf; + + if (ready_di_buf->new_format_flag && + (ready_di_buf->type == VFRAME_TYPE_IN)) { + pr_info("DI:ch[%d],%d disable post.\n", + channel, + __LINE__); + di_buf->vframe->early_process_fun + = de_post_disable_fun; + } else { + if (ready_di_buf->type == + VFRAME_TYPE_IN) + di_buf->vframe-> + early_process_fun + = do_nothing_fun; + + else + di_buf->vframe-> + early_process_fun + = do_pre_only_fun; + } + dim_print("%s:2\n", __func__); + if (ready_di_buf->post_proc_flag == -2) { + di_buf->vframe->type + |= VIDTYPE_VIU_FIELD; + di_buf->vframe->type + &= ~(VIDTYPE_TYPEMASK); + di_buf->vframe->process_fun += (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) ? NULL : + dim_post_process; + di_buf->process_fun_index = + PROCESS_FUN_DI; + di_buf->pd_config.global_mode + = PULL_DOWN_EI; + } else { + di_buf->vframe->process_fun = + NULL; + di_buf->process_fun_index = + PROCESS_FUN_NULL; + di_buf->pd_config.global_mode = + PULL_DOWN_NORMAL; + } + di_buf->di_buf[0] = ready_di_buf; + di_buf->di_buf[1] = NULL; + queue_out(channel, ready_di_buf); + +#ifdef DET3D + if (dual_vframe_flag) { + di_buf->di_buf[1] = + di_buf->di_buf_dup_p[1]; + queue_out(channel, di_buf->di_buf[1]); + } +#endif + drop_frame(check_drop, + di_buf->di_buf[0]->throw_flag, + di_buf, channel); + + frame_count++; +#ifdef DI_BUFFER_DEBUG + dim_print( + "%s : ", + __func__); +#endif + ret = 1; + pw_vf_notify_receiver(channel, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } else if (ready_count >= 2) { + /*for progressive input,type + * 1:separate tow fields,type + * 2:bypass post as frame + */ + unsigned char prog_tb_field_proc_type = + (dimp_get(eDI_MP_prog_proc_config) >> 1) & 0x3; + di_lock_irqfiq_save(irq_flag2); + + di_buf = di_que_out_to_di_buf(channel, QUE_POST_FREE); + if (dim_check_di_buf(di_buf, 20, channel)) { + di_unlock_irqfiq_restore(irq_flag2); + return 0; + } + + di_unlock_irqfiq_restore(irq_flag2); + + i = 0; + + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(channel, tmpa[itmp]); + di_buf->di_buf_dup_p[i++] = p; + if (i >= 2) { + di_buf->di_buf_dup_p[i] = NULL; + break; + } + } + if (i < 2) { + PR_ERR("%s:Error6\n", __func__); + + if (recovery_flag == 0) + recovery_log_reason = 21; + + recovery_flag++; + return 0; + } + + memcpy(di_buf->vframe, + di_buf->di_buf_dup_p[0]->vframe, + sizeof(vframe_t)); + di_buf->vframe->private_data = di_buf; + + /*separate one progressive frame + * as two interlace fields + */ + if (prog_tb_field_proc_type == 1) { + /* do weave by di post */ + di_buf->vframe->type = + VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; + if ( + di_buf->di_buf_dup_p[0]-> + new_format_flag) + di_buf->vframe-> + early_process_fun = + de_post_disable_fun; + else + di_buf->vframe-> + early_process_fun = + do_nothing_fun; + + di_buf->pd_config.global_mode = + PULL_DOWN_BUF1; + di_buf->vframe->process_fun = +(dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) ? NULL : + dim_post_process; + di_buf->process_fun_index = PROCESS_FUN_DI; + } else if (prog_tb_field_proc_type == 0) { + /* to do: need change for + * DI_USE_FIXED_CANVAS_IDX + */ + /* do weave by vpp */ + di_buf->vframe->type = + VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE; + if ( + (di_buf->di_buf_dup_p[0]-> + new_format_flag) || + (Rd(DI_IF1_GEN_REG) & 1)) + di_buf->vframe-> + early_process_fun = + de_post_disable_fun; + else + di_buf->vframe-> + early_process_fun = + do_nothing_fun; + di_buf->vframe->process_fun = NULL; + di_buf->process_fun_index = PROCESS_FUN_NULL; + di_buf->vframe->canvas0Addr = + di_buf->di_buf_dup_p[0]-> + nr_canvas_idx; + di_buf->vframe->canvas1Addr = + di_buf->di_buf_dup_p[1]-> + nr_canvas_idx; + } else { + /* to do: need change for + * DI_USE_FIXED_CANVAS_IDX + */ + di_buf->vframe->type = + VIDTYPE_PROGRESSIVE | + VIDTYPE_VIU_422 | + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; + di_buf->vframe->height >>= 1; + + di_buf->vframe->width + = di_buf->di_buf_dup_p[0]->width_bk; + if ( + (di_buf->di_buf_dup_p[0]-> + new_format_flag) || + (Rd(DI_IF1_GEN_REG) & 1)) + di_buf->vframe-> + early_process_fun = + de_post_disable_fun; + else + di_buf->vframe-> + early_process_fun = + do_nothing_fun; + if (prog_tb_field_proc_type == 2) { + di_buf->vframe->canvas0Addr = + di_buf->di_buf_dup_p[0] + ->nr_canvas_idx; +/* top */ + di_buf->vframe->canvas1Addr = + di_buf->di_buf_dup_p[0] + ->nr_canvas_idx; + } else { + di_buf->vframe->canvas0Addr = + di_buf->di_buf_dup_p[1] + ->nr_canvas_idx; /* top */ + di_buf->vframe->canvas1Addr = + di_buf->di_buf_dup_p[1] + ->nr_canvas_idx; + } + } + + di_buf->di_buf[0] = di_buf->di_buf_dup_p[0]; + queue_out(channel, di_buf->di_buf[0]); + /*check if the field is error,then drop*/ + if ( + (di_buf->di_buf_dup_p[0]->vframe->type & + VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_BOTTOM) { + di_buf->di_buf[1] = + di_buf->di_buf_dup_p[1] = NULL; + queue_in(channel, di_buf, QUEUE_TMP); + recycle_vframe_type_post(di_buf, channel); + pr_dbg("%s drop field %d.\n", __func__, + di_buf->di_buf_dup_p[0]->seq); + } else { + di_buf->di_buf[1] = + di_buf->di_buf_dup_p[1]; + queue_out(channel, di_buf->di_buf[1]); + + drop_frame( + dimp_get(eDI_MP_check_start_drop_prog), + (di_buf->di_buf_dup_p[0]->throw_flag) || + (di_buf->di_buf_dup_p[1]->throw_flag), + di_buf, channel); + } + frame_count++; +#ifdef DI_BUFFER_DEBUG + dim_print("%s : ", __func__); +#endif + ret = 1; + pw_vf_notify_receiver(channel, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } + } + +#ifdef DI_BUFFER_DEBUG + if (di_buf) { + dim_print("%s[%d](", + vframe_type_name[di_buf->type], di_buf->index); + for (i = 0; i < 2; i++) { + if (di_buf->di_buf[i]) + dim_print("%s[%d],", + vframe_type_name[di_buf->di_buf[i]->type], + di_buf->di_buf[i]->index); + } + dim_print(")(vframe type %x dur %d)", + di_buf->vframe->type, di_buf->vframe->duration); + if (di_buf->di_buf_dup_p[1] && + (di_buf->di_buf_dup_p[1]->post_proc_flag == 3)) + dim_print("=> recycle_list\n"); + else + dim_print("=> post_ready_list\n"); + } +#endif + return ret; +} + +/* + * di task + */ +void dim_unreg_process(unsigned int channel) +{ + unsigned long start_jiffes = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + pr_info("%s unreg start %d.\n", __func__, get_reg_flag(channel)); + if (get_reg_flag(channel)) { + start_jiffes = jiffies_64; + di_vframe_unreg(channel); + pr_dbg("%s vf unreg cost %u ms.\n", __func__, + jiffies_to_msecs(jiffies_64 - start_jiffes)); + unreg_cnt++; + if (unreg_cnt > 0x3fffffff) + unreg_cnt = 0; + pr_dbg("%s unreg stop %d.\n", __func__, get_reg_flag(channel)); + + } else { + ppre->force_unreg_req_flag = 0; + ppre->disable_req_flag = 0; + recovery_flag = 0; + } +} + +void di_unreg_setting(void) +{ + unsigned int mirror_disable = get_blackout_policy(); + + if (!get_hw_reg_flg()) { + PR_ERR("%s:have setting?do nothing\n", __func__); + return; + } + + pr_info("%s:\n", __func__); + /*set flg*/ + set_hw_reg_flg(false); + + dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en)); + post_close_new(); /*2018-11-29*/ + dimh_afbc_reg_sw(false); + dimh_hw_uninit(); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { + dim_pre_gate_control(false, dimp_get(eDI_MP_mcpre_en)); + get_ops_nr()->nr_gate_control(false); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + dim_DI_Wr(DI_CLKG_CTRL, 0x80f60000); + dim_DI_Wr(DI_PRE_CTRL, 0); + } else { + dim_DI_Wr(DI_CLKG_CTRL, 0xf60000); + } + /*ary add for switch to post wr, can't display*/ + pr_info("di: patch dimh_disable_post_deinterlace_2\n"); + dimh_disable_post_deinterlace_2(); + /* nr/blend0/ei0/mtn0 clock gate */ + + dim_hw_disable(dimp_get(eDI_MP_mcpre_en)); + + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { + dimh_enable_di_post_mif(GATE_OFF); + dim_post_gate_control(false); + dim_top_gate_control(false, false); + } else { + dim_DI_Wr(DI_CLKG_CTRL, 0x80000000); + } + if (!is_meson_gxl_cpu() && + !is_meson_gxm_cpu() && + !is_meson_gxbb_cpu() && + !is_meson_txlx_cpu()) + diext_clk_b_sw(false); + pr_info("%s disable di mirror image.\n", __func__); + +#if 0 + if (mirror_disable) { + /*no mirror:*/ + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) + dim_set_power_control(0); + + } else { + /*have mirror:*/ + } +#else /*0624?*/ + if ((dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) || + mirror_disable) { + /*diwr_set_power_control(0);*/ + hpst_mem_pd_sw(0); + } + if (mirror_disable) + hpst_vd1_sw(0); +#endif + + #if 0 /*tmp*/ + if (post_wr_en && post_wr_support) + dim_set_power_control(0); + #endif + + disp_frame_count = 0;/* debug only*/ +} + +void di_unreg_variable(unsigned int channel) +{ + ulong irq_flag2 = 0; + unsigned int mirror_disable = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + +#if (defined ENABLE_SPIN_LOCK_ALWAYS) + ulong flags = 0; + + spin_lock_irqsave(&plist_lock, flags); +#endif + pr_info("%s:\n", __func__); + set_init_flag(channel, false); /*init_flag = 0;*/ + mirror_disable = get_blackout_policy(); + di_lock_irqfiq_save(irq_flag2); + dim_print("%s: dim_uninit_buf\n", __func__); + dim_uninit_buf(mirror_disable, channel); +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (di_pre_rdma_enable) + rdma_clear(de_devp->rdma_handle); +#endif + get_ops_mtn()->adpative_combing_exit(); + + di_unlock_irqfiq_restore(irq_flag2); + +#if (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_unlock_irqrestore(&plist_lock, flags); +#endif + dimh_patch_post_update_mc_sw(DI_MC_SW_REG, false); + + ppre->force_unreg_req_flag = 0; + ppre->disable_req_flag = 0; + recovery_flag = 0; + ppre->cur_prog_flag = 0; + + if (de_devp->flag_cma == 1 || + de_devp->flag_cma == 3 || + de_devp->flag_cma == 4) + dip_wq_cma_run(channel, false); + + sum_g_clear(channel); + sum_p_clear(channel); + dbg_reg("%s:end\n", __func__); +} + +void dim_unreg_process_irq(unsigned int channel) +{ + ulong irq_flag2 = 0; + unsigned int mirror_disable = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + +#if (defined ENABLE_SPIN_LOCK_ALWAYS) + ulong flags = 0; + + spin_lock_irqsave(&plist_lock, flags); +#endif + pr_info("%s:warn:not use\n", __func__); + set_init_flag(channel, false); /*init_flag = 0;*/ + mirror_disable = 1; /*get_blackout_policy()*/; + di_lock_irqfiq_save(irq_flag2); + dim_print("%s: dim_uninit_buf\n", __func__); + dim_uninit_buf(mirror_disable, channel); +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (di_pre_rdma_enable) + rdma_clear(de_devp->rdma_handle); +#endif + get_ops_mtn()->adpative_combing_exit(); + dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en)); + dimh_afbc_reg_sw(false); + dimh_hw_uninit(); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { + dim_pre_gate_control(false, dimp_get(eDI_MP_mcpre_en)); + get_ops_nr()->nr_gate_control(false); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + dim_DI_Wr(DI_CLKG_CTRL, 0x80f60000); + dim_DI_Wr(DI_PRE_CTRL, 0); + } else { + dim_DI_Wr(DI_CLKG_CTRL, 0xf60000); + } + /*ary add for switch to post wr, can't display*/ + pr_info("di: patch dimh_disable_post_deinterlace_2\n"); + dimh_disable_post_deinterlace_2(); + +/* nr/blend0/ei0/mtn0 clock gate */ + if (mirror_disable) { + dim_hw_disable(dimp_get(eDI_MP_mcpre_en)); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { + dimh_enable_di_post_mif(GATE_OFF); + dim_post_gate_control(false); + dim_top_gate_control(false, false); + } else { + dim_DI_Wr(DI_CLKG_CTRL, 0x80000000); + } + if (!is_meson_gxl_cpu() && + !is_meson_gxm_cpu() && + !is_meson_gxbb_cpu() && + !is_meson_txlx_cpu()) + diext_clk_b_sw(false); + + pr_info("%s disable di mirror image.\n", __func__); + } + if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) + dim_set_power_control(0); + di_unlock_irqfiq_restore(irq_flag2); + +#if (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_unlock_irqrestore(&plist_lock, flags); +#endif + dimh_patch_post_update_mc_sw(DI_MC_SW_REG, false); + ppre->force_unreg_req_flag = 0; + ppre->disable_req_flag = 0; + recovery_flag = 0; + ppre->cur_prog_flag = 0; + +#if 0 +#ifdef CONFIG_CMA + if (de_devp->flag_cma == 1) { + pr_dbg("%s:cma release req time: %d ms\n", + __func__, jiffies_to_msecs(jiffies)); + ppre->cma_release_req = 1; + up(get_sema()); + } +#endif +#else + if (de_devp->flag_cma == 1) + dip_wq_cma_run(channel, false); + +#endif +} + +void diext_clk_b_sw(bool on) +{ + if (on) + ext_ops.switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_ON); + else + ext_ops.switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_OFF); +} + +void dim_reg_process(unsigned int channel) +{ + /*get vout information first time*/ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (get_reg_flag(channel)) + return; + di_vframe_reg(channel); + + ppre->bypass_flag = false; + reg_cnt++; + if (reg_cnt > 0x3fffffff) + reg_cnt = 0; + dim_print("########%s\n", __func__); +} + +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA +/* di pre rdma operation */ +static void di_rdma_irq(void *arg) +{ + struct di_dev_s *di_devp = (struct di_dev_s *)arg; + unsigned int channel = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (IS_ERR_OR_NULL(di_devp)) + return; + if (di_devp->rdma_handle <= 0) { + PR_ERR("%s rdma handle %d error.\n", __func__, + di_devp->rdma_handle); + return; + } + if (dimp_get(eDI_MP_di_printk_flag)) + pr_dbg("%s...%d.\n", __func__, + ppre->field_count_for_cont); +} + +static struct rdma_op_s di_rdma_op = { + di_rdma_irq, + NULL +}; +#endif + +void dim_rdma_init(void) +{ +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + struct di_dev_s *de_devp = get_dim_de_devp(); +/* rdma handle */ + if (di_pre_rdma_enable) { + di_rdma_op.arg = de_devp; + de_devp->rdma_handle = rdma_register(&di_rdma_op, + de_devp, RDMA_TABLE_SIZE); + } + +#endif +} + +void dim_rdma_exit(void) +{ +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + struct di_dev_s *de_devp = get_dim_de_devp(); + + /* rdma handle */ + if (de_devp->rdma_handle > 0) + rdma_unregister(de_devp->rdma_handle); +#endif +} + +static void di_load_pq_table(void) +{ + struct di_pq_parm_s *pos = NULL, *tmp = NULL; + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (atomic_read(&de_devp->pq_flag) == 0 && + (de_devp->flags & DI_LOAD_REG_FLAG)) { + atomic_set(&de_devp->pq_flag, 1); + list_for_each_entry_safe(pos, tmp, + &de_devp->pq_table_list, list) { + dimh_load_regs(pos); + list_del(&pos->list); + di_pq_parm_destroy(pos); + } + de_devp->flags &= ~DI_LOAD_REG_FLAG; + atomic_set(&de_devp->pq_flag, 0); + } +} + +static void di_pre_size_change(unsigned short width, + unsigned short height, + unsigned short vf_type, + unsigned int channel) +{ + unsigned int blkhsize = 0; + int pps_w = 0, pps_h = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + /*pr_info("%s:\n", __func__);*/ + /*debug only:*/ + /*di_pause(channel, true);*/ + get_ops_nr()->nr_all_config(width, height, vf_type); + #ifdef DET3D + /*det3d_config*/ + get_ops_3d()->det3d_config(dimp_get(eDI_MP_det3d_en) ? 1 : 0); + #endif + if (dimp_get(eDI_MP_pulldown_enable)) { + /*pulldown_init(width, height);*/ + get_ops_pd()->init(width, height); + dimh_init_field_mode(height); + + if (is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) + dim_film_mode_win_config(width, height); + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dimh_combing_pd22_window_config(width, height); + dim_RDMA_WR(DI_PRE_SIZE, (width - 1) | + ((height - 1) << 16)); + + if (dimp_get(eDI_MP_mcpre_en)) { + blkhsize = (width + 4) / 5; + dim_RDMA_WR(MCDI_HV_SIZEIN, height + | (width << 16)); + dim_RDMA_WR(MCDI_HV_BLKSIZEIN, (overturn ? 3 : 0) << 30 + | blkhsize << 16 | height); + dim_RDMA_WR(MCDI_BLKTOTAL, blkhsize * height); + if (is_meson_gxlx_cpu()) { + dim_RDMA_WR(MCDI_PD_22_CHK_FLG_CNT, 0); + dim_RDMA_WR(MCDI_FIELD_MV, 0); + } + } + if (channel == 0) + di_load_pq_table(); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dim_RDMA_WR(DI_PRE_GL_CTRL, 0x80000005); + if (de_devp->nrds_enable) + dim_nr_ds_init(width, height); + if (de_devp->pps_enable && dimp_get(eDI_MP_pps_position)) { + pps_w = ppre->cur_width; + pps_h = ppre->cur_height >> 1; + dim_pps_config(1, pps_w, pps_h, + dimp_get(eDI_MP_pps_dstw), + (dimp_get(eDI_MP_pps_dsth) >> 1)); + } + if (is_meson_sm1_cpu() || is_meson_tm2_cpu()) { + if (de_devp->h_sc_down_en) { + pps_w = ppre->cur_width; + dim_inp_hsc_setting(pps_w, + di_mp_uit_get(eDI_MP_pre_hsc_down_width)); + } else { + dim_inp_hsc_setting(ppre->cur_width, + ppre->cur_width); + } + } + #if 0 + dimh_interrupt_ctrl(ppre->madi_enable, + det3d_en ? 1 : 0, + de_devp->nrds_enable, + post_wr_en, + ppre->mcdi_enable); + #else + /*dimh_int_ctr(0, 0, 0, 0, 0, 0);*/ + dimh_int_ctr(1, ppre->madi_enable, + dimp_get(eDI_MP_det3d_en) ? 1 : 0, + de_devp->nrds_enable, + dimp_get(eDI_MP_post_wr_en), + ppre->mcdi_enable); + #endif +} + +static bool need_bypass(struct vframe_s *vf) +{ + if (vf->type & VIDTYPE_MVC) + return true; + + if (vf->source_type == VFRAME_SOURCE_TYPE_PPMGR) + return true; + + if (vf->type & VIDTYPE_VIU_444) + return true; + + if (vf->type & VIDTYPE_PIC) + return true; +#if 0 + if (vf->type & VIDTYPE_COMPRESS) + return true; +#else + /*support G12A and TXLX platform*/ + if (vf->type & VIDTYPE_COMPRESS) { + if (!dimh_afbc_is_supported()) + return true; + if ((vf->compHeight > (default_height + 8)) || + (vf->compWidth > default_width)) + return true; + } +#endif + if ((vf->width > default_width) || + (vf->height > (default_height + 8))) + return true; +#if 1 + if (vf_type_is_prog(vf->type)) {/*temp bypass p*/ + return true; + } +#endif + /*true bypass for 720p above*/ + if ((vf->flag & VFRAME_FLAG_GAME_MODE) && + (vf->width > 720)) + return true; + + return false; +} + +/********************************* + * + * setting register only call when + * from di_reg_process_irq + *********************************/ +void di_reg_setting(unsigned int channel, struct vframe_s *vframe) +{ + unsigned short nr_height = 0, first_field_type; + struct di_dev_s *de_devp = get_dim_de_devp(); + + pr_info("%s:ch[%d]:for first ch reg:\n", __func__, channel); + + if (get_hw_reg_flg()) { + PR_ERR("%s:have setting?do nothing\n", __func__); + return; + } + /*set flg*/ + set_hw_reg_flg(true); + + diext_clk_b_sw(true); + + dim_ddbg_mod_save(eDI_DBG_MOD_REGB, channel, 0); + + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) + dim_set_power_control(1); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + /*if (!use_2_interlace_buff) {*/ + if (1) { + dim_top_gate_control(true, true); + dim_post_gate_control(true); + /* freerun for reg configuration */ + dimh_enable_di_post_mif(GATE_AUTO); + } else { + dim_top_gate_control(true, false); + } + de_devp->flags |= DI_VPU_CLKB_SET; + #if 1 /*set clkb to max */ + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu() + ) { + #ifdef CLK_TREE_SUPPORT + clk_set_rate(de_devp->vpu_clkb, + de_devp->clkb_max_rate); + #endif + } + #endif + dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en)); + dim_pre_gate_control(true, dimp_get(eDI_MP_mcpre_en)); + dim_rst_protect(true);/*2019-01-22 by VLSI feng.wang*/ + dim_pre_nr_wr_done_sel(true); + get_ops_nr()->nr_gate_control(true); + } else { + /* if mcdi enable DI_CLKG_CTRL should be 0xfef60000 */ + dim_DI_Wr(DI_CLKG_CTRL, 0xfef60001); + /* nr/blend0/ei0/mtn0 clock gate */ + } + /*--------------------------*/ + dim_init_setting_once(); + /*--------------------------*/ + /*di_post_reset();*/ /*add by feijun 2018-11-19 */ + post_mif_sw(false); + post_dbg_contr(); + /*--------------------------*/ + + nr_height = (vframe->height >> 1);/*temp*/ + /*--------------------------*/ + dimh_calc_lmv_init(); + first_field_type = (vframe->type & VIDTYPE_TYPEMASK); + di_pre_size_change(vframe->width, nr_height, + first_field_type, channel); + get_ops_nr()->cue_int(vframe); + dim_ddbg_mod_save(eDI_DBG_MOD_REGE, channel, 0); + + /*--------------------------*/ + /*test*/ + dimh_int_ctr(0, 0, 0, 0, 0, 0); +} + +/********************************* + * + * setting variable + * from di_reg_process_irq + * + *********************************/ +void di_reg_variable(unsigned int channel, struct vframe_s *vframe) +{ + ulong irq_flag2 = 0; + #ifndef RUN_DI_PROCESS_IN_IRQ + ulong flags = 0; + #endif + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + if ((pre_run_flag != DI_RUN_FLAG_RUN) && + (pre_run_flag != DI_RUN_FLAG_STEP)) + return; + if (pre_run_flag == DI_RUN_FLAG_STEP) + pre_run_flag = DI_RUN_FLAG_STEP_DONE; + + dbg_reg("%s:\n", __func__); + + dim_print("%s:0x%p\n", __func__, vframe); + if (vframe) { + dip_init_value_reg(channel);/*add 0404 for post*/ + dim_ddbg_mod_save(eDI_DBG_MOD_RVB, channel, 0); + if (need_bypass(vframe) || + ((dimp_get(eDI_MP_di_debug_flag) >> 20) & 0x1)) { + if (!ppre->bypass_flag) { + pr_info("DI %ux%u-0x%x.\n", + vframe->width, + vframe->height, + vframe->type); + } + ppre->bypass_flag = true; + dimh_patch_post_update_mc_sw(DI_MC_SW_OTHER, false); + return; + } + ppre->bypass_flag = false; + /* patch for vdin progressive input */ + if ((is_from_vdin(vframe) && + is_progressive(vframe)) + #ifdef DET3D + || dimp_get(eDI_MP_det3d_en) + #endif + || (dimp_get(eDI_MP_use_2_interlace_buff) & 0x2) + ) { + dimp_set(eDI_MP_use_2_interlace_buff, 1); + } else { + dimp_set(eDI_MP_use_2_interlace_buff, 0); + } + de_devp->nrds_enable = dimp_get(eDI_MP_nrds_en); + de_devp->pps_enable = dimp_get(eDI_MP_pps_en); + /*di pre h scaling down: sm1 tm2*/ + de_devp->h_sc_down_en = di_mp_uit_get(eDI_MP_pre_hsc_down_en); + + if (dimp_get(eDI_MP_di_printk_flag) & 2) + dimp_set(eDI_MP_di_printk_flag, 1); + + dim_print("%s: vframe come => di_init_buf\n", __func__); + + if (de_devp->flag_cma == 0 && !de_devp->mem_flg) + dim_rev_mem_check(); + + /*(is_progressive(vframe) && (prog_proc_config & 0x10)) {*/ + if (0) { +#if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_lock_irqsave(&plist_lock, flags); +#endif + di_lock_irqfiq_save(irq_flag2); + /* + * 10 bit mode need 1.5 times buffer size of + * 8 bit mode, init the buffer size as 10 bit + * mode size, to make sure can switch bit mode + * smoothly. + */ + di_init_buf(default_width, default_height, 1, channel); + + di_unlock_irqfiq_restore(irq_flag2); + +#if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_unlock_irqrestore(&plist_lock, flags); +#endif + } else { +#if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_lock_irqsave(&plist_lock, flags); +#endif + di_lock_irqfiq_save(irq_flag2); + /* + * 10 bit mode need 1.5 times buffer size of + * 8 bit mode, init the buffer size as 10 bit + * mode size, to make sure can switch bit mode + * smoothly. + */ + di_init_buf(default_width, default_height, 0, channel); + + di_unlock_irqfiq_restore(irq_flag2); + +#if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) + spin_unlock_irqrestore(&plist_lock, flags); +#endif + } + + ppre->mtn_status = + get_ops_mtn()->adpative_combing_config(vframe->width, + (vframe->height >> 1), + (vframe->source_type), + is_progressive(vframe), + vframe->sig_fmt); + + dimh_patch_post_update_mc_sw(DI_MC_SW_REG, true); + di_sum_reg_init(channel); + + set_init_flag(channel, true);/*init_flag = 1;*/ + + dim_ddbg_mod_save(eDI_DBG_MOD_RVE, channel, 0); + } +} + +/*para 1 not use*/ + +/* + * provider/receiver interface + */ + +/*************************/ +int di_ori_event_unreg(unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", + __func__, + dim_is_bypass(NULL, channel), + trick_mode, + di_cfgx_get(channel, eDI_CFGX_BYPASS_ALL)); + /*dbg_ev("%s:unreg\n", __func__);*/ + dip_even_unreg_val(channel); /*new*/ + + ppre->vdin_source = false; + + dip_event_unreg_chst(channel); + +#ifdef SUPPORT_MPEG_TO_VDIN + if (mpeg2vdin_flag) { + struct vdin_arg_s vdin_arg; + struct vdin_v4l2_ops_s *vdin_ops = get_vdin_v4l2_ops(); + + vdin_arg.cmd = VDIN_CMD_MPEGIN_STOP; + if (vdin_ops->tvin_vdin_func) + vdin_ops->tvin_vdin_func(0, &vdin_arg); + + mpeg2vdin_flag = 0; + } +#endif + di_bypass_state_set(channel, true); +#ifdef RUN_DI_PROCESS_IN_IRQ + if (ppre->vdin_source) + dim_DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); +#endif + + dbg_ev("ch[%d]unreg end\n", channel); + return 0; +} + +int di_ori_event_reg(void *data, unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + struct vframe_receiver_s *preceiver; + + char *provider_name = (char *)data; + const char *receiver_name = NULL; + + dip_even_reg_init_val(channel); + if (de_devp->flags & DI_SUSPEND_FLAG) { + PR_ERR("reg event device hasn't resumed\n"); + return -1; + } + if (get_reg_flag(channel)) { + PR_ERR("no muti instance.\n"); + return -1; + } + dbg_ev("reg:%s\n", provider_name); + + di_bypass_state_set(channel, false); + + dip_event_reg_chst(channel); + + if (strncmp(provider_name, "vdin0", 4) == 0) + ppre->vdin_source = true; + else + ppre->vdin_source = false; + + /*ary: need use interface api*/ + /*receiver_name = vf_get_receiver_name(VFM_NAME);*/ + preceiver = vf_get_receiver(di_rev_name[channel]); + if (preceiver) + receiver_name = preceiver->name; + + if (receiver_name) { + if (!strcmp(receiver_name, "amvideo")) { + ppost->run_early_proc_fun_flag = 0; + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support)) + ppost->run_early_proc_fun_flag = 1; + } else { + ppost->run_early_proc_fun_flag = 1; + pr_info("set run_early_proc_fun_flag to 1\n"); + } + } else { + pr_info("%s error receiver is null.\n", __func__); + } + + dbg_ev("ch[%d]:reg end\n", channel); + return 0; +} + +int di_ori_event_qurey_vdin2nr(unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + return ppre->vdin2nr; +} + +int di_ori_event_reset(unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct vframe_s **pvframe_in = get_vframe_in(channel); + int i; + ulong flags; + + /*block*/ + di_blocking = 1; + + /*dbg_ev("%s: VFRAME_EVENT_PROVIDER_RESET\n", __func__);*/ + if (dim_is_bypass(NULL, channel) || + di_bypass_state_get(channel) || + ppre->bypass_flag) { + pw_vf_notify_receiver(channel, + VFRAME_EVENT_PROVIDER_RESET, + NULL); + } + + spin_lock_irqsave(&plist_lock, flags); + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + if (pvframe_in[i]) + pr_dbg("DI:clear vframe_in[%d]\n", i); + + pvframe_in[i] = NULL; + } + spin_unlock_irqrestore(&plist_lock, flags); + di_blocking = 0; + + return 0; +} + +int di_ori_event_light_unreg(unsigned int channel) +{ + struct vframe_s **pvframe_in = get_vframe_in(channel); + int i; + ulong flags; + + di_blocking = 1; + + pr_dbg("%s: vf_notify_receiver ligth unreg\n", __func__); + + spin_lock_irqsave(&plist_lock, flags); + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + if (pvframe_in[i]) + pr_dbg("DI:clear vframe_in[%d]\n", i); + + pvframe_in[i] = NULL; + } + spin_unlock_irqrestore(&plist_lock, flags); + di_blocking = 0; + + return 0; +} + +int di_ori_event_light_unreg_revframe(unsigned int channel) +{ + struct vframe_s **pvframe_in = get_vframe_in(channel); + int i; + ulong flags; + + unsigned char vf_put_flag = 0; + + pr_info( + "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", + __func__); +/* + * do not display garbage when 2d->3d or 3d->2d + */ + spin_lock_irqsave(&plist_lock, flags); + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + if (pvframe_in[i]) { + pw_vf_put(pvframe_in[i], channel); + pr_dbg("DI:clear vframe_in[%d]\n", i); + vf_put_flag = 1; + } + pvframe_in[i] = NULL; + } + if (vf_put_flag) + pw_vf_notify_provider(channel, + VFRAME_EVENT_RECEIVER_PUT, NULL); + + spin_unlock_irqrestore(&plist_lock, flags); + + return 0; +} + +int di_irq_ori_event_ready(unsigned int channel) +{ + return 0; +} + +int di_ori_event_ready(unsigned int channel) +{ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (ppre->bypass_flag) + pw_vf_notify_receiver(channel, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + + if (dip_chst_get(channel) == eDI_TOP_STATE_REG_STEP1) + task_send_cmd(LCMD1(eCMD_READY, channel)); + else + task_send_ready(); + + di_irq_ori_event_ready(channel); + return 0; +} + +int di_ori_event_qurey_state(unsigned int channel) +{ + /*int in_buf_num = 0;*/ + struct vframe_states states; + + if (recovery_flag) + return RECEIVER_INACTIVE; + + /*fix for ucode reset method be break by di.20151230*/ + di_vf_l_states(&states, channel); + if (states.buf_avail_num > 0) + return RECEIVER_ACTIVE; + + if (pw_vf_notify_receiver( + channel, + VFRAME_EVENT_PROVIDER_QUREY_STATE, + NULL) == RECEIVER_ACTIVE) + return RECEIVER_ACTIVE; + + return RECEIVER_INACTIVE; +} + +void di_ori_event_set_3D(int type, void *data, unsigned int channel) +{ +#ifdef DET3D + + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (type == VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE) { + int flag = (long)data; + + ppre->vframe_interleave_flag = flag; + } + +#endif +} + +/*************************/ + +/*recycle the buffer for keeping buffer*/ +static void recycle_keep_buffer(unsigned int channel) +{ + ulong irq_flag2 = 0; + int i = 0; + struct di_buf_s *keep_buf; + struct di_post_stru_s *ppost = get_post_stru(channel); + + keep_buf = ppost->keep_buf; + if (!IS_ERR_OR_NULL(keep_buf)) { + PR_ERR("%s:\n", __func__); + if (keep_buf->type == VFRAME_TYPE_POST) { + pr_dbg("%s recycle keep cur di_buf %d (", + __func__, keep_buf->index); + di_lock_irqfiq_save(irq_flag2); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + if (keep_buf->di_buf_dup_p[i]) { + queue_in(channel, + keep_buf->di_buf_dup_p[i], + QUEUE_RECYCLE); + pr_dbg(" %d ", + keep_buf->di_buf_dup_p[i]->index); + } + } + di_que_in(channel, QUE_POST_FREE, keep_buf); + di_unlock_irqfiq_restore(irq_flag2); + pr_dbg(")\n"); + } + ppost->keep_buf = NULL; + } +} + +/************************************/ +/************************************/ +struct vframe_s *di_vf_l_get(unsigned int channel) +{ + vframe_t *vframe_ret = NULL; + struct di_buf_s *di_buf = NULL; +#ifdef DI_DEBUG_POST_BUF_FLOW + struct di_buf_s *nr_buf = NULL; +#endif + + ulong irq_flag2 = 0; + struct di_post_stru_s *ppost = get_post_stru(channel); + + dim_print("%s:ch[%d]\n", __func__, channel); + + if (!get_init_flag(channel) || + recovery_flag || + di_blocking || + !get_reg_flag(channel) || + dump_state_flag) { + dim_tr_ops.post_get2(1); + return NULL; + } + + /**************************/ + if (list_count(channel, QUEUE_DISPLAY) > 2) { + dim_tr_ops.post_get2(2); + return NULL; + } + /**************************/ + +#ifdef SUPPORT_START_FRAME_HOLD + if ((disp_frame_count == 0) && (dim_is_bypass(NULL, channel) == 0)) { + int ready_count = di_que_list_count(channel, QUE_POST_READY); + + if (ready_count > start_frame_hold_count) + goto get_vframe; + } else +#endif + if (!di_que_is_empty(channel, QUE_POST_READY)) { +#ifdef SUPPORT_START_FRAME_HOLD +get_vframe: +#endif + dim_log_buffer_state("ge_", channel); + di_lock_irqfiq_save(irq_flag2); + + di_buf = di_que_out_to_di_buf(channel, QUE_POST_READY); + if (dim_check_di_buf(di_buf, 21, channel)) { + di_unlock_irqfiq_restore(irq_flag2); + return NULL; + } + /* add it into display_list */ + queue_in(channel, di_buf, QUEUE_DISPLAY); + + di_unlock_irqfiq_restore(irq_flag2); + + if (di_buf) { + vframe_ret = di_buf->vframe; +#ifdef DI_DEBUG_POST_BUF_FLOW + nr_buf = di_buf->di_buf_dup_p[1]; + if (dimp_get(eDI_MP_post_wr_en) && + dimp_get(eDI_MP_post_wr_support) && + (di_buf->process_fun_index != PROCESS_FUN_NULL)) { + #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + vframe_ret->canvas0_config[0].phy_addr = + di_buf->nr_adr; + vframe_ret->canvas0_config[0].width = + di_buf->canvas_width[NR_CANVAS], + vframe_ret->canvas0_config[0].height = + di_buf->canvas_height; + vframe_ret->canvas0_config[0].block_mode = 0; + vframe_ret->plane_num = 1; + vframe_ret->canvas0Addr = -1; + vframe_ret->canvas1Addr = -1; + if (di_mp_uit_get(eDI_MP_show_nrwr)) { + vframe_ret->canvas0_config[0].phy_addr = + nr_buf->nr_adr; + vframe_ret->canvas0_config[0].width = + nr_buf->canvas_width[NR_CANVAS]; + vframe_ret->canvas0_config[0].height = + nr_buf->canvas_height; + } + #else + config_canvas_idx(di_buf, di_wr_idx, -1); + vframe_ret->canvas0Addr = di_buf->nr_canvas_idx; + vframe_ret->canvas1Addr = di_buf->nr_canvas_idx; + if (di_mp_uit_get(eDI_MP_show_nrwr)) { + config_canvas_idx(nr_buf, + di_wr_idx, -1); + vframe_ret->canvas0Addr = di_wr_idx; + vframe_ret->canvas1Addr = di_wr_idx; + } + #endif + vframe_ret->early_process_fun = dim_do_post_wr_fun; + vframe_ret->process_fun = NULL; + } +#endif + di_buf->seq = disp_frame_count; + atomic_set(&di_buf->di_cnt, 1); + } + disp_frame_count++; + + dim_log_buffer_state("get", channel); + } + if (vframe_ret) { + dim_print("%s: %s[%d]:0x%p %u ms\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index, + vframe_ret, + jiffies_to_msecs(jiffies_64 - + vframe_ret->ready_jiffies64)); + didbg_vframe_out_save(vframe_ret); + + dim_tr_ops.post_get(vframe_ret->omx_index); + } else { + dim_tr_ops.post_get2(3); + } + + if (!dimp_get(eDI_MP_post_wr_en) && + ppost->run_early_proc_fun_flag && + vframe_ret) { + if (vframe_ret->early_process_fun == do_pre_only_fun) + vframe_ret->early_process_fun(vframe_ret->private_data, + vframe_ret); + } + return vframe_ret; +} + +void di_vf_l_put(struct vframe_s *vf, unsigned char channel) +{ + struct di_buf_s *di_buf = NULL; + ulong irq_flag2 = 0; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_post_stru_s *ppost = get_post_stru(channel); + + dim_print("%s:ch[%d]\n", __func__, channel); + + if (ppre->bypass_flag) { + pw_vf_put(vf, channel); + pw_vf_notify_provider(channel, + VFRAME_EVENT_RECEIVER_PUT, NULL); + if (!IS_ERR_OR_NULL(ppost->keep_buf)) + recycle_keep_buffer(channel); + return; + } +/* struct di_buf_s *p = NULL; */ +/* int itmp = 0; */ + if (!get_init_flag(channel) || + recovery_flag || + IS_ERR_OR_NULL(vf)) { + PR_ERR("%s: 0x%p\n", __func__, vf); + return; + } + if (di_blocking) + return; + dim_log_buffer_state("pu_", channel); + di_buf = (struct di_buf_s *)vf->private_data; + if (IS_ERR_OR_NULL(di_buf)) { + pw_vf_put(vf, channel); + pw_vf_notify_provider(channel, + VFRAME_EVENT_RECEIVER_PUT, NULL); + PR_ERR("%s: get vframe %p without di buf\n", + __func__, vf); + return; + } +#if 0 + if (ppost->keep_buf == di_buf) { + pr_info("[DI]recycle buffer %d, get cnt %d.\n", + di_buf->index, disp_frame_count); + recycle_keep_buffer(channel); + } +#else + +#endif + + if (di_buf->type == VFRAME_TYPE_POST + ) { +#if 0 + dim_print("%s:put:%d\n", __func__, di_buf->index); + + di_lock_irqfiq_save(irq_flag2); + + if (is_in_queue(channel, di_buf, QUEUE_DISPLAY)) { + if (!atomic_dec_and_test(&di_buf->di_cnt)) + dim_print("%s,di_cnt > 0\n", __func__); + dim_print("%s:put:%d\n", __func__, di_buf->index); + recycle_vframe_type_post(di_buf, channel); + } else { + dim_print("%s: %s[%d] not in display list\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index); + } + di_unlock_irqfiq_restore(irq_flag2); +#ifdef DI_BUFFER_DEBUG + recycle_vframe_type_post_print(di_buf, __func__, __LINE__); +#endif +#else + pw_queue_in(channel, QUE_POST_BACK, di_buf->index); +#endif + } else { + di_lock_irqfiq_save(irq_flag2); + queue_in(channel, di_buf, QUEUE_RECYCLE); + di_unlock_irqfiq_restore(irq_flag2); + + dim_print("%s: %s[%d] =>recycle_list\n", __func__, + vframe_type_name[di_buf->type], di_buf->index); + } + + task_send_ready(); +} + +void dim_recycle_post_back(unsigned int channel) +{ + struct di_buf_s *di_buf = NULL; + unsigned int post_buf_index; + struct di_buf_s *pbuf_post = get_buf_post(channel); + ulong irq_flag2 = 0; + + struct di_post_stru_s *ppost = get_post_stru(channel); + + if (pw_queue_empty(channel, QUE_POST_BACK)) + return; + + while (pw_queue_out(channel, QUE_POST_BACK, &post_buf_index)) { + /*pr_info("dp2:%d\n", post_buf_index);*/ + if (post_buf_index >= MAX_POST_BUF_NUM) { + PR_ERR("%s:index is overlfow[%d]\n", + __func__, post_buf_index); + break; + } + dim_print("di_back:%d\n", post_buf_index); + di_lock_irqfiq_save(irq_flag2); /**/ + + di_buf = &pbuf_post[post_buf_index]; + if (!atomic_dec_and_test(&di_buf->di_cnt)) + PR_ERR("%s,di_cnt > 0\n", __func__); + recycle_vframe_type_post(di_buf, channel); + di_unlock_irqfiq_restore(irq_flag2); + } + /*back keep_buf:*/ + if (ppost->keep_buf_post) { + PR_INF("ch[%d]:%s:%d\n", + channel, + __func__, + ppost->keep_buf_post->index); + di_lock_irqfiq_save(irq_flag2); /**/ + di_que_in(channel, QUE_POST_FREE, ppost->keep_buf_post); + di_unlock_irqfiq_restore(irq_flag2); + ppost->keep_buf_post = NULL; + } +} + +struct vframe_s *di_vf_l_peek(unsigned int channel) +{ + struct vframe_s *vframe_ret = NULL; + struct di_buf_s *di_buf = NULL; + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + /*dim_print("%s:ch[%d]\n",__func__, channel);*/ + + di_sum_inc(channel, eDI_SUM_O_PEEK_CNT); + if (ppre->bypass_flag) { + dim_tr_ops.post_peek(0); + return pw_vf_peek(channel); + } + if (!get_init_flag(channel) || + recovery_flag || + di_blocking || + !get_reg_flag(channel) || + dump_state_flag) { + dim_tr_ops.post_peek(1); + return NULL; + } + + /**************************/ + if (list_count(channel, QUEUE_DISPLAY) > DI_POST_GET_LIMIT) { + dim_tr_ops.post_peek(2); + return NULL; + } + /**************************/ + dim_log_buffer_state("pek", channel); + +#ifdef SUPPORT_START_FRAME_HOLD + if ((disp_frame_count == 0) && (dim_is_bypass(NULL, channel) == 0)) { + int ready_count = di_que_list_count(channel, QUE_POST_READY); + + if (ready_count > start_frame_hold_count) { + di_buf = di_que_peek(channel, QUE_POST_READY); + if (di_buf) + vframe_ret = di_buf->vframe; + } + } else +#endif + { + if (!di_que_is_empty(channel, QUE_POST_READY)) { + di_buf = di_que_peek(channel, QUE_POST_READY); + if (di_buf) + vframe_ret = di_buf->vframe; + } + } +#ifdef DI_BUFFER_DEBUG + if (vframe_ret) + dim_print("%s: %s[%d]:%x\n", __func__, + vframe_type_name[di_buf->type], + di_buf->index, vframe_ret); +#endif + if (vframe_ret) + dim_tr_ops.post_peek(9); + else + dim_tr_ops.post_peek(4); + return vframe_ret; +} + +int di_vf_l_states(struct vframe_states *states, unsigned int channel) +{ + struct di_mm_s *mm = dim_mm_get(); + + /*pr_info("%s: ch[%d]\n", __func__, channel);*/ + if (!states) + return -1; + states->vf_pool_size = mm->sts.num_local; + states->buf_free_num = list_count(channel, QUEUE_LOCAL_FREE); + + states->buf_avail_num = di_que_list_count(channel, QUE_POST_READY); + states->buf_recycle_num = list_count(channel, QUEUE_RECYCLE); + if (dimp_get(eDI_MP_di_dbg_mask) & 0x1) { + di_pr_info("di-pre-ready-num:%d\n", + /*new que list_count(channel, QUEUE_PRE_READY));*/ + di_que_list_count(channel, QUE_PRE_READY)); + di_pr_info("di-display-num:%d\n", + list_count(channel, QUEUE_DISPLAY)); + } + return 0; +} + +/**********************************************/ + +/***************************** + * di driver file_operations + * + ******************************/ +#if 0 /*move to di_sys.c*/ +static int di_open(struct inode *node, struct file *file) +{ + di_dev_t *di_in_devp; + +/* Get the per-device structure that contains this cdev */ + di_in_devp = container_of(node->i_cdev, di_dev_t, cdev); + file->private_data = di_in_devp; + + return 0; +} + +static int di_release(struct inode *node, struct file *file) +{ +/* di_dev_t *di_in_devp = file->private_data; */ + +/* Reset file pointer */ + +/* Release some other fields */ + file->private_data = NULL; + return 0; +} + +#endif /*move to di_sys.c*/ + +static struct di_pq_parm_s *di_pq_parm_create(struct am_pq_parm_s *pq_parm_p) +{ + struct di_pq_parm_s *pq_ptr = NULL; + struct am_reg_s *am_reg_p = NULL; + size_t mem_size = 0; + + pq_ptr = vzalloc(sizeof(*pq_ptr)); + mem_size = sizeof(struct am_pq_parm_s); + memcpy(&pq_ptr->pq_parm, pq_parm_p, mem_size); + mem_size = sizeof(struct am_reg_s) * pq_parm_p->table_len; + am_reg_p = vzalloc(mem_size); + if (!am_reg_p) { + vfree(pq_ptr); + PR_ERR("alloc pq table memory errors\n"); + return NULL; + } + pq_ptr->regs = am_reg_p; + + return pq_ptr; +} + +static void di_pq_parm_destroy(struct di_pq_parm_s *pq_ptr) +{ + if (!pq_ptr) { + PR_ERR("%s pq parm pointer null.\n", __func__); + return; + } + vfree(pq_ptr->regs); + vfree(pq_ptr); +} + +/*move from ioctrl*/ +long dim_pq_load_io(unsigned long arg) +{ + long ret = 0, tab_flag = 0; + di_dev_t *di_devp; + void __user *argp = (void __user *)arg; + size_t mm_size = 0; + struct am_pq_parm_s tmp_pq_s = {0}; + struct di_pq_parm_s *di_pq_ptr = NULL; + struct di_dev_s *de_devp = get_dim_de_devp(); + unsigned int channel = 0; /*fix to channel 0*/ + + di_devp = de_devp; + + mm_size = sizeof(struct am_pq_parm_s); + if (copy_from_user(&tmp_pq_s, argp, mm_size)) { + PR_ERR("set pq parm errors\n"); + return -EFAULT; + } + if (tmp_pq_s.table_len >= TABLE_LEN_MAX) { + PR_ERR("load 0x%x wrong pq table_len.\n", + tmp_pq_s.table_len); + return -EFAULT; + } + tab_flag = TABLE_NAME_DI | TABLE_NAME_NR | TABLE_NAME_MCDI | + TABLE_NAME_DEBLOCK | TABLE_NAME_DEMOSQUITO; + if (tmp_pq_s.table_name & tab_flag) { + pr_info("[DI] load 0x%x pq table len %u %s.\n", + tmp_pq_s.table_name, tmp_pq_s.table_len, + get_init_flag(channel) ? "directly" : "later"); + } else { + PR_ERR("load 0x%x wrong pq table.\n", + tmp_pq_s.table_name); + return -EFAULT; + } + di_pq_ptr = di_pq_parm_create(&tmp_pq_s); + if (!di_pq_ptr) { + PR_ERR("allocat pq parm struct error.\n"); + return -EFAULT; + } + argp = (void __user *)tmp_pq_s.table_ptr; + mm_size = tmp_pq_s.table_len * sizeof(struct am_reg_s); + if (copy_from_user(di_pq_ptr->regs, argp, mm_size)) { + PR_ERR("user copy pq table errors\n"); + return -EFAULT; + } + if (get_init_flag(channel)) { + dimh_load_regs(di_pq_ptr); + di_pq_parm_destroy(di_pq_ptr); + + return ret; + } + if (atomic_read(&de_devp->pq_flag) == 0) { + atomic_set(&de_devp->pq_flag, 1); + if (di_devp->flags & DI_LOAD_REG_FLAG) { + struct di_pq_parm_s *pos = NULL, *tmp = NULL; + + list_for_each_entry_safe(pos, tmp, + &di_devp->pq_table_list, list) { + if (di_pq_ptr->pq_parm.table_name == + pos->pq_parm.table_name) { + pr_info("[DI] remove 0x%x table.\n", + pos->pq_parm.table_name); + list_del(&pos->list); + di_pq_parm_destroy(pos); + } + } + } + list_add_tail(&di_pq_ptr->list, + &di_devp->pq_table_list); + di_devp->flags |= DI_LOAD_REG_FLAG; + atomic_set(&de_devp->pq_flag, 0); + } else { + PR_ERR("please retry table name 0x%x.\n", + di_pq_ptr->pq_parm.table_name); + di_pq_parm_destroy(di_pq_ptr); + ret = -EFAULT; + } + + return ret; +} + +#if 0 /*#ifdef CONFIG_AMLOGIC_MEDIA_RDMA*/ +unsigned int dim_RDMA_RD_BITS(unsigned int adr, unsigned int start, + unsigned int len) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (de_devp->rdma_handle && di_pre_rdma_enable) + return rdma_read_reg(de_devp->rdma_handle, adr) & + (((1 << len) - 1) << start); + else + return Rd_reg_bits(adr, start, len); +} + +unsigned int dim_RDMA_WR(unsigned int adr, unsigned int val) +{ + unsigned int channel = get_current_channel(); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (is_need_stop_reg(adr)) + return 0; + + if (de_devp->rdma_handle > 0 && di_pre_rdma_enable) { + if (ppre->field_count_for_cont < 1) + dim_DI_Wr(adr, val); + else + rdma_write_reg(de_devp->rdma_handle, adr, val); + return 0; + } + + dim_DI_Wr(adr, val); + return 1; +} + +unsigned int dim_RDMA_RD(unsigned int adr) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (de_devp->rdma_handle > 0 && di_pre_rdma_enable) + return rdma_read_reg(de_devp->rdma_handle, adr); + else + return Rd(adr); +} + +unsigned int dim_RDMA_WR_BITS(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len) +{ + unsigned int channel = get_current_channel(); + struct di_pre_stru_s *ppre = get_pre_stru(channel); + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (is_need_stop_reg(adr)) + return 0; + + if (de_devp->rdma_handle > 0 && di_pre_rdma_enable) { + if (ppre->field_count_for_cont < 1) + dim_DI_Wr_reg_bits(adr, val, start, len); + else + rdma_write_reg_bits(de_devp->rdma_handle, + adr, val, start, len); + return 0; + } + dim_DI_Wr_reg_bits(adr, val, start, len); + return 1; +} +#else +unsigned int dim_RDMA_RD_BITS(unsigned int adr, unsigned int start, + unsigned int len) +{ + return Rd_reg_bits(adr, start, len); +} + +unsigned int dim_RDMA_WR(unsigned int adr, unsigned int val) +{ + dim_DI_Wr(adr, val); + return 1; +} + +unsigned int dim_RDMA_RD(unsigned int adr) +{ + return Rd(adr); +} + +unsigned int dim_RDMA_WR_BITS(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len) +{ + dim_DI_Wr_reg_bits(adr, val, start, len); + return 1; +} +#endif + +void dim_set_di_flag(void) +{ + if (is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { + dimp_set(eDI_MP_mcpre_en, 1); + mc_mem_alloc = true; + dimp_set(eDI_MP_pulldown_enable, 0); + di_pre_rdma_enable = false; + /* + * txlx atsc 1080i ei only will cause flicker + * when full to small win in home screen + */ + + dimp_set(eDI_MP_di_vscale_skip_enable, + (is_meson_txlx_cpu() || + is_meson_txhd_cpu()) ? 12 : 4); + /*use_2_interlace_buff = is_meson_gxlx_cpu()?0:1;*/ + dimp_set(eDI_MP_use_2_interlace_buff, + is_meson_gxlx_cpu() ? 0 : 1); + if (is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) { + dimp_set(eDI_MP_full_422_pack, 1); + } + + if (dimp_get(eDI_MP_nr10bit_support)) { + dimp_set(eDI_MP_di_force_bit_mode, 10); + } else { + dimp_set(eDI_MP_di_force_bit_mode, 8); + dimp_set(eDI_MP_full_422_pack, 0); + } + + dimp_set(eDI_MP_post_hold_line, + (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu() || + is_meson_sm1_cpu()) ? 10 : 17); + } else { + /*post_hold_line = 8;*/ /*2019-01-10: from VLSI feijun*/ + dimp_set(eDI_MP_post_hold_line, 8); + dimp_set(eDI_MP_mcpre_en, 0); + dimp_set(eDI_MP_pulldown_enable, 0); + di_pre_rdma_enable = false; + dimp_set(eDI_MP_di_vscale_skip_enable, 4); + dimp_set(eDI_MP_use_2_interlace_buff, 0); + dimp_set(eDI_MP_di_force_bit_mode, 8); + } + /*if (is_meson_tl1_cpu() || is_meson_tm2_cpu())*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dimp_set(eDI_MP_pulldown_enable, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + intr_mode = 3; + if (di_pre_rdma_enable) { + pldn_dly = 1; + pldn_dly1 = 1; + } else { + pldn_dly = 2; + pldn_dly1 = 2; + } + + get_ops_mtn()->mtn_int_combing_glbmot(); +} + +#if 0 /*move to di_sys.c*/ +static const struct reserved_mem_ops rmem_di_ops = { + .device_init = rmem_di_device_init, + .device_release = rmem_di_device_release, +}; + +static int __init rmem_di_setup(struct reserved_mem *rmem) +{ + rmem->ops = &rmem_di_ops; +/* rmem->priv = cma; */ + + di_pr_info( + "DI reserved memory: created CMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + + return 0; +} + +RESERVEDMEM_OF_DECLARE(di, "amlogic, di-mem", rmem_di_setup); +#endif + +void dim_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) +{ + int ret = 0; + unsigned int tmp_clk[2] = {0, 0}; + struct clk *vpu_clk = NULL; + struct clk *clkb_tmp_comp = NULL; + + vpu_clk = clk_get(dev, "vpu_mux"); + if (IS_ERR(vpu_clk)) + PR_ERR("%s: get clk vpu error.\n", __func__); + else + clk_prepare_enable(vpu_clk); + + ret = of_property_read_u32_array(dev->of_node, "clock-range", + tmp_clk, 2); + if (ret) { + pdev->clkb_min_rate = 250000000; + pdev->clkb_max_rate = 500000000; + } else { + pdev->clkb_min_rate = tmp_clk[0] * 1000000; + pdev->clkb_max_rate = tmp_clk[1] * 1000000; + } + pr_info("DI: vpu clkb <%lu, %lu>\n", pdev->clkb_min_rate, + pdev->clkb_max_rate); + #ifdef CLK_TREE_SUPPORT + pdev->vpu_clkb = clk_get(dev, "vpu_clkb_composite"); + if (is_meson_tl1_cpu()) { + clkb_tmp_comp = clk_get(dev, "vpu_clkb_tmp_composite"); + if (IS_ERR(clkb_tmp_comp)) { + PR_ERR("clkb_tmp_comp error\n"); + } else { + /*ary: this make clk from 500 to 666?*/ + if (!IS_ERR(vpu_clk)) + clk_set_parent(clkb_tmp_comp, vpu_clk); + } + } + + if (IS_ERR(pdev->vpu_clkb)) { + PR_ERR("%s: get vpu clkb gate error.\n", __func__); + } else { + clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); + pr_info("get clkb rate:%ld\n", clk_get_rate(pdev->vpu_clkb)); + } + + #endif +} + +module_param_named(invert_top_bot, invert_top_bot, int, 0664); + +#ifdef SUPPORT_START_FRAME_HOLD +module_param_named(start_frame_hold_count, start_frame_hold_count, int, 0664); +#endif + +#ifdef DET3D + +MODULE_PARM_DESC(det3d_mode, "\n det3d_mode\n"); +module_param(det3d_mode, uint, 0664); +#endif + +module_param_array(di_stop_reg_addr, uint, &num_di_stop_reg_addr, + 0664); + +module_param_named(overturn, overturn, bool, 0664); + +#ifdef DEBUG_SUPPORT +#ifdef RUN_DI_PROCESS_IN_IRQ +module_param_named(input2pre, input2pre, uint, 0664); +module_param_named(input2pre_buf_miss_count, input2pre_buf_miss_count, + uint, 0664); +module_param_named(input2pre_proc_miss_count, input2pre_proc_miss_count, + uint, 0664); +module_param_named(input2pre_miss_policy, input2pre_miss_policy, uint, 0664); +module_param_named(input2pre_throw_count, input2pre_throw_count, uint, 0664); +#endif +#ifdef SUPPORT_MPEG_TO_VDIN +module_param_named(mpeg2vdin_en, mpeg2vdin_en, int, 0664); +module_param_named(mpeg2vdin_flag, mpeg2vdin_flag, int, 0664); +#endif +module_param_named(di_pre_rdma_enable, di_pre_rdma_enable, uint, 0664); +module_param_named(pldn_dly, pldn_dly, uint, 0644); +module_param_named(pldn_dly1, pldn_dly1, uint, 0644); +module_param_named(di_reg_unreg_cnt, di_reg_unreg_cnt, int, 0664); +module_param_named(bypass_pre, bypass_pre, int, 0664); +module_param_named(frame_count, frame_count, int, 0664); +#endif + +int dim_seq_file_module_para_di(struct seq_file *seq) +{ + seq_puts(seq, "di---------------\n"); + +#ifdef DET3D + seq_printf(seq, "%-15s:%d\n", "det3d_frame_cnt", det3d_frame_cnt); +#endif + +#ifdef SUPPORT_START_FRAME_HOLD + seq_printf(seq, "%-15s:%d\n", "start_frame_hold_count", + start_frame_hold_count); +#endif + seq_printf(seq, "%-15s:%ld\n", "same_field_top_count", + same_field_top_count); + seq_printf(seq, "%-15s:%ld\n", "same_field_bot_count", + same_field_bot_count); + + seq_printf(seq, "%-15s:%d\n", "overturn", overturn); + +#ifdef DEBUG_SUPPORT +#ifdef RUN_DI_PROCESS_IN_IRQ + seq_printf(seq, "%-15s:%d\n", "input2pre", input2pre); + seq_printf(seq, "%-15s:%d\n", "input2pre_buf_miss_count", + input2pre_buf_miss_count); + seq_printf(seq, "%-15s:%d\n", "input2pre_proc_miss_count", + input2pre_proc_miss_count); + seq_printf(seq, "%-15s:%d\n", "input2pre_miss_policy", + input2pre_miss_policy); + seq_printf(seq, "%-15s:%d\n", "input2pre_throw_count", + input2pre_throw_count); +#endif +#ifdef SUPPORT_MPEG_TO_VDIN + + seq_printf(seq, "%-15s:%d\n", "mpeg2vdin_en", mpeg2vdin_en); + seq_printf(seq, "%-15s:%d\n", "mpeg2vdin_flag", mpeg2vdin_flag); +#endif + seq_printf(seq, "%-15s:%d\n", "di_pre_rdma_enable", + di_pre_rdma_enable); + seq_printf(seq, "%-15s:%d\n", "pldn_dly", pldn_dly); + seq_printf(seq, "%-15s:%d\n", "pldn_dly1", pldn_dly1); + seq_printf(seq, "%-15s:%d\n", "di_reg_unreg_cnt", di_reg_unreg_cnt); + seq_printf(seq, "%-15s:%d\n", "bypass_pre", bypass_pre); + seq_printf(seq, "%-15s:%d\n", "frame_count", frame_count); +#endif +/******************************/ + +#ifdef DET3D + seq_printf(seq, "%-15s:%d\n", "det3d_mode", det3d_mode); +#endif + return 0; +} + +#if 0 /*move to di_sys.c*/ +MODULE_DESCRIPTION("AMLOGIC DEINTERLACE driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("4.0.0"); +#endif diff --git a/drivers/amlogic/media/di_multi/deinterlace.h b/drivers/amlogic/media/di_multi/deinterlace.h new file mode 100644 index 000000000000..96abc673f676 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace.h @@ -0,0 +1,658 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _DI_H +#define _DI_H +#include +#include +#include +#include + +#include "../di_local/di_local.h" +#include +#include +#include "deinterlace_hw.h" +#include "../deinterlace/di_pqa.h" + +/*trigger_pre_di_process param*/ +#define TRIGGER_PRE_BY_PUT 'p' +#define TRIGGER_PRE_BY_DE_IRQ 'i' +#define TRIGGER_PRE_BY_UNREG 'u' +/*di_timer_handle*/ +#define TRIGGER_PRE_BY_TIMER 't' +#define TRIGGER_PRE_BY_FORCE_UNREG 'f' +#define TRIGGER_PRE_BY_VFRAME_READY 'r' +#define TRIGGER_PRE_BY_PROVERDER_UNREG 'n' +#define TRIGGER_PRE_BY_DEBUG_DISABLE 'd' +#define TRIGGER_PRE_BY_PROVERDER_REG 'R' + +#define DI_RUN_FLAG_RUN 0 +#define DI_RUN_FLAG_PAUSE 1 +#define DI_RUN_FLAG_STEP 2 +#define DI_RUN_FLAG_STEP_DONE 3 + +#define USED_LOCAL_BUF_MAX 3 +#define BYPASS_GET_MAX_BUF_NUM 4 + +/* buffer management related */ +#define MAX_IN_BUF_NUM (4) +#define MAX_LOCAL_BUF_NUM (7) +#define MAX_POST_BUF_NUM (7) /*(5)*/ /* 16 */ + +#define VFRAME_TYPE_IN 1 +#define VFRAME_TYPE_LOCAL 2 +#define VFRAME_TYPE_POST 3 +#define VFRAME_TYPE_NUM 3 + +#define DI_POST_GET_LIMIT 4 +#define DI_PRE_READY_LIMIT 4 +/*vframe define*/ +#define vframe_t struct vframe_s + +#define is_from_vdin(vframe) ((vframe)->type & VIDTYPE_VIU_422) + +/* canvas defination */ +#define DI_USE_FIXED_CANVAS_IDX +/*#define DET3D */ +#undef SUPPORT_MPEG_TO_VDIN +#define CLK_TREE_SUPPORT +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA +#ifndef VSYNC_WR_MPEG_REG +#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val) +#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + aml_vcbus_update_bits((adr), \ + ((1 << (len)) - 1) << (start), (val) << (start)) + +#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr) +#endif +#endif + +#define IS_VDIN_SRC(src) ( \ + ((src) == VFRAME_SOURCE_TYPE_TUNER) || \ + ((src) == VFRAME_SOURCE_TYPE_CVBS) || \ + ((src) == VFRAME_SOURCE_TYPE_COMP) || \ + ((src) == VFRAME_SOURCE_TYPE_HDMI)) + +#define IS_I_SRC(vftype) ((vftype) & VIDTYPE_INTERLACE_BOTTOM) + +#define IS_COMP_MODE(vftype) ((vftype) & VIDTYPE_COMPRESS) + +enum process_fun_index_e { + PROCESS_FUN_NULL = 0, + PROCESS_FUN_DI, + PROCESS_FUN_PD, + PROCESS_FUN_PROG, + PROCESS_FUN_BOB +}; + +#define process_fun_index_t enum process_fun_index_e + +enum canvas_idx_e { + NR_CANVAS, + MTN_CANVAS, + MV_CANVAS, +}; + +#define pulldown_mode_t enum pulldown_mode_e +struct di_buf_s { + struct vframe_s *vframe; + int index; /* index in vframe_in_dup[] or vframe_in[], + * only for type of VFRAME_TYPE_IN + */ + int post_proc_flag; /* 0,no post di; 1, normal post di; + * 2, edge only; 3, dummy + */ + int new_format_flag; + int type; + int throw_flag; + int invert_top_bot_flag; + int seq; + int pre_ref_count; /* none zero, is used by mem_mif, + * chan2_mif, or wr_buf + */ + int post_ref_count; /* none zero, is used by post process */ + int queue_index; + /*below for type of VFRAME_TYPE_LOCAL */ + unsigned long nr_adr; + int nr_canvas_idx; + unsigned long mtn_adr; + int mtn_canvas_idx; + unsigned long cnt_adr; + int cnt_canvas_idx; + unsigned long mcinfo_adr; + int mcinfo_canvas_idx; + unsigned long mcvec_adr; + int mcvec_canvas_idx; + struct mcinfo_pre_s { + unsigned int highvertfrqflg; + unsigned int motionparadoxflg; + unsigned int regs[26];/* reg 0x2fb0~0x2fc9 */ + } curr_field_mcinfo; + /* blend window */ + struct pulldown_detected_s + pd_config; + /* tff bff check result bit[1:0]*/ + unsigned int privated; + unsigned int canvas_config_flag; + /* 0,configed; 1,config type 1 (prog); + * 2, config type 2 (interlace) + */ + unsigned int canvas_height; + unsigned int canvas_height_mc; /*ary add for mc h is diff*/ + unsigned int canvas_width[3];/* nr/mtn/mv */ + process_fun_index_t process_fun_index; + int early_process_fun_index; + int left_right;/*1,left eye; 0,right eye in field alternative*/ + /*below for type of VFRAME_TYPE_POST*/ + struct di_buf_s *di_buf[2]; + struct di_buf_s *di_buf_dup_p[5]; + /* 0~4: n-2, n-1, n, n+1, n+2; n is the field to display*/ + /*0: n-2*/ + /*1: n-1*/ + /*2: n*/ + /*3: n+1*/ + /*4: n+2*/ + struct di_buf_s *di_wr_linked_buf; + /* debug for di-vf-get/put + * 1: after get + * 0: after put + */ + atomic_t di_cnt; + struct page *pages; + /*ary add */ + unsigned int channel; + unsigned int width_bk; /*move from ppre*/ +}; + +#define RDMA_DET3D_IRQ 0x20 +/* vdin0 rdma irq */ +#define RDMA_DEINT_IRQ 0x2 +#define RDMA_TABLE_SIZE ((PAGE_SIZE) << 1) + +#define MAX_CANVAS_WIDTH 1920 +#define MAX_CANVAS_HEIGHT 1088 + +/* #define DI_BUFFER_DEBUG */ + +#define DI_LOG_MTNINFO 0x02 +#define DI_LOG_PULLDOWN 0x10 +#define DI_LOG_BUFFER_STATE 0x20 +#define DI_LOG_TIMESTAMP 0x100 +#define DI_LOG_PRECISE_TIMESTAMP 0x200 +#define DI_LOG_QUEUE 0x40 +#define DI_LOG_VFRAME 0x80 + +#if 0 +#define QUEUE_LOCAL_FREE 0 +#define QUEUE_IN_FREE 1 +#define QUEUE_PRE_READY 2 +#define QUEUE_POST_FREE 3 +#define QUEUE_POST_READY 4 +#define QUEUE_RECYCLE 5 +#define QUEUE_DISPLAY 6 +#define QUEUE_TMP 7 +#define QUEUE_POST_DOING 8 +#define QUEUE_NUM 9 +#else +#define QUEUE_LOCAL_FREE 0 +#define QUEUE_RECYCLE 1 /* 5 */ +#define QUEUE_DISPLAY 2 /* 6 */ +#define QUEUE_TMP 3 /* 7 */ +#define QUEUE_POST_DOING 4 /* 8 */ + +#define QUEUE_IN_FREE 5 /* 1 */ +#define QUEUE_PRE_READY 6 /* 2 */ +#define QUEUE_POST_FREE 7 /* 3 */ +#define QUEUE_POST_READY 8 /* 4 QUE_POST_READY */ + +/*new use this for put back control*/ +#define QUEUE_POST_PUT_BACK (9) + +#define QUEUE_NUM 5 /* 9 */ +#define QUEUE_NEW_THD_MIN (QUEUE_IN_FREE - 1) +#define QUEUE_NEW_THD_MAX (QUEUE_POST_READY + 1) + +#endif + +#define queue_t struct queue_s + +#define VFM_NAME "deinterlace" + +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +void enable_rdma(int enable_flag); +int VSYNC_WR_MPEG_REG(u32 adr, u32 val); +int VSYNC_WR_MPEG_REG_BITS(u32 adr, u32 val, u32 start, u32 len); +u32 VSYNC_RD_MPEG_REG(u32 adr); +bool is_vsync_rdma_enable(void); +#else +#ifndef VSYNC_WR_MPEG_REG +#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val) +#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + aml_vcbus_update_bits((adr), \ + ((1 << (len)) - 1) << (start), (val) << (start)) + +#define VSYNC_RD_MPEG_REG(adr) aml_read_vcbus(adr) +#endif +#endif + +#define DI_COUNT 1 +#define DI_MAP_FLAG 0x1 +#define DI_SUSPEND_FLAG 0x2 +#define DI_LOAD_REG_FLAG 0x4 +#define DI_VPU_CLKB_SET 0x8 + +struct di_dev_s { + dev_t devt; + struct cdev cdev; /* The cdev structure */ + struct device *dev; + struct platform_device *pdev; + dev_t devno; + struct class *pclss; + + bool sema_flg; /*di_sema_init_flag*/ + + struct task_struct *task; + struct clk *vpu_clkb; + unsigned long clkb_max_rate; + unsigned long clkb_min_rate; + struct list_head pq_table_list; + atomic_t pq_flag; + unsigned char di_event; + unsigned int pre_irq; + unsigned int post_irq; + unsigned int flags; + unsigned long jiffy; + unsigned long mem_start; + unsigned int mem_size; + bool mem_flg; /*ary add for make sure mem is ok*/ + unsigned int buffer_size; + unsigned int post_buffer_size; + unsigned int buf_num_avail; + int rdma_handle; + /* is support nr10bit */ + unsigned int nr10bit_support; + /* is DI support post wr to mem for OMX */ + unsigned int post_wr_support; + unsigned int nrds_enable; + unsigned int pps_enable; + unsigned int h_sc_down_en;/*sm1, tm2 ...*/ + /*struct mutex cma_mutex;*/ + unsigned int flag_cma; + struct page *total_pages; + struct dentry *dbg_root; /*dbg_fs*/ + /***************************/ + /*struct di_data_l_s data_l;*/ + void *data_l; + +}; + +struct di_pre_stru_s { +/* pre input */ + struct DI_MIF_s di_inp_mif; + struct DI_MIF_s di_mem_mif; + struct DI_MIF_s di_chan2_mif; + struct di_buf_s *di_inp_buf; + struct di_buf_s *di_post_inp_buf; + struct di_buf_s *di_inp_buf_next; + /* p_asi_next: ary:add for p */ + struct di_buf_s *p_asi_next; + struct di_buf_s *di_mem_buf_dup_p; + struct di_buf_s *di_chan2_buf_dup_p; +/* pre output */ + struct DI_SIM_MIF_s di_nrwr_mif; + struct DI_SIM_MIF_s di_mtnwr_mif; + struct di_buf_s *di_wr_buf; + struct di_buf_s *di_post_wr_buf; + struct DI_SIM_MIF_s di_contp2rd_mif; + struct DI_SIM_MIF_s di_contprd_mif; + struct DI_SIM_MIF_s di_contwr_mif; + int field_count_for_cont; +/* + * 0 (f0,null,f0)->nr0, + * 1 (f1,nr0,f1)->nr1_cnt, + * 2 (f2,nr1_cnt,nr0)->nr2_cnt + * 3 (f3,nr2_cnt,nr1_cnt)->nr3_cnt + */ + struct DI_MC_MIF_s di_mcinford_mif; + struct DI_MC_MIF_s di_mcvecwr_mif; + struct DI_MC_MIF_s di_mcinfowr_mif; +/* pre state */ + int in_seq; + int recycle_seq; + int pre_ready_seq; + + int pre_de_busy; /* 1 if pre_de is not done */ + int pre_de_process_flag; /* flag when dim_pre_de_process done */ + int pre_de_clear_flag; + /* flag is set when VFRAME_EVENT_PROVIDER_UNREG*/ + int unreg_req_flag_cnt; + + int reg_req_flag_cnt; + int force_unreg_req_flag; + int disable_req_flag; + /* current source info */ + int cur_width; + int cur_height; + int cur_inp_type; + int cur_source_type; + int cur_sig_fmt; + unsigned int orientation; + int cur_prog_flag; /* 1 for progressive source */ +/* valid only when prog_proc_type is 0, for + * progressive source: top field 1, bot field 0 + */ + int source_change_flag; +/* input size change flag, 1: need reconfig pre/nr/dnr size */ +/* 0: not need config pre/nr/dnr size*/ + bool input_size_change_flag; +/* true: bypass di all logic, false: not bypass */ + bool bypass_flag; + unsigned char prog_proc_type; +/* set by prog_proc_config when source is vdin,0:use 2 i + * serial buffer,1:use 1 p buffer,3:use 2 i paralleling buffer + */ +/* ary: loacal play p mode is 0 + * local play i mode is 0 + */ + + unsigned char buf_alloc_mode; +/* alloc di buf as p or i;0: alloc buf as i; + * 1: alloc buf as p; + */ + unsigned char madi_enable; + unsigned char mcdi_enable; + unsigned int pps_dstw; /*no use ?*/ + unsigned int pps_dsth; /*no use ?*/ + int left_right;/*1,left eye; 0,right eye in field alternative*/ +/*input2pre*/ + int bypass_start_count; +/* need discard some vframe when input2pre => bypass */ + unsigned char vdin2nr; + enum tvin_trans_fmt source_trans_fmt; + enum tvin_trans_fmt det3d_trans_fmt; + unsigned int det_lr; + unsigned int det_tp; + unsigned int det_la; + unsigned int det_null; + unsigned int width_bk; +#ifdef DET3D + int vframe_interleave_flag; +#endif +/**/ + int pre_de_irq_timeout_count; + int pre_throw_flag; + int bad_frame_throw_count; +/*for static pic*/ + int static_frame_count; + bool force_interlace; + bool bypass_pre; + bool invert_flag; + bool vdin_source; + int nr_size; + int count_size; + int mcinfo_size; + int mv_size; + int mtn_size; + + int cma_release_req; + /* for performance debug */ + unsigned long irq_time[2]; + /* combing adaptive */ + struct combing_status_s *mtn_status; + bool combing_fix_en; + unsigned int comb_mode; +}; + +struct di_post_stru_s { + struct DI_MIF_s di_buf0_mif; + struct DI_MIF_s di_buf1_mif; + struct DI_MIF_s di_buf2_mif; + struct DI_SIM_MIF_s di_diwr_mif; + struct DI_SIM_MIF_s di_mtnprd_mif; + struct DI_MC_MIF_s di_mcvecrd_mif; + /*post doing buf and write buf to post ready*/ + struct di_buf_s *cur_post_buf; + struct di_buf_s *keep_buf; + struct di_buf_s *keep_buf_post; /*ary add for keep post buf*/ + int update_post_reg_flag; + int run_early_proc_fun_flag; + int cur_disp_index; + int canvas_id; + int next_canvas_id; + bool toggle_flag; + bool vscale_skip_flag; + uint start_pts; + int buf_type; + int de_post_process_done; + int post_de_busy; + int di_post_num; + unsigned int post_peek_underflow; + unsigned int di_post_process_cnt; + unsigned int check_recycle_buf_cnt;/*cp to di_hpre_s*/ + /* performance debug */ + unsigned int post_wr_cnt; + unsigned long irq_time; + + /*frame cnt*/ + unsigned int frame_cnt; /*cnt for post process*/ +}; + +#define MAX_QUEUE_POOL_SIZE 256 +struct queue_s { + unsigned int num; + unsigned int in_idx; + unsigned int out_idx; + unsigned int type; +/* 0, first in first out; + * 1, general;2, fix position for di buf + */ + unsigned int pool[MAX_QUEUE_POOL_SIZE]; +}; + +struct di_buf_pool_s { + struct di_buf_s *di_buf_ptr; + unsigned int size; +}; + +struct dim_mm_s { + struct page *ppage; + unsigned long addr; +}; + +bool dim_mm_alloc(int cma_mode, size_t count, struct dim_mm_s *o); +bool dim_mm_release(int cma_mode, + struct page *pages, + int count, + unsigned long addr); + +unsigned char dim_is_bypass(vframe_t *vf_in, unsigned int channel); +bool dim_bypass_first_frame(unsigned int ch); + +int di_cnt_buf(int width, int height, int prog_flag, int mc_mm, + int bit10_support, int pack422); + +/*---get di state parameter---*/ +struct di_dev_s *get_dim_de_devp(void); + +const char *dim_get_version_s(void); +int dim_get_dump_state_flag(void); + +int dim_get_blocking(void); + +struct di_buf_s *dim_get_recovery_log_di_buf(void); + +unsigned long dim_get_reg_unreg_timeout_cnt(void); +struct vframe_s **dim_get_vframe_in(unsigned int ch); +int dim_check_recycle_buf(unsigned int channel); + +int dim_seq_file_module_para_di(struct seq_file *seq); +int dim_seq_file_module_para_hw(struct seq_file *seq); + +int dim_seq_file_module_para_film_fw1(struct seq_file *seq); +int dim_seq_file_module_para_mtn(struct seq_file *seq); + +int dim_seq_file_module_para_pps(struct seq_file *seq); + +int dim_seq_file_module_para_(struct seq_file *seq); + +/***********************/ + +unsigned int di_get_dts_nrds_en(void); +int di_get_disp_cnt(void); + +/*---------------------*/ +long dim_pq_load_io(unsigned long arg); +int dim_get_canvas(void); +unsigned int dim_cma_alloc_total(struct di_dev_s *de_devp); +irqreturn_t dim_irq(int irq, void *dev_instance); +irqreturn_t dim_post_irq(int irq, void *dev_instance); + +void dim_rdma_init(void); +void dim_rdma_exit(void); + +void dim_set_di_flag(void); +void dim_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev); + +void dim_log_buffer_state(unsigned char *tag, unsigned int channel); + +unsigned char dim_pre_de_buf_config(unsigned int channel); +void dim_pre_de_process(unsigned int channel); +void dim_pre_de_done_buf_config(unsigned int channel, bool flg_timeout); +void dim_pre_de_done_buf_clear(unsigned int channel); + +void di_reg_setting(unsigned int channel, struct vframe_s *vframe); +void di_reg_variable(unsigned int channel, struct vframe_s *vframe); + +void dim_unreg_process_irq(unsigned int channel); +void di_unreg_variable(unsigned int channel); +void di_unreg_setting(void); + +void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel); +void dim_unreg_process(unsigned int channel); + +int dim_process_post_vframe(unsigned int channel); +unsigned char dim_check_di_buf(struct di_buf_s *di_buf, int reason, + unsigned int channel); +int dim_do_post_wr_fun(void *arg, vframe_t *disp_vf); +int dim_post_process(void *arg, unsigned int zoom_start_x_lines, + unsigned int zoom_end_x_lines, + unsigned int zoom_start_y_lines, + unsigned int zoom_end_y_lines, vframe_t *disp_vf); +void dim_post_de_done_buf_config(unsigned int channel); +void dim_recycle_post_back(unsigned int channel); +void recycle_post_ready_local(struct di_buf_s *di_buf, + unsigned int channel); + +/*--------------------------*/ +unsigned char dim_vcry_get_flg(void); +void dim_vcry_flg_inc(void); +void dim_vcry_set_flg(unsigned char val); +/*--------------------------*/ +unsigned int dim_vcry_get_log_reason(void); +void dim_vcry_set_log_reason(unsigned int val); +/*--------------------------*/ +unsigned char dim_vcry_get_log_q_idx(void); +void dim_vcry_set_log_q_idx(unsigned int val); +/*--------------------------*/ +struct di_buf_s **dim_vcry_get_log_di_buf(void); +void dim_vcry_set_log_di_buf(struct di_buf_s *di_bufp); +void dim_vcry_set(unsigned int reason, unsigned int idx, + struct di_buf_s *di_bufp); + +const char *dim_get_vfm_type_name(unsigned int nub); + +bool dim_cma_top_alloc(unsigned int ch); +bool dim_cma_top_release(unsigned int ch); + +int dim_get_reg_unreg_cnt(void); +void dim_reg_timeout_inc(void); + +void dim_reg_process(unsigned int channel); +bool is_bypass2(struct vframe_s *vf_in, unsigned int ch); + +/*--------------------------*/ +int di_ori_event_unreg(unsigned int channel); +int di_ori_event_reg(void *data, unsigned int channel); +int di_ori_event_qurey_vdin2nr(unsigned int channel); +int di_ori_event_reset(unsigned int channel); +int di_ori_event_light_unreg(unsigned int channel); +int di_ori_event_light_unreg_revframe(unsigned int channel); +int di_ori_event_ready(unsigned int channel); +int di_ori_event_qurey_state(unsigned int channel); +void di_ori_event_set_3D(int type, void *data, unsigned int channel); + +/*--------------------------*/ +extern int pre_run_flag; +extern unsigned int dbg_first_cnt_pre; +extern spinlock_t plist_lock; + +void dim_dbg_pre_cnt(unsigned int channel, char *item); + +void diext_clk_b_sw(bool on); + +int di_vf_l_states(struct vframe_states *states, unsigned int channel); +struct vframe_s *di_vf_l_peek(unsigned int channel); +void di_vf_l_put(struct vframe_s *vf, unsigned char channel); +struct vframe_s *di_vf_l_get(unsigned int channel); + +unsigned char pre_p_asi_de_buf_config(unsigned int ch); + +/*---------------------*/ + +ssize_t +store_config(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +ssize_t +store_dbg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +ssize_t +store_dump_mem(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len); +ssize_t +store_log(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +ssize_t +show_vframe_status(struct device *dev, + struct device_attribute *attr, + char *buf); + +ssize_t dim_read_log(char *buf); + +/*---------------------*/ + +struct di_buf_s *dim_get_buf(unsigned int channel, + int queue_idx, int *start_pos); + +#define queue_for_each_entry(di_buf, channel, queue_idx, list) \ + for (itmp = 0; \ + ((di_buf = dim_get_buf(channel, queue_idx, &itmp)) != NULL);) + +#define di_dev_t struct di_dev_s + +#define di_pr_info(fmt, args ...) pr_info("DI: " fmt, ## args) + +#define pr_dbg(fmt, args ...) pr_debug("DI: " fmt, ## args) + +#define pr_error(fmt, args ...) pr_err("DI: " fmt, ## args) + +/*this is debug for buf*/ +/*#define DI_DEBUG_POST_BUF_FLOW (1)*/ + +#endif diff --git a/drivers/amlogic/media/di_multi/deinterlace_dbg.c b/drivers/amlogic/media/di_multi/deinterlace_dbg.c new file mode 100644 index 000000000000..153f6e07bbb5 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace_dbg.c @@ -0,0 +1,1214 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace_dbg.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "register.h" +#include "deinterlace_dbg.h" +#include "di_pps.h" +#include "nr_downscale.h" +#include +#include "deinterlace.h" + +#include "di_data_l.h" +#include "di_que.h" +#include "di_prc.h" +#include "di_pre.h" +#include "di_post.h" + +#include "di_vframe.h" + +/*2018-07-18 add debugfs*/ +#include +#include +/*2018-07-18 -----------*/ + +void dim_parse_cmd_params(char *buf_orig, char **parm) +{ + char *ps, *token; + char delim1[3] = " "; + char delim2[2] = "\n"; + unsigned int n = 0; + + strcat(delim1, delim2); + ps = buf_orig; + while (1) { + token = strsep(&ps, delim1); + if (!token) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } +} + +static const unsigned int size_reg_addr1[] = { + 0x1702, 0x1703, 0x2d01, + 0x2d01, 0x2d8f, 0x2d08, + 0x2d09, 0x2f00, 0x2f01, + 0x17d0, 0x17d1, 0x17d2, + 0x17d3, 0x17dd, 0x17de, + 0x17df, 0x17e0, 0x17f7, + 0x17f8, 0x17f9, 0x17fa, + 0x17c0, 0x17c1, 0x17a0, + 0x17a1, 0x17c3, 0x17c4, + 0x17cb, 0x17cc, 0x17a3, + 0x17a4, 0x17a5, 0x17a6, + 0x2f92, 0x2f93, 0x2f95, + 0x2f96, 0x2f98, 0x2f99, + 0x2f9b, 0x2f9c, 0x2f65, + 0x2f66, 0x2f67, 0x2f68, + 0x1a53, 0x1a54, 0x1a55, + 0x1a56, 0x17ea, 0x17eb, + 0x17ec, 0x17ed, 0x2012, + 0x2013, 0x2014, 0x2015, + 0xffff +}; + +/*g12 new added*/ +static const unsigned int size_reg_addr2[] = { + 0x37d2, 0x37d3, 0x37d7, + 0x37d8, 0x37dc, 0x37dd, + 0x37e1, 0x37e2, 0x37e6, + 0x37e7, 0x37e9, 0x37ea, + 0x37ed, 0x37ee, 0x37f1, + 0x37f2, 0x37f4, 0x37f5, + 0x37f6, 0x37f8, 0x3751, + 0x3752, 0x376e, 0x376f, + 0x37f9, 0x37fa, 0x37fc, + 0x3740, 0x3757, 0x3762, + 0xffff +}; + +/*2018-08-17 add debugfs*/ +static int seq_file_dump_di_reg_show(struct seq_file *seq, void *v) +{ + unsigned int i = 0, base_addr = 0; + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + base_addr = 0xff900000; + else + base_addr = 0xd0100000; + + seq_puts(seq, "----dump di reg----\n"); + seq_puts(seq, "----dump size reg---\n"); + /*txl crash when dump 0x37d2~0x3762 of size_reg_addr*/ + for (i = 0; size_reg_addr1[i] != 0xffff; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((size_reg_addr1[i]) << 2), + size_reg_addr1[i], dim_RDMA_RD(size_reg_addr1[i])); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + for (i = 0; size_reg_addr2[i] != 0xffff; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((size_reg_addr2[i]) << 2), + size_reg_addr2[i], + dim_RDMA_RD(size_reg_addr2[i])); + } + for (i = 0; i < 255; i++) { + if (i == 0x45) + seq_puts(seq, "----nr reg----"); + if (i == 0x80) + seq_puts(seq, "----3d reg----"); + if (i == 0x9e) + seq_puts(seq, "---nr reg done---"); + if (i == 0x9c) + seq_puts(seq, "---3d reg done---"); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x1700 + i) << 2), + 0x1700 + i, dim_RDMA_RD(0x1700 + i)); + } + for (i = 0; i < 4; i++) { + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x20ab + i) << 2), + 0x20ab + i, dim_RDMA_RD(0x20ab + i)); + } + seq_puts(seq, "----dump mcdi reg----\n"); + for (i = 0; i < 201; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2f00 + i) << 2), + 0x2f00 + i, dim_RDMA_RD(0x2f00 + i)); + seq_puts(seq, "----dump pulldown reg----\n"); + for (i = 0; i < 26; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2fd0 + i) << 2), + 0x2fd0 + i, dim_RDMA_RD(0x2fd0 + i)); + seq_puts(seq, "----dump bit mode reg----\n"); + for (i = 0; i < 4; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x20a7 + i) << 2), + 0x20a7 + i, dim_RDMA_RD(0x20a7 + i)); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (0x2022 << 2), + 0x2022, dim_RDMA_RD(0x2022)); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (0x17c1 << 2), + 0x17c1, dim_RDMA_RD(0x17c1)); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (0x17c2 << 2), + 0x17c2, dim_RDMA_RD(0x17c2)); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (0x1aa7 << 2), + 0x1aa7, dim_RDMA_RD(0x1aa7)); + seq_puts(seq, "----dump dnr reg----\n"); + for (i = 0; i < 29; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2d00 + i) << 2), + 0x2d00 + i, dim_RDMA_RD(0x2d00 + i)); + seq_puts(seq, "----dump if0 reg----\n"); + for (i = 0; i < 26; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x1a60 + i) << 2), + 0x1a50 + i, dim_RDMA_RD(0x1a50 + i)); + seq_puts(seq, "----dump gate reg----\n"); + seq_printf(seq, "[0x%x][0x1718]=0x%x\n", + base_addr + ((0x1718) << 2), + dim_RDMA_RD(0x1718)); + for (i = 0; i < 5; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2006 + i) << 2), + 0x2006 + i, dim_RDMA_RD(0x2006 + i)); + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2dff) << 2), + 0x2dff, dim_RDMA_RD(0x2dff)); + seq_puts(seq, "----dump if2 reg----\n"); + for (i = 0; i < 29; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2010 + i) << 2), + 0x2010 + i, dim_RDMA_RD(0x2010 + i)); + if (!is_meson_txl_cpu()) { + seq_puts(seq, "----dump nr4 reg----\n"); + for (i = 0x2da4; i < 0x2df6; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, dim_RDMA_RD(i)); + for (i = 0x3700; i < 0x373f; i++) + seq_printf(seq, "[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, dim_RDMA_RD(i)); + } + seq_puts(seq, "----dump reg done----\n"); + return 0; +} + +static void dump_mif_state(struct DI_MIF_s *mif) +{ + pr_info("luma <%u, %u> <%u %u>.\n", + mif->luma_x_start0, mif->luma_x_end0, + mif->luma_y_start0, mif->luma_y_end0); + pr_info("chroma <%u, %u> <%u %u>.\n", + mif->chroma_x_start0, mif->chroma_x_end0, + mif->chroma_y_start0, mif->chroma_y_end0); + pr_info("canvas id <%u %u %u>.\n", + mif->canvas0_addr0, + mif->canvas0_addr1, + mif->canvas0_addr2); +} + +/*2018-08-17 add debugfs*/ +/*same as dump_mif_state*/ +static void dump_mif_state_seq(struct DI_MIF_s *mif, + struct seq_file *seq) +{ + seq_printf(seq, "luma <%u, %u> <%u %u>.\n", + mif->luma_x_start0, mif->luma_x_end0, + mif->luma_y_start0, mif->luma_y_end0); + seq_printf(seq, "chroma <%u, %u> <%u %u>.\n", + mif->chroma_x_start0, mif->chroma_x_end0, + mif->chroma_y_start0, mif->chroma_y_end0); + seq_printf(seq, "canvas id <%u %u %u>.\n", + mif->canvas0_addr0, + mif->canvas0_addr1, + mif->canvas0_addr2); +} + +static void dump_simple_mif_state(struct DI_SIM_MIF_s *simp_mif) +{ + pr_info("<%u %u> <%u %u>.\n", + simp_mif->start_x, simp_mif->end_x, + simp_mif->start_y, simp_mif->end_y); + pr_info("canvas num <%u>.\n", + simp_mif->canvas_num); +} + +/*2018-08-17 add debugfs*/ +/*same as dump_simple_mif_state*/ +static void dump_simple_mif_state_seq(struct DI_SIM_MIF_s *simp_mif, + struct seq_file *seq) +{ + seq_printf(seq, "<%u %u> <%u %u>.\n", + simp_mif->start_x, simp_mif->end_x, + simp_mif->start_y, simp_mif->end_y); + seq_printf(seq, "canvas num <%u>.\n", + simp_mif->canvas_num); +} + +static void dump_mc_mif_state(struct DI_MC_MIF_s *mc_mif) +{ + pr_info("startx %u,<%u %u>, size <%u %u>.\n", + mc_mif->start_x, mc_mif->start_y, + mc_mif->end_y, mc_mif->size_x, + mc_mif->size_y); +} + +/*2018-08-17 add debugfs*/ +/*same as dump_mc_mif_state*/ +static void dump_mc_mif_state_seq(struct DI_MC_MIF_s *mc_mif, + struct seq_file *seq) +{ + seq_printf(seq, "startx %u,<%u %u>, size <%u %u>.\n", + mc_mif->start_x, mc_mif->start_y, + mc_mif->end_y, mc_mif->size_x, + mc_mif->size_y); +} + +void dim_dump_pre_stru(struct di_pre_stru_s *ppre) +{ + pr_info("di_pre_stru:\n"); + pr_info("di_mem_buf_dup_p = 0x%p\n", + ppre->di_mem_buf_dup_p); + pr_info("di_chan2_buf_dup_p = 0x%p\n", + ppre->di_chan2_buf_dup_p); + pr_info("in_seq = %d\n", + ppre->in_seq); + pr_info("recycle_seq = %d\n", + ppre->recycle_seq); + pr_info("pre_ready_seq = %d\n", + ppre->pre_ready_seq); + pr_info("pre_de_busy = %d\n", + ppre->pre_de_busy); + + pr_info("pre_de_process_flag = %d\n", + ppre->pre_de_process_flag); + pr_info("pre_de_irq_timeout_count=%d\n", + ppre->pre_de_irq_timeout_count); + + pr_info("cur_width = %d\n", + ppre->cur_width); + pr_info("cur_height = %d\n", + ppre->cur_height); + pr_info("cur_inp_type = 0x%x\n", + ppre->cur_inp_type); + pr_info("cur_source_type = %d\n", + ppre->cur_source_type); + pr_info("cur_prog_flag = %d\n", + ppre->cur_prog_flag); + pr_info("source_change_flag = %d\n", + ppre->source_change_flag); + pr_info("bypass_flag = %s\n", + ppre->bypass_flag ? "true" : "false"); + pr_info("prog_proc_type = %d\n", + ppre->prog_proc_type); + pr_info("madi_enable = %u\n", + ppre->madi_enable); + pr_info("mcdi_enable = %u\n", + ppre->mcdi_enable); +#ifdef DET3D + pr_info("vframe_interleave_flag = %d\n", + ppre->vframe_interleave_flag); +#endif + pr_info("left_right = %d\n", + ppre->left_right); + pr_info("force_interlace = %s\n", + ppre->force_interlace ? "true" : "false"); + pr_info("vdin2nr = %d\n", + ppre->vdin2nr); + pr_info("bypass_pre = %s\n", + ppre->bypass_pre ? "true" : "false"); + pr_info("invert_flag = %s\n", + ppre->invert_flag ? "true" : "false"); +} + +/*2018-08-17 add debugfs*/ +/*same as dim_dump_pre_stru*/ +static int dump_di_pre_stru_seq(struct seq_file *seq, void *v, + unsigned int channel) + +{ + struct di_pre_stru_s *di_pre_stru_p = get_pre_stru(channel); + + seq_printf(seq, "di_pre_stru[%d]:\n", channel); + seq_printf(seq, "%-25s = 0x%p\n", "di_mem_buf_dup_p", + di_pre_stru_p->di_mem_buf_dup_p); + seq_printf(seq, "%-25s = 0x%p\n", "di_chan2_buf_dup_p", + di_pre_stru_p->di_chan2_buf_dup_p); + seq_printf(seq, "%-25s = %d\n", "in_seq", + di_pre_stru_p->in_seq); + seq_printf(seq, "%-25s = %d\n", "recycle_seq", + di_pre_stru_p->recycle_seq); + seq_printf(seq, "%-25s = %d\n", "pre_ready_seq", + di_pre_stru_p->pre_ready_seq); + seq_printf(seq, "%-25s = %d\n", "pre_de_busy", + di_pre_stru_p->pre_de_busy); + seq_printf(seq, "%-25s = %d\n", "pre_de_process_flag", + di_pre_stru_p->pre_de_process_flag); + seq_printf(seq, "%-25s =%d\n", "pre_de_irq_timeout_count", + di_pre_stru_p->pre_de_irq_timeout_count); + seq_printf(seq, "%-25s = %d\n", "cur_width", + di_pre_stru_p->cur_width); + seq_printf(seq, "%-25s = %d\n", "cur_height", + di_pre_stru_p->cur_height); + seq_printf(seq, "%-25s = 0x%x\n", "cur_inp_type", + di_pre_stru_p->cur_inp_type); + seq_printf(seq, "%-25s = %d\n", "cur_source_type", + di_pre_stru_p->cur_source_type); + seq_printf(seq, "%-25s = %d\n", "cur_prog_flag", + di_pre_stru_p->cur_prog_flag); + seq_printf(seq, "%-25s = %d\n", "source_change_flag", + di_pre_stru_p->source_change_flag); + seq_printf(seq, "%-25s = %s\n", "bypass_flag", + di_pre_stru_p->bypass_flag ? "true" : "false"); + seq_printf(seq, "%-25s = %d\n", "prog_proc_type", + di_pre_stru_p->prog_proc_type); + seq_printf(seq, "%-25s = %d\n", "madi_enable", + di_pre_stru_p->madi_enable); + seq_printf(seq, "%-25s = %d\n", "mcdi_enable", + di_pre_stru_p->mcdi_enable); +#ifdef DET3D + seq_printf(seq, "%-25s = %d\n", "vframe_interleave_flag", + di_pre_stru_p->vframe_interleave_flag); +#endif + seq_printf(seq, "%-25s = %d\n", "left_right", + di_pre_stru_p->left_right); + seq_printf(seq, "%-25s = %s\n", "force_interlace", + di_pre_stru_p->force_interlace ? "true" : "false"); + seq_printf(seq, "%-25s = %d\n", "vdin2nr", + di_pre_stru_p->vdin2nr); + seq_printf(seq, "%-25s = %s\n", "bypass_pre", + di_pre_stru_p->bypass_pre ? "true" : "false"); + seq_printf(seq, "%-25s = %s\n", "invert_flag", + di_pre_stru_p->invert_flag ? "true" : "false"); + + return 0; +} + +void dim_dump_post_stru(struct di_post_stru_s *di_post_stru_p) +{ + pr_info("\ndi_post_stru:\n"); + pr_info("run_early_proc_fun_flag = %d\n", + di_post_stru_p->run_early_proc_fun_flag); + pr_info("cur_disp_index = %d\n", + di_post_stru_p->cur_disp_index); + pr_info("post_de_busy = %d\n", + di_post_stru_p->post_de_busy); + pr_info("de_post_process_done = %d\n", + di_post_stru_p->de_post_process_done); + pr_info("cur_post_buf = 0x%p\n", + di_post_stru_p->cur_post_buf); + pr_info("post_peek_underflow = %u\n", + di_post_stru_p->post_peek_underflow); +} + +/*2018-08-17 add debugfs*/ +/*same as dim_dump_post_stru*/ +static int dump_di_post_stru_seq(struct seq_file *seq, void *v, + unsigned int channel) +{ + struct di_post_stru_s *di_post_stru_p = get_post_stru(channel); + + seq_printf(seq, "di_post_stru[%d]:\n", channel); + seq_printf(seq, "run_early_proc_fun_flag = %d\n", + di_post_stru_p->run_early_proc_fun_flag); + seq_printf(seq, "cur_disp_index = %d\n", + di_post_stru_p->cur_disp_index); + seq_printf(seq, "post_de_busy = %d\n", + di_post_stru_p->post_de_busy); + seq_printf(seq, "de_post_process_done = %d\n", + di_post_stru_p->de_post_process_done); + seq_printf(seq, "cur_post_buf = 0x%p\n", + di_post_stru_p->cur_post_buf); + seq_printf(seq, "post_peek_underflow = %u\n", + di_post_stru_p->post_peek_underflow); + + return 0; +} + +void dim_dump_mif_size_state(struct di_pre_stru_s *pre_stru_p, + struct di_post_stru_s *post_stru_p) +{ + pr_info("======pre mif status======\n"); + pr_info("DI_PRE_CTRL=0x%x\n", Rd(DI_PRE_CTRL)); + pr_info("DI_PRE_SIZE H=%d, V=%d\n", + (Rd(DI_PRE_SIZE) >> 16) & 0xffff, + Rd(DI_PRE_SIZE) & 0xffff); + pr_info("DNR_HVSIZE=0x%x\n", Rd(DNR_HVSIZE)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_info("CONTWR_CAN_SIZE=0x%x\n", Rd(0x37ec)); + pr_info("MTNWR_CAN_SIZE=0x%x\n", Rd(0x37f0)); + } + pr_info("DNR_STAT_X_START_END=0x%x\n", Rd(0x2d08)); + pr_info("DNR_STAT_Y_START_END=0x%x\n", Rd(0x2d09)); + pr_info("MCDI_HV_SIZEIN=0x%x\n", Rd(0x2f00)); + pr_info("MCDI_HV_BLKSIZEIN=0x%x\n", Rd(0x2f01)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_info("MCVECWR_CAN_SIZE=0x%x\n", Rd(0x37f4)); + pr_info("MCINFWR_CAN_SIZE=0x%x\n", Rd(0x37f8)); + pr_info("NRDSWR_CAN_SIZE=0x%x\n", Rd(0x37fc)); + pr_info("NR_DS_BUF_SIZE=0x%x\n", Rd(0x3740)); + } + + pr_info("=====inp mif:\n"); +#if 0 + Wr(DI_DBG_CTRL, 0x1b); + Wr(DI_DBG_CTRL1, 0x640064); + Wr_reg_bits(DI_PRE_GL_CTRL, 0, 31, 1); + Wr_reg_bits(DI_PRE_CTRL, 0, 11, 1); + Wr_reg_bits(DI_PRE_CTRL, 1, 31, 1); + Wr_reg_bits(DI_PRE_GL_CTRL, 1, 31, 1); + pr_info("DI_DBG_SRDY_INF=0x%x\n", Rd(DI_DBG_SRDY_INF)); + pr_info("DI_DBG_RRDY_INF=0x%x\n", Rd(DI_DBG_RRDY_INF)); +#endif + pr_info("DI_INP_GEN_REG=0x%x\n", Rd(DI_INP_GEN_REG)); + dump_mif_state(&pre_stru_p->di_inp_mif); + pr_info("=====mem mif:\n"); + pr_info("DI_MEM_GEN_REG=0x%x\n", Rd(DI_MEM_GEN_REG)); + dump_mif_state(&pre_stru_p->di_mem_mif); + pr_info("=====chan2 mif:\n"); + pr_info("DI_CHAN2_GEN_REG=0x%x\n", Rd(DI_CHAN2_GEN_REG)); + dump_mif_state(&pre_stru_p->di_chan2_mif); + pr_info("=====nrwr mif:\n"); + pr_info("DI_NRWR_CTRL=0x%x\n", Rd(DI_NRWR_CTRL)); + dump_simple_mif_state(&pre_stru_p->di_nrwr_mif); + pr_info("=====mtnwr mif:\n"); + dump_simple_mif_state(&pre_stru_p->di_mtnwr_mif); + pr_info("=====contp2rd mif:\n"); + dump_simple_mif_state(&pre_stru_p->di_contp2rd_mif); + pr_info("=====contprd mif:\n"); + dump_simple_mif_state(&pre_stru_p->di_contprd_mif); + pr_info("=====contwr mif:\n"); + dump_simple_mif_state(&pre_stru_p->di_contwr_mif); + pr_info("=====mcinford mif:\n"); + dump_mc_mif_state(&pre_stru_p->di_mcinford_mif); + pr_info("=====mcinfowr mif:\n"); + dump_mc_mif_state(&pre_stru_p->di_mcinfowr_mif); + pr_info("=====mcvecwr mif:\n"); + dump_mc_mif_state(&pre_stru_p->di_mcvecwr_mif); + pr_info("======post mif status======\n"); + pr_info("DI_POST_SIZE=0x%x\n", Rd(DI_POST_SIZE)); + pr_info("DECOMB_FRM_SIZE=0x%x\n", Rd(0x2d8f)); + pr_info("=====if0 mif:\n"); + pr_info("DI_IF0_GEN_REG=0x%x\n", Rd(0x2030)); + dump_mif_state(&post_stru_p->di_buf0_mif); + pr_info("=====if1 mif:\n"); + pr_info("DI_IF1_GEN_REG=0x%x\n", Rd(0x17e8)); + dump_mif_state(&post_stru_p->di_buf1_mif); + pr_info("=====if2 mif:\n"); + pr_info("DI_IF2_GEN_REG=0x%x\n", Rd(0x2010)); + dump_mif_state(&post_stru_p->di_buf2_mif); + pr_info("=====diwr mif:\n"); + dump_simple_mif_state(&post_stru_p->di_diwr_mif); + pr_info("=====mtnprd mif:\n"); + dump_simple_mif_state(&post_stru_p->di_mtnprd_mif); + pr_info("=====mcvecrd mif:\n"); + dump_mc_mif_state(&post_stru_p->di_mcvecrd_mif); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + pr_info("======pps size status======\n"); + pr_info("DI_SC_LINE_IN_LENGTH=0x%x\n", Rd(0x3751)); + pr_info("DI_SC_PIC_IN_HEIGHT=0x%x\n", Rd(0x3752)); + pr_info("DI_HDR_IN_HSIZE=0x%x\n", Rd(0x376e)); + pr_info("DI_HDR_IN_VSIZE=0x%x\n", Rd(0x376f)); + } +} + +/*2018-08-17 add debugfs*/ +/*same as dump_mif_size_state*/ +int dim_dump_mif_size_state_show(struct seq_file *seq, + void *v, unsigned int channel) +{ + struct di_pre_stru_s *di_pre_stru_p; + struct di_post_stru_s *di_post_stru_p; + + di_pre_stru_p = get_pre_stru(channel); + di_post_stru_p = get_post_stru(channel); + + seq_puts(seq, "======pre mif status======\n"); + seq_printf(seq, "DI_PRE_CTRL=0x%x\n", Rd(DI_PRE_CTRL)); + seq_printf(seq, "DI_PRE_SIZE=0x%x\n", Rd(DI_PRE_SIZE)); + seq_printf(seq, "DNR_HVSIZE=0x%x\n", Rd(DNR_HVSIZE)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + seq_printf(seq, "CONTWR_CAN_SIZE=0x%x\n", Rd(0x37ec)); + seq_printf(seq, "MTNWR_CAN_SIZE=0x%x\n", Rd(0x37f0)); + } + seq_printf(seq, "DNR_STAT_X_START_END=0x%x\n", Rd(0x2d08)); + seq_printf(seq, "DNR_STAT_Y_START_END=0x%x\n", Rd(0x2d09)); + seq_printf(seq, "MCDI_HV_SIZEIN=0x%x\n", Rd(0x2f00)); + seq_printf(seq, "MCDI_HV_BLKSIZEIN=0x%x\n", Rd(0x2f01)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + seq_printf(seq, "MCVECWR_CAN_SIZE=0x%x\n", Rd(0x37f4)); + seq_printf(seq, "MCINFWR_CAN_SIZE=0x%x\n", Rd(0x37f8)); + seq_printf(seq, "NRDSWR_CAN_SIZE=0x%x\n", Rd(0x37fc)); + seq_printf(seq, "NR_DS_BUF_SIZE=0x%x\n", Rd(0x3740)); + } + + seq_puts(seq, "=====inp mif:\n"); + + seq_printf(seq, "DI_INP_GEN_REG=0x%x\n", Rd(DI_INP_GEN_REG)); + dump_mif_state_seq(&di_pre_stru_p->di_inp_mif, seq);/*dump_mif_state*/ + seq_puts(seq, "=====mem mif:\n"); + seq_printf(seq, "DI_MEM_GEN_REG=0x%x\n", Rd(DI_MEM_GEN_REG)); + dump_mif_state_seq(&di_pre_stru_p->di_mem_mif, seq); + seq_puts(seq, "=====chan2 mif:\n"); + seq_printf(seq, "DI_CHAN2_GEN_REG=0x%x\n", Rd(DI_CHAN2_GEN_REG)); + dump_mif_state_seq(&di_pre_stru_p->di_chan2_mif, seq); + seq_puts(seq, "=====nrwr mif:\n"); + seq_printf(seq, "DI_NRWR_CTRL=0x%x\n", Rd(DI_NRWR_CTRL)); + /*dump_simple_mif_state*/ + dump_simple_mif_state_seq(&di_pre_stru_p->di_nrwr_mif, seq); + seq_puts(seq, "=====mtnwr mif:\n"); + dump_simple_mif_state_seq(&di_pre_stru_p->di_mtnwr_mif, seq); + seq_puts(seq, "=====contp2rd mif:\n"); + dump_simple_mif_state_seq(&di_pre_stru_p->di_contp2rd_mif, seq); + seq_puts(seq, "=====contprd mif:\n"); + dump_simple_mif_state_seq(&di_pre_stru_p->di_contprd_mif, seq); + seq_puts(seq, "=====contwr mif:\n"); + dump_simple_mif_state_seq(&di_pre_stru_p->di_contwr_mif, seq); + seq_puts(seq, "=====mcinford mif:\n"); + /*dump_mc_mif_state*/ + dump_mc_mif_state_seq(&di_pre_stru_p->di_mcinford_mif, seq); + seq_puts(seq, "=====mcinfowr mif:\n"); + dump_mc_mif_state_seq(&di_pre_stru_p->di_mcinfowr_mif, seq); + seq_puts(seq, "=====mcvecwr mif:\n"); + dump_mc_mif_state_seq(&di_pre_stru_p->di_mcvecwr_mif, seq); + seq_puts(seq, "======post mif status======\n"); + seq_printf(seq, "DI_POST_SIZE=0x%x\n", Rd(DI_POST_SIZE)); + seq_printf(seq, "DECOMB_FRM_SIZE=0x%x\n", Rd(0x2d8f)); + seq_puts(seq, "=====if0 mif:\n"); + seq_printf(seq, "DI_IF0_GEN_REG=0x%x\n", Rd(0x2030)); + dump_mif_state_seq(&di_post_stru_p->di_buf0_mif, seq); + seq_puts(seq, "=====if1 mif:\n"); + seq_printf(seq, "DI_IF1_GEN_REG=0x%x\n", Rd(0x17e8)); + dump_mif_state_seq(&di_post_stru_p->di_buf1_mif, seq); + seq_puts(seq, "=====if2 mif:\n"); + seq_printf(seq, "DI_IF2_GEN_REG=0x%x\n", Rd(0x2010)); + dump_mif_state_seq(&di_post_stru_p->di_buf2_mif, seq); + seq_puts(seq, "=====diwr mif:\n"); + dump_simple_mif_state_seq(&di_post_stru_p->di_diwr_mif, seq); + seq_puts(seq, "=====mtnprd mif:\n"); + dump_simple_mif_state_seq(&di_post_stru_p->di_mtnprd_mif, seq); + seq_puts(seq, "=====mcvecrd mif:\n"); + dump_mc_mif_state_seq(&di_post_stru_p->di_mcvecrd_mif, seq); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + seq_puts(seq, "======pps size status======\n"); + seq_printf(seq, "DI_SC_LINE_IN_LENGTH=0x%x\n", Rd(0x3751)); + seq_printf(seq, "DI_SC_PIC_IN_HEIGHT=0x%x\n", Rd(0x3752)); + seq_printf(seq, "DI_HDR_IN_HSIZE=0x%x\n", Rd(0x376e)); + seq_printf(seq, "DI_HDR_IN_VSIZE=0x%x\n", Rd(0x376f)); + } + return 0; +} + +void dim_dump_di_buf(struct di_buf_s *di_buf) +{ + pr_info("di_buf %p vframe %p:\n", di_buf, di_buf->vframe); + pr_info("index %d, post_proc_flag %d, new_format_flag %d, type %d,", + di_buf->index, di_buf->post_proc_flag, + di_buf->new_format_flag, di_buf->type); + pr_info("seq %d, pre_ref_count %d,post_ref_count %d, queue_index %d,", + di_buf->seq, di_buf->pre_ref_count, di_buf->post_ref_count, + di_buf->queue_index); + pr_info("pulldown_mode %d process_fun_index %d\n", + di_buf->pd_config.global_mode, di_buf->process_fun_index); + pr_info("di_buf: %p, %p, di_buf_dup_p: %p, %p, %p, %p, %p\n", + di_buf->di_buf[0], di_buf->di_buf[1], di_buf->di_buf_dup_p[0], + di_buf->di_buf_dup_p[1], di_buf->di_buf_dup_p[2], + di_buf->di_buf_dup_p[3], di_buf->di_buf_dup_p[4]); + pr_info( + "nr_adr 0x%lx, nr_canvas_idx 0x%x, mtn_adr 0x%lx, mtn_canvas_idx 0x%x", + di_buf->nr_adr, di_buf->nr_canvas_idx, di_buf->mtn_adr, + di_buf->mtn_canvas_idx); + pr_info("cnt_adr 0x%lx, cnt_canvas_idx 0x%x\n", + di_buf->cnt_adr, di_buf->cnt_canvas_idx); + pr_info("di_cnt %d, priveated %u.\n", + atomic_read(&di_buf->di_cnt), di_buf->privated); +} + +void dim_dump_pool(struct queue_s *q) +{ + int j; + + pr_info("queue: in_idx %d, out_idx %d, num %d, type %d\n", + q->in_idx, q->out_idx, q->num, q->type); + for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++) { + pr_info("0x%x ", q->pool[j]); + if (((j + 1) % 16) == 0) + pr_debug("\n"); + } + pr_info("\n"); +} + +void dim_dump_vframe(struct vframe_s *vf) +{ + pr_info("vframe %p:\n", vf); + pr_info("index %d, type 0x%x, type_backup 0x%x, blend_mode %d bitdepth %d\n", + vf->index, vf->type, vf->type_backup, + vf->blend_mode, (vf->bitdepth & BITDEPTH_Y10) ? 10 : 8); + pr_info("duration %d, duration_pulldown %d, pts %d, flag 0x%x\n", + vf->duration, vf->duration_pulldown, vf->pts, vf->flag); + pr_info("canvas0Addr 0x%x, canvas1Addr 0x%x, bufWidth %d\n", + vf->canvas0Addr, vf->canvas1Addr, vf->bufWidth); + pr_info("width %d, height %d, ratio_control 0x%x, orientation 0x%x\n", + vf->width, vf->height, vf->ratio_control, vf->orientation); + pr_info("source_type %d, phase %d, soruce_mode %d, sig_fmt %d\n", + vf->source_type, vf->phase, vf->source_mode, vf->sig_fmt); + pr_info( + "trans_fmt 0x%x, lefteye(%d %d %d %d), righteye(%d %d %d %d)\n", + vf->trans_fmt, vf->left_eye.start_x, vf->left_eye.start_y, + vf->left_eye.width, vf->left_eye.height, + vf->right_eye.start_x, vf->right_eye.start_y, + vf->right_eye.width, vf->right_eye.height); + pr_info("mode_3d_enable %d, use_cnt %d,", + vf->mode_3d_enable, atomic_read(&vf->use_cnt)); + pr_info("early_process_fun 0x%p, process_fun 0x%p, private_data %p\n", + vf->early_process_fun, + vf->process_fun, vf->private_data); + pr_info("pixel_ratio %d list %p\n", + vf->pixel_ratio, &vf->list); +} + +void dim_print_di_buf(struct di_buf_s *di_buf, int format) +{ + if (!di_buf) + return; + if (format == 1) { + pr_info( + "\t+index %d, 0x%p, type %d, vframetype 0x%x, trans_fmt %u,bitdepath %d\n", + di_buf->index, + di_buf, + di_buf->type, + di_buf->vframe->type, + di_buf->vframe->trans_fmt, + di_buf->vframe->bitdepth); + if (di_buf->di_wr_linked_buf) { + pr_info("\tlinked +index %d, 0x%p, type %d\n", + di_buf->di_wr_linked_buf->index, + di_buf->di_wr_linked_buf, + di_buf->di_wr_linked_buf->type); + } + } else if (format == 2) { + pr_info("index %d, 0x%p(vframe 0x%p), type %d\n", + di_buf->index, di_buf, + di_buf->vframe, di_buf->type); + pr_info("vframetype 0x%x, trans_fmt %u,duration %d pts %d,bitdepth %d\n", + di_buf->vframe->type, + di_buf->vframe->trans_fmt, + di_buf->vframe->duration, + di_buf->vframe->pts, + di_buf->vframe->bitdepth); + if (di_buf->di_wr_linked_buf) { + pr_info("linked index %d, 0x%p, type %d\n", + di_buf->di_wr_linked_buf->index, + di_buf->di_wr_linked_buf, + di_buf->di_wr_linked_buf->type); + } + } +} + +/*2018-08-17 add debugfs*/ +/*same as print_di_buf*/ +static void print_di_buf_seq(struct di_buf_s *di_buf, int format, + struct seq_file *seq) +{ + if (!di_buf) + return; + if (format == 1) { + seq_printf(seq, "\t+index %d, 0x%p, type %d\n", + di_buf->index, + di_buf, + di_buf->type); + seq_printf(seq, "vframetype 0x%x, trans_fmt %u,bitdepath %d\n", + di_buf->vframe->type, + di_buf->vframe->trans_fmt, + di_buf->vframe->bitdepth); + if (di_buf->di_wr_linked_buf) { + seq_printf(seq, "\tlinked +index %d, 0x%p, type %d\n", + di_buf->di_wr_linked_buf->index, + di_buf->di_wr_linked_buf, + di_buf->di_wr_linked_buf->type); + } + } else if (format == 2) { + seq_printf(seq, "index %d, 0x%p(vframe 0x%p), type %d\n", + di_buf->index, di_buf, + di_buf->vframe, di_buf->type); + seq_printf(seq, "vfmtype 0x%x, trans_fmt %u\n", + di_buf->vframe->type, + di_buf->vframe->trans_fmt); + seq_printf(seq, ",duration %d pts %d,bitdepth %d\n", + di_buf->vframe->duration, + di_buf->vframe->pts, + di_buf->vframe->bitdepth); + if (di_buf->di_wr_linked_buf) { + seq_printf(seq, "linked index %d, 0x%p, type %d\n", + di_buf->di_wr_linked_buf->index, + di_buf->di_wr_linked_buf, + di_buf->di_wr_linked_buf->type); + } + } +} + +void dim_dump_pre_mif_state(void) +{ + unsigned int i = 0; + + Wr_reg_bits(DI_INP_GEN_REG3, 3, 10, 2); + Wr_reg_bits(DI_MEM_GEN_REG3, 3, 10, 2); + Wr_reg_bits(DI_CHAN2_GEN_REG3, 3, 10, 2); + pr_info("DI_INP_GEN_REG2=0x%x.\n", Rd(DI_INP_GEN_REG2)); + pr_info("DI_INP_GEN_REG3=0x%x.\n", Rd(DI_INP_GEN_REG3)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17ce + i, Rd(0x17ce + i)); + pr_info("DI_MEM_GEN_REG2=0x%x.\n", Rd(DI_MEM_GEN_REG2)); + pr_info("DI_MEM_GEN_REG3=0x%x.\n", Rd(DI_MEM_GEN_REG3)); + pr_info("DI_MEM_LUMA_FIFO_SIZE=0x%x.\n", Rd(DI_MEM_LUMA_FIFO_SIZE)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17db + i, Rd(0x17db + i)); + pr_info("DI_CHAN2_GEN_REG2=0x%x.\n", Rd(DI_CHAN2_GEN_REG2)); + pr_info("DI_CHAN2_GEN_REG3=0x%x.\n", Rd(DI_CHAN2_GEN_REG3)); + pr_info("DI_CHAN2_LUMA_FIFO_SIZE=0x%x.\n", Rd(DI_CHAN2_LUMA_FIFO_SIZE)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17f5 + i, Rd(0x17f5 + i)); +} + +void dim_dump_post_mif_reg(void) +{ + pr_info("VIU_MISC_CTRL0=0x%x\n", Rd(VIU_MISC_CTRL0)); + + pr_info("VD1_IF0_GEN_REG=0x%x\n", Rd(VD1_IF0_GEN_REG)); + pr_info("VD1_IF0_GEN_REG2=0x%x\n", Rd(VD1_IF0_GEN_REG2)); + pr_info("VD1_IF0_GEN_REG3=0x%x\n", Rd(VD1_IF0_GEN_REG3)); + pr_info("VD1_IF0_LUMA_X0=0x%x\n", Rd(VD1_IF0_LUMA_X0)); + pr_info("VD1_IF0_LUMA_Y0=0x%x\n", Rd(VD1_IF0_LUMA_Y0)); + pr_info("VD1_IF0_CHROMA_X0=0x%x\n", Rd(VD1_IF0_CHROMA_X0)); + pr_info("VD1_IF0_CHROMA_Y0=0x%x\n", Rd(VD1_IF0_CHROMA_Y0)); + pr_info("VD1_IF0_LUMA_X1=0x%x\n", Rd(VD1_IF0_LUMA_X1)); + pr_info("VD1_IF0_LUMA_Y1=0x%x\n", Rd(VD1_IF0_LUMA_Y1)); + pr_info("VD1_IF0_CHROMA_X1=0x%x\n", Rd(VD1_IF0_CHROMA_X1)); + pr_info("VD1_IF0_CHROMA_Y1=0x%x\n", Rd(VD1_IF0_CHROMA_Y1)); + pr_info("VD1_IF0_REPEAT_LOOP=0x%x\n", Rd(VD1_IF0_RPT_LOOP)); + pr_info("VD1_IF0_LUMA0_RPT_PAT=0x%x\n", Rd(VD1_IF0_LUMA0_RPT_PAT)); + pr_info("VD1_IF0_CHROMA0_RPT_PAT=0x%x\n", Rd(VD1_IF0_CHROMA0_RPT_PAT)); + pr_info("VD1_IF0_LUMA_PSEL=0x%x\n", Rd(VD1_IF0_LUMA_PSEL)); + pr_info("VD1_IF0_CHROMA_PSEL=0x%x\n", Rd(VD1_IF0_CHROMA_PSEL)); + pr_info("VIU_VD1_FMT_CTRL=0x%x\n", Rd(VIU_VD1_FMT_CTRL)); + pr_info("VIU_VD1_FMT_W=0x%x\n", Rd(VIU_VD1_FMT_W)); + + pr_info("DI_IF1_GEN_REG=0x%x\n", Rd(DI_IF1_GEN_REG)); + pr_info("DI_IF1_GEN_REG2=0x%x\n", Rd(DI_IF1_GEN_REG2)); + pr_info("DI_IF1_GEN_REG3=0x%x\n", Rd(DI_IF1_GEN_REG3)); + pr_info("DI_IF1_CANVAS0=0x%x\n", Rd(DI_IF1_CANVAS0)); + pr_info("DI_IF1_LUMA_X0=0x%x\n", Rd(DI_IF1_LUMA_X0)); + pr_info("DI_IF1_LUMA_Y0=0x%x\n", Rd(DI_IF1_LUMA_Y0)); + pr_info("DI_IF1_CHROMA_X0=0x%x\n", Rd(DI_IF1_CHROMA_X0)); + pr_info("DI_IF1_CHROMA_Y0=0x%x\n", Rd(DI_IF1_CHROMA_Y0)); + pr_info("DI_IF1_LUMA0_RPT_PAT=0x%x\n", Rd(DI_IF1_LUMA0_RPT_PAT)); + pr_info("DI_IF1_CHROMA0_RPT_PAT=0x%x\n", Rd(DI_IF1_LUMA0_RPT_PAT)); + pr_info("DI_IF1_FMT_CTRL=0x%x\n", Rd(DI_IF1_FMT_CTRL)); + pr_info("DI_IF1_FMT_W=0x%x\n", Rd(DI_IF1_FMT_W)); + + pr_info("DI_IF2_GEN_REG=0x%x\n", Rd(DI_IF2_GEN_REG)); + pr_info("DI_IF2_GEN_REG2=0x%x\n", Rd(DI_IF2_GEN_REG2)); + pr_info("DI_IF2_GEN_REG3=0x%x\n", Rd(DI_IF2_GEN_REG3)); + pr_info("DI_IF2_CANVAS0=0x%x\n", Rd(DI_IF2_CANVAS0)); + pr_info("DI_IF2_LUMA_X0=0x%x\n", Rd(DI_IF2_LUMA_X0)); + pr_info("DI_IF2_LUMA_Y0=0x%x\n", Rd(DI_IF2_LUMA_Y0)); + pr_info("DI_IF2_CHROMA_X0=0x%x\n", Rd(DI_IF2_CHROMA_X0)); + pr_info("DI_IF2_CHROMA_Y0=0x%x\n", Rd(DI_IF2_CHROMA_Y0)); + pr_info("DI_IF2_LUMA0_RPT_PAT=0x%x\n", Rd(DI_IF2_LUMA0_RPT_PAT)); + pr_info("DI_IF2_CHROMA0_RPT_PAT=0x%x\n", Rd(DI_IF2_LUMA0_RPT_PAT)); + pr_info("DI_IF2_FMT_CTRL=0x%x\n", Rd(DI_IF2_FMT_CTRL)); + pr_info("DI_IF2_FMT_W=0x%x\n", Rd(DI_IF2_FMT_W)); + + pr_info("DI_DIWR_Y=0x%x\n", Rd(DI_DIWR_Y)); + pr_info("DI_DIWR_CTRL=0x%x", Rd(DI_DIWR_CTRL)); + pr_info("DI_DIWR_X=0x%x.\n", Rd(DI_DIWR_X)); +} + +void dim_dump_buf_addr(struct di_buf_s *di_buf, unsigned int num) +{ + unsigned int i = 0; + struct di_buf_s *di_buf_p = NULL; + + for (i = 0; i < num; i++) { + di_buf_p = (di_buf + i); + pr_info("di_buf[%d] nr_addr 0x%lx,", + di_buf_p->index, di_buf_p->nr_adr); + pr_info("mtn_addr 0x%lx, cnt_adr 0x%lx,", + di_buf_p->mtn_adr, di_buf_p->cnt_adr); + pr_info("mv_adr 0x%lx, mcinfo_adr 0x%lx.\n", + di_buf_p->mcvec_adr, di_buf_p->mcinfo_adr); + } +} + +static int seq_file_module_para_show(struct seq_file *seq, void *v) +{ + dim_seq_file_module_para_di(seq); + dim_seq_file_module_para_hw(seq); + dim_seq_file_module_para_pps(seq); + get_ops_mtn()->module_para(seq); + get_ops_nr()->module_para(seq); + get_ops_pd()->module_para(seq); + + return 0; +} + +/*2018-08-17 add debugfs*/ +/*same as dump_state*/ +int dim_state_show(struct seq_file *seq, void *v, unsigned int channel) +{ + int itmp, i; + struct di_buf_s *p = NULL, *keep_buf;/* ptmp; */ + struct di_pre_stru_s *di_pre_stru_p; + struct di_post_stru_s *di_post_stru_p; + struct di_dev_s *de_devp = get_dim_de_devp(); + const char *version_s = dim_get_version_s(); + int dump_state_flag = dim_get_dump_state_flag(); + unsigned char recovery_flag = dim_vcry_get_flg(); + unsigned int recovery_log_reason = dim_vcry_get_log_reason(); + int di_blocking = dim_get_blocking(); + unsigned int recovery_log_queue_idx = dim_vcry_get_log_q_idx(); + struct di_buf_s *recovery_log_di_buf = dim_get_recovery_log_di_buf(); + unsigned long reg_unreg_timeout_cnt = dim_get_reg_unreg_timeout_cnt(); + struct vframe_s **vframe_in = dim_get_vframe_in(channel); + unsigned int tmpa[MAX_FIFO_SIZE]; /*new que*/ + unsigned int psize; /*new que*/ + struct di_hpre_s *pre = get_hw_pre(); + struct di_hpst_s *post = get_hw_pst(); + struct di_buf_s *keep_buf_post = NULL; + char *splt = "---------------------------"; + struct di_mm_s *mm = dim_mm_get(); /*mm-0705*/ + + di_pre_stru_p = get_pre_stru(channel); + di_post_stru_p = get_post_stru(channel); + + dump_state_flag = 1; + seq_printf(seq, "%s:ch[%d]\n", __func__, channel); + seq_printf(seq, "version %s, init_flag %d, is_bypass %d\n", + version_s, + get_init_flag(channel), + dim_is_bypass(NULL, channel)); + seq_printf(seq, "recovery_flag = %d, reason=%d, di_blocking=%d", + recovery_flag, recovery_log_reason, di_blocking); + seq_printf(seq, "recovery_log_q_idx=%d, recovery_log_di_buf=0x%p\n", + recovery_log_queue_idx, recovery_log_di_buf); + seq_printf(seq, "buffer_size=%d, mem_flag=%s, cma_flag=%d\n", + de_devp->buffer_size, + di_cma_dbg_get_st_name(channel), + de_devp->flag_cma); + keep_buf = di_post_stru_p->keep_buf; + seq_printf(seq, "used_post_buf_index %d(0x%p),", + IS_ERR_OR_NULL(keep_buf) ? + -1 : keep_buf->index, keep_buf); + if (!IS_ERR_OR_NULL(keep_buf)) { + seq_puts(seq, "used_local_buf_index:\n"); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + p = keep_buf->di_buf_dup_p[i]; + seq_printf(seq, "%d(0x%p) ", + IS_ERR_OR_NULL(p) ? -1 : p->index, p); + } + } + /********************************/ + /* check keep buf post */ + /********************************/ + keep_buf_post = di_post_stru_p->keep_buf_post; + + if (IS_ERR_OR_NULL(keep_buf_post)) + seq_printf(seq, "%s:NULL\n", "keep_buf_post"); + else + seq_printf(seq, "%s:type=%d:index=%d\n", + "keep_buf_post", + keep_buf_post->type, keep_buf_post->index); + /********************************/ + /* in_free_list */ + /********************************/ + di_que_list(channel, QUE_IN_FREE, &tmpa[0], &psize); /*new que*/ + seq_printf(seq, "\nin_free_list max(%d) curr(%d):\n", + MAX_IN_BUF_NUM, psize); + for (itmp = 0; itmp < psize; itmp++) { /*new que*/ + p = pw_qindex_2_buf(channel, tmpa[itmp]); /*new que*/ + + seq_printf(seq, "index %2d, 0x%p, type %d\n", + p->index, p, p->type); + } + seq_printf(seq, "%s\n", splt); + /********************************/ + /* local_free_list */ + /********************************/ + seq_printf(seq, "local_free_list (max %d):\n", mm->cfg.num_local); + queue_for_each_entry(p, channel, QUEUE_LOCAL_FREE, list) { + seq_printf(seq, "index %2d, 0x%p, type %d\n", + p->index, p, p->type); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* post_doing_list */ + /********************************/ + seq_puts(seq, "post_doing_list:\n"); + queue_for_each_entry(p, channel, QUEUE_POST_DOING, list) { + print_di_buf_seq(p, 2, seq); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* pre_ready_list */ + /********************************/ + seq_puts(seq, "pre_ready_list:\n"); + di_que_list(channel, QUE_PRE_READY, &tmpa[0], &psize); /*new que*/ + for (itmp = 0; itmp < psize; itmp++) { /*new que*/ + p = pw_qindex_2_buf(channel, tmpa[itmp]); /*new que*/ + + print_di_buf_seq(p, 2, seq); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* post_free_list */ + /********************************/ + di_que_list(channel, QUE_POST_FREE, &tmpa[0], &psize); /*new que*/ + seq_printf(seq, "post_free_list (max %d) (crr %d):\n", + mm->cfg.num_post, psize); + for (itmp = 0; itmp < psize; itmp++) { /*new que*/ + p = pw_qindex_2_buf(channel, tmpa[itmp]); /*new que*/ + + seq_printf(seq, "index %2d, 0x%p, type %d, vframetype 0x%x\n", + p->index, p, p->type, p->vframe->type); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* post_ready_list */ + /********************************/ + di_que_list(channel, QUE_POST_READY, &tmpa[0], &psize); /*new que*/ + seq_printf(seq, "post_ready_list: curr(%d)\n", psize); + + for (itmp = 0; itmp < psize; itmp++) { /*new que*/ + p = pw_qindex_2_buf(channel, tmpa[itmp]); /*new que*/ + + print_di_buf_seq(p, 2, seq); + print_di_buf_seq(p->di_buf[0], 1, seq); + print_di_buf_seq(p->di_buf[1], 1, seq); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* display_list */ + /********************************/ + seq_puts(seq, "display_list:\n"); + queue_for_each_entry(p, channel, QUEUE_DISPLAY, list) { + print_di_buf_seq(p, 2, seq); + print_di_buf_seq(p->di_buf[0], 1, seq); + print_di_buf_seq(p->di_buf[1], 1, seq); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* recycle_list */ + /********************************/ + seq_puts(seq, "recycle_list:\n"); + queue_for_each_entry(p, channel, QUEUE_RECYCLE, list) { + seq_printf(seq, + "index %d, 0x%p, type %d, vfm 0x%x pre %d postt %d\n", + p->index, p, p->type, + p->vframe->type, + p->pre_ref_count, + p->post_ref_count); + if (p->di_wr_linked_buf) { + seq_printf(seq, + "ld index %2d, 0x%p, type %d pret %d pst %d\n", + p->di_wr_linked_buf->index, + p->di_wr_linked_buf, + p->di_wr_linked_buf->type, + p->di_wr_linked_buf->pre_ref_count, + p->di_wr_linked_buf->post_ref_count); + } + } + seq_printf(seq, "%s\n", splt); + /********************************/ + /* post back */ + /********************************/ + di_que_list(channel, QUE_POST_BACK, &tmpa[0], &psize); /*new que*/ + seq_printf(seq, "post_back: curr(%d)\n", psize); + + for (itmp = 0; itmp < psize; itmp++) { /*new que*/ + seq_printf(seq, "%d\n", tmpa[itmp]); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + + if (di_pre_stru_p->di_inp_buf) { + seq_printf(seq, "di_inp_buf:index %d, 0x%p, type %d\n", + di_pre_stru_p->di_inp_buf->index, + &di_pre_stru_p->di_inp_buf, + di_pre_stru_p->di_inp_buf->type); + } else { + seq_puts(seq, "di_inp_buf: NULL\n"); + } + if (di_pre_stru_p->di_wr_buf) { + seq_printf(seq, "di_wr_buf:index %d, 0x%p, type %d\n", + di_pre_stru_p->di_wr_buf->index, + &di_pre_stru_p->di_wr_buf, + di_pre_stru_p->di_wr_buf->type); + } else { + seq_puts(seq, "di_wr_buf: NULL\n"); + } + dump_di_pre_stru_seq(seq, v, channel); + dump_di_post_stru_seq(seq, v, channel); + seq_puts(seq, "vframe_in[]:"); + + for (i = 0; i < MAX_IN_BUF_NUM; i++) { + seq_printf(seq, "0x%p\n", *vframe_in); + vframe_in++; + } + + seq_puts(seq, "\n"); + seq_printf(seq, "vf_peek()=>0x%p, video_peek_cnt = %d\n", + pw_vf_peek(channel), + di_sum_get(channel, eDI_SUM_O_PEEK_CNT)); + seq_printf(seq, "reg_unreg_timerout = %lu\n", + reg_unreg_timeout_cnt); + seq_printf(seq, "%-15s=%s\n", "top_state", + dip_chst_get_name_curr(channel)); + seq_printf(seq, "%-15s=%d\n", "trig_unreg", + get_flag_trig_unreg(channel)); + seq_printf(seq, "%-15s=%d\n", "bypass_compelet", + is_bypss2_complete(channel)); + seq_printf(seq, "%-15s=%d\n", "reg_flag", + get_reg_flag(channel)); + seq_printf(seq, "%-15s=%s\n", "pre_state", + dpre_state4_name_get(pre->pre_st)); + seq_printf(seq, "%-15s=%s\n", "post_state", + dpst_state_name_get(post->state)); + + seq_printf(seq, "%-15s=%d\n", "pre_get_sum", + get_sum_g(channel)); + seq_printf(seq, "%-15s=%d\n", "pre_put_sum", + get_sum_p(channel)); + dump_state_flag = 0; + return 0; +} + +static int seq_file_afbc_show(struct seq_file *seq, void *v) +{ + seq_puts(seq, "******dump VD2 AFBC********\n"); + seq_printf(seq, "VD2_AFBC_ENABLE 0x%x.\n", + dim_RDMA_RD(VD2_AFBC_ENABLE)); + seq_printf(seq, "VD2_AFBC_STAT 0x%x.\n", dim_RDMA_RD(VD2_AFBC_STAT)); + seq_printf(seq, "VD2_AFBCD1_MISC_CTRL 0x%x.\n", + dim_RDMA_RD(VD2_AFBCD1_MISC_CTRL)); + + seq_puts(seq, "******dump VD1 AFBC********\n"); + seq_printf(seq, "AFBC_ENABLE 0x%x.\n", dim_RDMA_RD(AFBC_ENABLE)); + seq_printf(seq, "AFBC_STAT 0x%x.\n", dim_RDMA_RD(AFBC_STAT)); + seq_printf(seq, "VD1_AFBCD0_MISC_CTRL 0x%x.\n", + dim_RDMA_RD(VD1_AFBCD0_MISC_CTRL)); + seq_puts(seq, "***************************\n"); + + seq_printf(seq, "VIU_MISC_CTRL0 0x%x.\n", dim_RDMA_RD(VIU_MISC_CTRL0)); + seq_printf(seq, "VIU_MISC_CTRL1 0x%x.\n", dim_RDMA_RD(VIU_MISC_CTRL1)); + seq_printf(seq, "VIUB_MISC_CTRL0 0x%x.\n", + dim_RDMA_RD(VIUB_MISC_CTRL0)); + + seq_printf(seq, "DI_PRE_CTRL bit8=%d,bit 28 =%d.\n", + dim_RDMA_RD_BITS(DI_PRE_CTRL, 8, 1), + dim_RDMA_RD_BITS(DI_PRE_CTRL, 28, 1)); + + return 0; +} + +/*2018-08-17 add debugfs*/ +#define DEFINE_SHOW_DI(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +DEFINE_SHOW_DI(seq_file_module_para); +/*DEFINE_SHOW_DI(seq_file_di_state);*/ +DEFINE_SHOW_DI(seq_file_dump_di_reg); +/*DEFINE_SHOW_DI(seq_file_dump_mif_size_state);*/ +DEFINE_SHOW_DI(seq_file_afbc); + +struct di_debugfs_files_t { + const char *name; + const umode_t mode; + const struct file_operations *fops; +}; + +static struct di_debugfs_files_t di_debugfs_files[] = { +/* {"state", S_IFREG | 0644, &seq_file_di_state_fops},*/ + {"dumpreg", S_IFREG | 0644, &seq_file_dump_di_reg_fops}, +/* {"dumpmif", S_IFREG | 0644, &seq_file_dump_mif_size_state_fops},*/ + {"dumpafbc", S_IFREG | 0644, &seq_file_afbc_fops}, + {"dumppara", S_IFREG | 0644, &seq_file_module_para_fops}, +}; + +void dim_debugfs_init(void) +{ + int i; + struct dentry *ent; + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (de_devp->dbg_root) + return; + + de_devp->dbg_root = debugfs_create_dir("di", NULL); + if (!de_devp->dbg_root) { + PR_ERR("can't create debugfs dir di\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(di_debugfs_files); i++) { + ent = debugfs_create_file(di_debugfs_files[i].name, + di_debugfs_files[i].mode, + de_devp->dbg_root, NULL, + di_debugfs_files[i].fops); + if (!ent) + PR_ERR("debugfs create failed\n"); + } +} + +void dim_debugfs_exit(void) +{ + struct di_dev_s *de_devp = get_dim_de_devp(); + + if (de_devp && de_devp->dbg_root) + debugfs_remove_recursive(de_devp->dbg_root); +} + +/*-----------------------*/ diff --git a/drivers/amlogic/media/di_multi/deinterlace_dbg.h b/drivers/amlogic/media/di_multi/deinterlace_dbg.h new file mode 100644 index 000000000000..7aa2ed2e0991 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace_dbg.h @@ -0,0 +1,43 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace_dbg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _DI_DBG_H +#define _DI_DBG_H +#include "deinterlace.h" + +void dim_parse_cmd_params(char *buf_orig, char **parm); +void dim_dump_pre_stru(struct di_pre_stru_s *ppre); +void dim_dump_post_stru(struct di_post_stru_s *di_post_stru_p); +void dim_dump_di_buf(struct di_buf_s *di_buf); +void dim_dump_pool(struct queue_s *q); +void dim_dump_vframe(vframe_t *vf); +void dim_print_di_buf(struct di_buf_s *di_buf, int format); +void dim_dump_pre_mif_state(void); +void dim_dump_post_mif_reg(void); +void dim_dump_buf_addr(struct di_buf_s *di_buf, unsigned int num); +void dim_dump_mif_size_state(struct di_pre_stru_s *pre, + struct di_post_stru_s *post); +void debug_device_files_add(struct device *dev); +void debug_device_files_del(struct device *dev); +void dim_debugfs_init(void); +void dim_debugfs_exit(void); +int dim_state_show(struct seq_file *seq, void *v, + unsigned int channel); +int dim_dump_mif_size_state_show(struct seq_file *seq, void *v, + unsigned int channel); + +#endif diff --git a/drivers/amlogic/media/di_multi/deinterlace_hw.c b/drivers/amlogic/media/di_multi/deinterlace_hw.c new file mode 100644 index 000000000000..5fa6bfb65c50 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace_hw.c @@ -0,0 +1,4236 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "deinterlace.h" +#include "di_data_l.h" + +#include "deinterlace_hw.h" +#include "register.h" +#include "register_nr4.h" +#ifdef DET3D +#include "detect3d.h" +#endif +#include "di_api.h" +#include "di_reg_tab.h" +#include "di_prc.h" + +#include + +static unsigned int ctrl_regs[SKIP_CTRE_NUM]; + +static void set_di_inp_fmt_more( + unsigned int repeat_l0_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ); + +static void set_di_inp_mif(struct DI_MIF_s *mif, int urgent, int hold_line); + +static void set_di_mem_fmt_more( + int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ); + +static void set_di_mem_mif(struct DI_MIF_s *mif, int urgent, int hold_line); + +static void set_di_if0_fmt_more( + int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ); + +static void set_di_if1_fmt_more( + int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ); + +static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt); + +static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line); + +static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt, int wr_en); + +static void set_di_if0_mif_g12(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt, int wr_en); + +static void ma_di_init(void) +{ + /* 420->422 chrome difference is large motion is large,flick */ + dim_DI_Wr(DI_MTN_1_CTRL4, 0x01800880); + dim_DI_Wr(DI_MTN_1_CTRL7, 0x0a800480); + /* mtn setting */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { + dim_DI_Wr_reg_bits(DI_MTN_CTRL, 1, 0, 1); + dim_DI_Wr(DI_MTN_1_CTRL1, 0x202015); + } else { + dim_DI_Wr(DI_MTN_1_CTRL1, 0xa0202015); + } + /* invert chan2 field num */ + dim_DI_Wr(DI_MTN_CTRL1, (1 << 17) | 2); + /* no invert chan2 field num from gxlx*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + dim_DI_Wr(DI_MTN_CTRL1, 2); +} + +static void ei_hw_init(void) +{ + /* ei setting */ + dim_DI_Wr(DI_EI_CTRL0, 0x00ff0100); + dim_DI_Wr(DI_EI_CTRL1, 0x5a0a0f2d); + dim_DI_Wr(DI_EI_CTRL2, 0x050a0a5d); + dim_DI_Wr(DI_EI_CTRL3, 0x80000013); + if (is_meson_txlx_cpu()) { + dim_DI_Wr_reg_bits(DI_EI_DRT_CTRL, 1, 30, 1); + dim_DI_Wr_reg_bits(DI_EI_DRT_CTRL, 1, 31, 1); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + dim_DI_Wr_reg_bits(DI_EI_DRT_CTRL_GXLX, 1, 30, 1); + dim_DI_Wr_reg_bits(DI_EI_DRT_CTRL_GXLX, 1, 31, 1); + } +} + +static void mc_di_param_init(void) +{ + dim_DI_Wr(MCDI_CHK_EDGE_GAIN_OFFST, 0x4f6124); + dim_DI_Wr(MCDI_LMV_RT, 0x7455); + dim_DI_Wr(MCDI_LMV_GAINTHD, 0x6014d409); + dim_DI_Wr(MCDI_REL_DET_LPF_MSK_22_30, 0x0a010001); + dim_DI_Wr(MCDI_REL_DET_LPF_MSK_31_34, 0x01010101); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_DI_Wr_reg_bits(MCDI_REF_MV_NUM, 2, 0, 2); +} + +void dimh_init_field_mode(unsigned short height) +{ + dim_DI_Wr(DIPD_COMB_CTRL0, 0x02400210); + dim_DI_Wr(DIPD_COMB_CTRL1, 0x88080808); + dim_DI_Wr(DIPD_COMB_CTRL2, 0x41041008); + dim_DI_Wr(DIPD_COMB_CTRL3, 0x00008053); + dim_DI_Wr(DIPD_COMB_CTRL4, 0x20070002); + if (height > 288) + dim_DI_Wr(DIPD_COMB_CTRL5, 0x04041020); + else + dim_DI_Wr(DIPD_COMB_CTRL5, 0x04040804); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + dim_DI_Wr(DIPD_COMB_CTRL6, 0x00107064); + dim_DI_Wr_reg_bits(DI_MC_32LVL0, 16, 0, 8); + dim_DI_Wr_reg_bits(DI_MC_22LVL0, 256, 0, 16); +} + +static void mc_pd22_check_irq(void) +{ + int cls_2_stl_thd = 1, cls_2_stl = 0; + int is_zmv = 0, no_gmv = 0; + int i, last_gmv, last_22_flg; + int cur_gmv, cur_22_flg; + unsigned int reg_val = 0; + + if (!dimp_get(eDI_MP_pd22_flg_calc_en)) + return; + + is_zmv = dim_RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 1, 1); + last_gmv = dim_RDMA_RD_BITS(MCDI_FIELD_MV, 0, 6); + last_gmv = last_gmv > 32 ? (32 - last_gmv) : last_gmv; + cur_gmv = dim_RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 2, 6); + cur_gmv = cur_gmv > 32 ? (32 - cur_gmv) : cur_gmv; + + cls_2_stl = abs(cur_gmv) <= cls_2_stl_thd; + no_gmv = (abs(cur_gmv) == 32 && (abs(last_gmv) <= cls_2_stl_thd)); + for (i = 0; i < 3; i++) { + last_22_flg = + dim_RDMA_RD_BITS(MCDI_PD_22_CHK_FLG_CNT, (24 + i), 1); + cur_22_flg = dim_RDMA_RD_BITS(MCDI_RO_PD_22_FLG, (24 + i), 1); + if ((is_zmv == 1 || cls_2_stl == 1 || no_gmv == 1) && + last_22_flg == 1 && cur_22_flg == 0) { + dim_RDMA_WR_BITS(MCDI_PD_22_CHK_FLG_CNT, + last_22_flg, (24 + i), 1); + reg_val = dim_RDMA_RD_BITS(MCDI_PD22_CHK_THD_RT, + 0, 5) - 1; + dim_RDMA_WR_BITS(MCDI_PD_22_CHK_FLG_CNT, + reg_val, i * 8, 8); + } else { + dim_RDMA_WR_BITS(MCDI_PD_22_CHK_FLG_CNT, + cur_22_flg, (24 + i), 1); + reg_val = + dim_RDMA_RD_BITS(MCDI_RO_PD_22_FLG, i * 8, 8); + dim_RDMA_WR_BITS(MCDI_PD_22_CHK_FLG_CNT, + reg_val, i * 8, 8); + } + } +} + +void dimh_mc_pre_mv_irq(void) +{ + unsigned int val1; + + if (dimp_get(eDI_MP_pd22_flg_calc_en) && is_meson_gxlx_cpu()) { + mc_pd22_check_irq(); + } else { + val1 = dim_RDMA_RD(MCDI_RO_PD_22_FLG); + dim_RDMA_WR(MCDI_PD_22_CHK_FLG_CNT, val1); + } + + val1 = dim_RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 0, 1); + dim_RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 0, 1); + val1 = dim_RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 1, 2); + dim_RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 2, 2); + val1 = dim_RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 8, 8); + dim_RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 8, 8); + val1 = dim_RDMA_RD_BITS(MCDI_RO_MOTION_PARADOX_FLG, 0, 16); + dim_RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 16, 16); + + val1 = dim_RDMA_RD_BITS(MCDI_RO_RPT_MV, 0, 6); + if (val1 == 32) { + val1 = 0; + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 15, 1); + } else { + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 15, 1); + } + + dim_RDMA_WR_BITS(MCDI_FIELD_MV, val1, 8, 6); + + val1 = dim_RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 0, 1); + dim_RDMA_WR_BITS(MCDI_FIELD_MV, val1, 14, 1); + + val1 = dim_RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 8, 8); + dim_RDMA_WR_BITS(MCDI_FIELD_MV, val1, 16, 8); + + val1 = dim_RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 2, 6); + if (val1 == 32) { + val1 = 0; + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 14, 1); + } else { + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 14, 1); + } + dim_RDMA_WR_BITS(MCDI_FIELD_MV, val1, 0, 6); + + val1 = dim_RDMA_RD(MCDI_FIELD_LUMA_AVG_SUM_1); + dim_RDMA_WR(MCDI_FIELD_LUMA_AVG_SUM_0, val1); + + val1 = dim_RDMA_RD(MCDI_RO_FLD_LUMA_AVG_SUM); + dim_RDMA_WR(MCDI_FIELD_LUMA_AVG_SUM_1, val1); +} + +static void lmvs_init(struct mcinfo_lmv_s *lmvs, unsigned short lmv) +{ + lmvs->lock_flag = (lmv >> 14) & 3; + lmvs->lmv = (lmv >> 8) & 63; + lmvs->lmv = lmvs->lmv > 32 ? (32 - lmvs->lmv) : lmvs->lmv; + lmvs->lock_cnt = (lmv & 255); +} + +void dimh_calc_lmv_init(void) +{ + if (dimp_get(eDI_MP_lmv_lock_win_en)) { + dim_RDMA_WR_BITS(MCDI_REL_DET_LMV_DIF_CHK, 3, 12, 2); + dim_RDMA_WR_BITS(MCDI_LMVLCKSTEXT_1, 3, 30, 2); + } else { + dim_RDMA_WR_BITS(MCDI_REL_DET_LMV_DIF_CHK, 0, 12, 2); + dim_RDMA_WR_BITS(MCDI_LMVLCKSTEXT_1, 0, 30, 2); + } +} + +static struct mcinfo_lmv_s lines_mv[540]; + +void dimh_calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr, + unsigned int mcinfo_size) +{ + unsigned short i, top_str, bot_str, top_end, bot_end, j = 0; + unsigned short *mcinfo_vadr = NULL, lck_num; + unsigned short flg_m1 = 0, flg_i = 0, nLmvLckSt = 0; + unsigned short lmv_lckstext[3] = {0, 0, 0}, nLmvLckEd; + unsigned short lmv_lckedext[3] = {0, 0, 0}, nLmvLckNum; + bool bflg_vmap = false; + u8 *tmp; + + /*mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr);*/ + + if (!dimp_get(eDI_MP_lmv_lock_win_en)) + return; + + tmp = dim_vmap(mcinfo_adr, mcinfo_size, &bflg_vmap); + if (!tmp) { + dim_print("err:dim_vmap failed\n"); + return; + } + mcinfo_vadr = (unsigned short *)tmp; + + for (i = 0; i < (vf_height >> 1); i++) { + lmvs_init(&lines_mv[i], *(mcinfo_vadr + i)); + j = i + (vf_height >> 1); + lmvs_init(&lines_mv[j], *(mcinfo_vadr + i + 272)); + if (dimp_get(eDI_MP_pr_mcinfo_cnt) && j < (vf_height - 10) && + j > (vf_height - dimp_get(eDI_MP_offset_lmv))) { + pr_info("MCINFO[%u]=0x%x\t", j, + *(mcinfo_vadr + i + 272)); + if (i % 16 == 0) + pr_info("\n"); + } + } + if (bflg_vmap) + dim_unmap_phyaddr(tmp); + + /*pr_mcinfo_cnt ? pr_mcinfo_cnt-- : (pr_mcinfo_cnt = 0);*/ + dimp_get(eDI_MP_pr_mcinfo_cnt) ? + dimp_dec(eDI_MP_pr_mcinfo_cnt) : + dimp_set(eDI_MP_pr_mcinfo_cnt, 0); + + top_str = 0; + top_end = dimp_get(eDI_MP_offset_lmv); + i = top_str; + j = 0; + lck_num = Rd_reg_bits(MCDI_LMVLCKSTEXT_1, 16, 12); + + while (i < top_end) { + flg_m1 = (i == top_str) ? 0 : + (lines_mv[i - 1].lock_flag > 0); + flg_i = (i == top_end - 1) ? 0 : + lines_mv[i].lock_flag > 0; + if (!flg_m1 && flg_i) { + #if 0 + nLmvLckSt = (j == 0) ? i : ((i < (lmv_lckedext[j - 1] + + dimp_get(eDI_MP_lmv_dist))) ? + lmv_lckstext[j - 1] : i); + #else + if (j == 0) { + nLmvLckSt = i; + } else { + if (i < (lmv_lckedext[j - 1] + + dimp_get(eDI_MP_lmv_dist))) + nLmvLckSt = lmv_lckstext[j - 1]; + else + nLmvLckSt = i; + } + #endif + j = (nLmvLckSt != i) ? (j - 1) : j; + } else if (flg_m1 && !flg_i) { + nLmvLckEd = i; + nLmvLckNum = (nLmvLckEd - nLmvLckSt + 1); + if (nLmvLckNum >= lck_num) { + lmv_lckstext[j] = nLmvLckSt; + lmv_lckedext[j] = nLmvLckEd; + j++; + } + } + i++; + if (j > 2) + break; + } + + bot_str = vf_height - dimp_get(eDI_MP_offset_lmv) - 1; + bot_end = vf_height; + i = bot_str; + while (i < bot_end && j < 3) { + flg_m1 = (i == bot_str) ? 0 : + (lines_mv[i - 1].lock_flag > 0); + flg_i = (i == bot_end - 1) ? 0 : + lines_mv[i].lock_flag > 0; + if (!flg_m1 && flg_i) { + nLmvLckSt = (j == 0) ? i : ((i < (lmv_lckedext[j - 1] + + dimp_get(eDI_MP_lmv_dist))) ? + lmv_lckstext[j - 1] : i); + j = (nLmvLckSt != i) ? (j - 1) : j; + } else if (flg_m1 && !flg_i) { + nLmvLckEd = i; + nLmvLckNum = (nLmvLckEd - nLmvLckSt + 1); + if (nLmvLckNum >= lck_num) { + lmv_lckstext[j] = nLmvLckSt; + lmv_lckedext[j] = nLmvLckEd; + j++; + } + } + i++; + if (j > 2) + break; + } + + Wr(MCDI_LMVLCKSTEXT_0, lmv_lckstext[1] << 16 | lmv_lckstext[0]); + Wr_reg_bits(MCDI_LMVLCKSTEXT_1, lmv_lckstext[2], 0, 12); + Wr(MCDI_LMVLCKEDEXT_0, lmv_lckedext[1] << 16 | lmv_lckedext[0]); + Wr(MCDI_LMVLCKEDEXT_1, lmv_lckedext[2]); +} + +/* + * config pre hold ratio & mif request block len + * pass_ratio = (pass_cnt + 1)/(pass_cnt + 1 + hold_cnt + 1) + */ +static void pre_hold_block_mode_config(void) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_DI_Wr(DI_PRE_HOLD, 0); + /* go field after 2 lines */ + dim_DI_Wr(DI_PRE_GL_CTRL, + (0x80000000 | dimp_get(eDI_MP_line_num_pre_frst))); + } else if (is_meson_txlx_cpu()) { + /* setup pre process ratio to 66.6%*/ + dim_DI_Wr(DI_PRE_HOLD, (1 << 31) | (1 << 16) | 3); + /* block len, after block insert null req to balance reqs */ + dim_DI_Wr_reg_bits(DI_INP_GEN_REG3, 0, 4, 3); + dim_DI_Wr_reg_bits(DI_MEM_GEN_REG3, 0, 4, 3); + dim_DI_Wr_reg_bits(DI_CHAN2_GEN_REG3, 0, 4, 3); + dim_DI_Wr_reg_bits(DI_IF1_GEN_REG3, 0, 4, 3); + dim_DI_Wr_reg_bits(DI_IF2_GEN_REG3, 0, 4, 3); + dim_DI_Wr_reg_bits(VD1_IF0_GEN_REG3, 0, 4, 3); + } else { + dim_DI_Wr(DI_PRE_HOLD, (1 << 31) | (31 << 16) | 31); + } +} + +/* + * ctrl or size related regs configured + * in software base on real size and condition + */ +static void set_skip_ctrl_size_regs(void) +{ + ctrl_regs[0] = DI_CLKG_CTRL; + ctrl_regs[1] = DI_MTN_1_CTRL1; + ctrl_regs[2] = MCDI_MOTINEN; + ctrl_regs[3] = MCDI_CTRL_MODE; + ctrl_regs[4] = MCDI_MC_CRTL; + ctrl_regs[5] = MCDI_PD_22_CHK_WND0_X; + ctrl_regs[6] = MCDI_PD_22_CHK_WND0_Y; + ctrl_regs[7] = MCDI_PD_22_CHK_WND1_X; + ctrl_regs[8] = MCDI_PD_22_CHK_WND1_Y; + ctrl_regs[9] = NR4_MCNR_LUMA_STAT_LIMTX; + ctrl_regs[10] = NR4_MCNR_LUMA_STAT_LIMTY; + ctrl_regs[11] = NR4_NM_X_CFG; + ctrl_regs[12] = NR4_NM_Y_CFG; +} + +void dim_hw_init_reg(void) +{ + unsigned short fifo_size_post = 0x120;/*feijun 08-02*/ + + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { + dim_DI_Wr(DI_IF1_LUMA_FIFO_SIZE, fifo_size_post); + /* 17f2 is DI_IF1_luma_fifo_size */ + dim_DI_Wr(DI_IF2_LUMA_FIFO_SIZE, fifo_size_post); + dim_DI_Wr(DI_IF0_LUMA_FIFO_SIZE, fifo_size_post); + } + + PR_INF("%s, 0x%x\n", __func__, dim_RDMA_RD(DI_IF0_LUMA_FIFO_SIZE)); +} + +void dimh_hw_init(bool pd_enable, bool mc_enable) +{ + unsigned short fifo_size_vpp = 0xc0; + unsigned short fifo_size_di = 0xc0; + + diext_clk_b_sw(true); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + dim_top_gate_control(true, true); + else if (is_meson_gxl_cpu() || + is_meson_gxm_cpu() || + is_meson_gxlx_cpu()) + dim_DI_Wr(DI_CLKG_CTRL, 0xffff0001); + else + dim_DI_Wr(DI_CLKG_CTRL, 0x1); /* di no clock gate */ + + if (is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { + /* vpp fifo max size on txl :128*3=384[0x180] */ + /* di fifo max size on txl :96*3=288[0x120] */ + fifo_size_vpp = 0x180; + fifo_size_di = 0x120; + } + + /*enable lock win, suggestion from vlsi zheng.bao*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dimp_set(eDI_MP_lmv_lock_win_en, 0);/*lmv_lock_win_en = 0;*/ + + dim_DI_Wr(VD1_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); + dim_DI_Wr(VD2_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); + /* 1a83 is vd2_if0_luma_fifo_size */ + dim_DI_Wr(DI_INP_LUMA_FIFO_SIZE, fifo_size_di); + /* 17d8 is DI_INP_luma_fifo_size */ + dim_DI_Wr(DI_MEM_LUMA_FIFO_SIZE, fifo_size_di); + /* 17e5 is DI_MEM_luma_fifo_size */ + dim_DI_Wr(DI_IF1_LUMA_FIFO_SIZE, fifo_size_di); + /* 17f2 is DI_IF1_luma_fifo_size */ + dim_DI_Wr(DI_IF2_LUMA_FIFO_SIZE, fifo_size_di); + /* 201a is if2 fifo size */ + dim_DI_Wr(DI_CHAN2_LUMA_FIFO_SIZE, fifo_size_di); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_DI_Wr(DI_IF0_LUMA_FIFO_SIZE, fifo_size_di); + dim_DI_Wr(DI_ARB_CTRL, 0); + } else { + /* enable di all arb */ + dim_DI_Wr_reg_bits(DI_ARB_CTRL, 0xf0f, 0, 16); + } + /* 17b3 is DI_chan2_luma_fifo_size */ + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { + dim_pre_gate_control(true, true); + dim_post_gate_control(true); + } + + pre_hold_block_mode_config(); + set_skip_ctrl_size_regs(); + ma_di_init(); + ei_hw_init(); + get_ops_nr()->nr_hw_init(); + if (pd_enable) + dimh_init_field_mode(288); + + if (mc_enable) + mc_di_param_init(); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu() || + is_meson_g12a_cpu() || + is_meson_sm1_cpu() || + is_meson_g12b_cpu() || + is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { + dim_pre_gate_control(false, true); + dim_post_gate_control(false); + dim_top_gate_control(false, false); + } else if (is_meson_txl_cpu() || is_meson_gxlx_cpu()) { + /* di clock div enable for pq load */ + dim_DI_Wr(DI_CLKG_CTRL, 0x80000000); + } else { + dim_DI_Wr(DI_CLKG_CTRL, 0x2); /* di clock gate all */ + } + + diext_clk_b_sw(false); + + /*move from prob*/ + dim_DI_Wr_reg_bits(MCDI_MC_CRTL, 0, 0, 1); +} + +void dimh_hw_uninit(void) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) + get_ops_nr()->nr_gate_control(false); +} + +/* + * mtn wr mif, contprd mif, contp2rd mif, + * contwr mif config + */ +static void set_ma_pre_mif(struct DI_SIM_MIF_s *mtnwr_mif, + struct DI_SIM_MIF_s *contprd_mif, + struct DI_SIM_MIF_s *contp2rd_mif, + struct DI_SIM_MIF_s *contwr_mif, + unsigned short urgent) +{ + /* current field mtn canvas index. */ + dim_RDMA_WR(DI_MTNWR_X, + (mtnwr_mif->start_x << 16) | + (mtnwr_mif->end_x)); + dim_RDMA_WR(DI_MTNWR_Y, + (mtnwr_mif->start_y << 16) | + (mtnwr_mif->end_y)); + dim_RDMA_WR(DI_MTNWR_CTRL, + mtnwr_mif->canvas_num | + (urgent << 8)); /* urgent. */ + + dim_RDMA_WR(DI_CONTPRD_X, + (contprd_mif->start_x << 16) | + (contprd_mif->end_x)); + dim_RDMA_WR(DI_CONTPRD_Y, + (contprd_mif->start_y << 16) | + (contprd_mif->end_y)); + dim_RDMA_WR(DI_CONTP2RD_X, + (contp2rd_mif->start_x << 16) | + (contp2rd_mif->end_x)); + dim_RDMA_WR(DI_CONTP2RD_Y, + (contp2rd_mif->start_y << 16) | + (contp2rd_mif->end_y)); + dim_RDMA_WR(DI_CONTRD_CTRL, + (contprd_mif->canvas_num << 8) | + (urgent << 16) | /* urgent */ + contp2rd_mif->canvas_num); + + dim_RDMA_WR(DI_CONTWR_X, + (contwr_mif->start_x << 16) | + (contwr_mif->end_x)); + dim_RDMA_WR(DI_CONTWR_Y, + (contwr_mif->start_y << 16) | + (contwr_mif->end_y)); + dim_RDMA_WR(DI_CONTWR_CTRL, + contwr_mif->canvas_num | + (urgent << 8));/* urgent. */ +} + +static void set_ma_pre_mif_g12(struct DI_SIM_MIF_s *mtnwr_mif, + struct DI_SIM_MIF_s *contprd_mif, + struct DI_SIM_MIF_s *contp2rd_mif, + struct DI_SIM_MIF_s *contwr_mif, + unsigned short urgent) +{ + dim_RDMA_WR_BITS(CONTRD_SCOPE_X, contprd_mif->start_x, 0, 13); + dim_RDMA_WR_BITS(CONTRD_SCOPE_X, contprd_mif->end_x, 16, 13); + dim_RDMA_WR_BITS(CONTRD_SCOPE_Y, contprd_mif->start_y, 0, 13); + dim_RDMA_WR_BITS(CONTRD_SCOPE_Y, contprd_mif->end_y, 16, 13); + dim_RDMA_WR_BITS(CONTRD_CTRL1, contprd_mif->canvas_num, 16, 8); + dim_RDMA_WR_BITS(CONTRD_CTRL1, 2, 8, 2); + dim_RDMA_WR_BITS(CONTRD_CTRL1, 0, 0, 3); + + dim_RDMA_WR_BITS(CONT2RD_SCOPE_X, contp2rd_mif->start_x, 0, 13); + dim_RDMA_WR_BITS(CONT2RD_SCOPE_X, contp2rd_mif->end_x, 16, 13); + dim_RDMA_WR_BITS(CONT2RD_SCOPE_Y, contp2rd_mif->start_y, 0, 13); + dim_RDMA_WR_BITS(CONT2RD_SCOPE_Y, contp2rd_mif->end_y, 16, 13); + dim_RDMA_WR_BITS(CONT2RD_CTRL1, contp2rd_mif->canvas_num, 16, 8); + dim_RDMA_WR_BITS(CONT2RD_CTRL1, 2, 8, 2); + dim_RDMA_WR_BITS(CONT2RD_CTRL1, 0, 0, 3); + + /* current field mtn canvas index. */ + dim_RDMA_WR_BITS(MTNWR_X, mtnwr_mif->start_x, 16, 13); + dim_RDMA_WR_BITS(MTNWR_X, mtnwr_mif->end_x, 0, 13); + dim_RDMA_WR_BITS(MTNWR_X, 2, 30, 2); + dim_RDMA_WR_BITS(MTNWR_Y, mtnwr_mif->start_y, 16, 13); + dim_RDMA_WR_BITS(MTNWR_Y, mtnwr_mif->end_y, 0, 13); + dim_RDMA_WR_BITS(MTNWR_CTRL, mtnwr_mif->canvas_num, 0, 8); + dim_RDMA_WR_BITS(MTNWR_CAN_SIZE, + (mtnwr_mif->end_y - mtnwr_mif->start_y), 0, 13); + dim_RDMA_WR_BITS(MTNWR_CAN_SIZE, + (mtnwr_mif->end_x - mtnwr_mif->start_x), 16, 13); + + dim_RDMA_WR_BITS(CONTWR_X, contwr_mif->start_x, 16, 13); + dim_RDMA_WR_BITS(CONTWR_X, contwr_mif->end_x, 0, 13); + dim_RDMA_WR_BITS(CONTWR_X, 2, 30, 2); + dim_RDMA_WR_BITS(CONTWR_Y, contwr_mif->start_y, 16, 13); + dim_RDMA_WR_BITS(CONTWR_Y, contwr_mif->end_y, 0, 13); + dim_RDMA_WR_BITS(CONTWR_CTRL, contwr_mif->canvas_num, 0, 8); + dim_RDMA_WR_BITS(CONTWR_CAN_SIZE, + (contwr_mif->end_y - contwr_mif->start_y), 0, 13); + dim_RDMA_WR_BITS(CONTWR_CAN_SIZE, + (contwr_mif->end_x - contwr_mif->start_x), 16, 13); +} + +static void set_di_nrwr_mif(struct DI_SIM_MIF_s *nrwr_mif, + unsigned short urgent) +{ + dim_RDMA_WR_BITS(DI_NRWR_X, nrwr_mif->end_x, 0, 14); + dim_RDMA_WR_BITS(DI_NRWR_X, nrwr_mif->start_x, 16, 14); + dim_RDMA_WR_BITS(DI_NRWR_Y, nrwr_mif->start_y, 16, 13); + dim_RDMA_WR_BITS(DI_NRWR_Y, nrwr_mif->end_y, 0, 13); + /* wr ext en from gxtvbb */ + dim_RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); + dim_RDMA_WR_BITS(DI_NRWR_Y, 3, 30, 2); + + dim_RDMA_WR_BITS(DI_NRWR_Y, nrwr_mif->bit_mode & 0x1, 14, 1); + + /*fix 1080i crash when di work on low speed*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL) && + ((nrwr_mif->bit_mode & 0x3) == 0x3)) { + dim_RDMA_WR(DI_NRWR_CTRL, + nrwr_mif->canvas_num | + (urgent << 16) | + 3 << 22 | + 1 << 24 | + 2 << 26 | /*burst_lim 1->2 2->4*/ + 1 << 30); /* urgent bit 16 */ + } else { + dim_RDMA_WR(DI_NRWR_CTRL, + nrwr_mif->canvas_num | + (urgent << 16) | + 1 << 24 | + 2 << 26 | /*burst_lim 1->2 2->4*/ + 1 << 30); /* urgent bit 16 */ + } +} + +void dimh_interrupt_ctrl(unsigned char ma_en, + unsigned char det3d_en, unsigned char nrds_en, + unsigned char post_wr, unsigned char mc_en) +{ + dim_RDMA_WR_BITS(DI_INTR_CTRL, ma_en ? 0 : 1, 17, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, ma_en ? 0 : 1, 20, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, mc_en ? 0 : 3, 22, 2); + /* enable nr wr int */ + dim_RDMA_WR_BITS(DI_INTR_CTRL, 0, 16, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, post_wr ? 0 : 1, 18, 1); + /* mask me interrupt hit abnormal */ + dim_RDMA_WR_BITS(DI_INTR_CTRL, 1, 21, 1); + /* mask hist interrupt */ + dim_RDMA_WR_BITS(DI_INTR_CTRL, 1, 19, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, det3d_en ? 0 : 1, 24, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, nrds_en ? 0 : 1, 25, 1); + /* clean all pending interrupt bits */ + dim_RDMA_WR_BITS(DI_INTR_CTRL, 0xffff, 0, 16); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dim_RDMA_WR_BITS(DI_INTR_CTRL, 3, 30, 2); + else + dim_RDMA_WR_BITS(DI_INTR_CTRL, 0, 30, 2); +} + +void dimh_int_ctr(unsigned int set_mod, unsigned char ma_en, + unsigned char det3d_en, unsigned char nrds_en, + unsigned char post_wr, unsigned char mc_en) +{ + static unsigned char lst_ma, lst_det3d, lst_nrds, lst_pw, lst_mc; + + if (set_mod == 0) { + /*int:*/ + lst_ma = 1; + lst_det3d = 0; + lst_nrds = 1; + lst_pw = 1; + lst_mc = 1; + dimh_interrupt_ctrl(lst_ma, + lst_det3d, + lst_nrds, + lst_pw, + lst_mc); + return; + } + + if (ma_en != lst_ma) { + dim_RDMA_WR_BITS(DI_INTR_CTRL, ma_en ? 0 : 1, 17, 1); + dim_RDMA_WR_BITS(DI_INTR_CTRL, ma_en ? 0 : 1, 20, 1); + lst_ma = ma_en; + } + if (mc_en != lst_mc) { + dim_RDMA_WR_BITS(DI_INTR_CTRL, mc_en ? 0 : 3, 22, 2); + lst_mc = mc_en; + } + + if (post_wr != lst_pw) { + dim_RDMA_WR_BITS(DI_INTR_CTRL, post_wr ? 0 : 1, 18, 1); + lst_pw = post_wr; + } + + if (det3d_en != lst_det3d) { + dim_RDMA_WR_BITS(DI_INTR_CTRL, det3d_en ? 0 : 1, 24, 1); + lst_det3d = det3d_en; + } + + if (nrds_en != lst_nrds) { + dim_RDMA_WR_BITS(DI_INTR_CTRL, nrds_en ? 0 : 1, 25, 1); + lst_nrds = nrds_en; + } +} + +void dimh_enable_di_pre_aml( + struct DI_MIF_s *di_inp_mif, + struct DI_MIF_s *di_mem_mif, + struct DI_MIF_s *di_chan2_mif, + struct DI_SIM_MIF_s *di_nrwr_mif, + struct DI_SIM_MIF_s *di_mtnwr_mif, + struct DI_SIM_MIF_s *di_contp2rd_mif, + struct DI_SIM_MIF_s *di_contprd_mif, + struct DI_SIM_MIF_s *di_contwr_mif, + unsigned char madi_en, unsigned char pre_field_num, + unsigned char pre_vdin_link) +{ + bool mem_bypass = false, chan2_disable = false; + unsigned short nrwr_hsize = 0, nrwr_vsize = 0; + unsigned short chan2_hsize = 0, chan2_vsize = 0; + unsigned short mem_hsize = 0, mem_vsize = 0; + + set_di_inp_mif(di_inp_mif, + dimp_get(eDI_MP_pre_urgent), + dimp_get(eDI_MP_pre_hold_line)); + set_di_nrwr_mif(di_nrwr_mif, + dimp_get(eDI_MP_pre_urgent)); + set_di_mem_mif(di_mem_mif, + dimp_get(eDI_MP_pre_urgent), + dimp_get(eDI_MP_pre_hold_line)); + set_di_chan2_mif(di_chan2_mif, + dimp_get(eDI_MP_pre_urgent), + dimp_get(eDI_MP_pre_hold_line)); + + nrwr_hsize = di_nrwr_mif->end_x - + di_nrwr_mif->start_x + 1; + nrwr_vsize = di_nrwr_mif->end_y - + di_nrwr_mif->start_y + 1; + chan2_hsize = di_chan2_mif->luma_x_end0 - + di_chan2_mif->luma_x_start0 + 1; + chan2_vsize = di_chan2_mif->luma_y_end0 - + di_chan2_mif->luma_y_start0 + 1; + mem_hsize = di_mem_mif->luma_x_end0 - + di_mem_mif->luma_x_start0 + 1; + mem_vsize = di_mem_mif->luma_y_end0 - + di_mem_mif->luma_y_start0 + 1; + if ((chan2_hsize != nrwr_hsize) || (chan2_vsize != nrwr_vsize)) + chan2_disable = true; + if ((mem_hsize != nrwr_hsize) || (mem_vsize != nrwr_vsize)) + mem_bypass = true; + /* + * enable&disable contwr txt + */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) + dim_RDMA_WR_BITS(DI_MTN_CTRL, madi_en ? 5 : 0, 29, 3); + else + dim_RDMA_WR_BITS(DI_MTN_1_CTRL1, madi_en ? 5 : 0, 29, 3); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (madi_en) { + set_ma_pre_mif_g12(di_mtnwr_mif, + di_contprd_mif, + di_contp2rd_mif, + di_contwr_mif, + dimp_get(eDI_MP_pre_urgent)); + } else { + chan2_disable = true; + } + dim_RDMA_WR_BITS(DI_PRE_GL_THD, + dimp_get(eDI_MP_pre_hold_line), 16, 6); + if (dimp_get(eDI_MP_pre_ctrl)) + dim_RDMA_WR_BITS(DI_PRE_CTRL, + dimp_get(eDI_MP_pre_ctrl), 0, 29); + else + dim_RDMA_WR(DI_PRE_CTRL, + 1 | /* nr wr en */ + (madi_en << 1) | /* mtn en */ + (madi_en << 2) | /* check3:2pulldown*/ + (madi_en << 3) | /* check2:2pulldown*/ + (1 << 4) | + (madi_en << 5) | /*hist check enable*/ + /* hist check use chan2. */ + (madi_en << 6) | + /*hist check use data before noise reduction.*/ + ((chan2_disable ? 0 : 1) << 8) | + /* chan 2 enable for 2:2 pull down check.*/ + /* line buffer 2 enable */ + ((chan2_disable ? 0 : 1) << 9) | + (0 << 10) | /* pre drop first. */ + (1 << 11) | /* nrds mif enable */ + (0 << 12) | /* pre viu link */ + (pre_vdin_link << 13) | + /* pre go line link */ + (pre_vdin_link << 14) | + (1 << 21) | /*invertNRfield num*/ + (1 << 22) | /* MTN after NR. */ + (0 << 25) | /* contrd en */ + ((mem_bypass ? 1 : 0) << 28) | + pre_field_num << 29); + } else { + if (madi_en) { + set_ma_pre_mif(di_mtnwr_mif, + di_contprd_mif, + di_contp2rd_mif, + di_contwr_mif, + dimp_get(eDI_MP_pre_urgent)); + } + dim_RDMA_WR(DI_PRE_CTRL, + 1 /* nr enable */ + | (madi_en << 1) /* mtn_en */ + | (madi_en << 2) /* check 3:2 pulldown */ + | (madi_en << 3) /* check 2:2 pulldown */ + | (1 << 4) + | (madi_en << 5) /* hist check enable */ + | (1 << 6) /* hist check use chan2. */ + | (0 << 7) + /* hist check use data before noise reduction. */ + | (madi_en << 8) + /* chan 2 enable for 2:2 pull down check.*/ + | (madi_en << 9) /* line buffer 2 enable */ + | (0 << 10) /* pre drop first. */ + | (0 << 11) /* di pre repeat */ + | (0 << 12) /* pre viu link */ + | (pre_vdin_link << 13) + | (pre_vdin_link << 14) /* pre go line link */ + | (dimp_get(eDI_MP_pre_hold_line) << 16) + /* pre hold line number */ + | (1 << 22) /* MTN after NR. */ + | (madi_en << 25) /* contrd en */ + | (pre_field_num << 29) /* pre field number.*/ + ); + } +} + +/* + * after g12a, framereset will not reset simple + * wr mif of pre such as mtn&cont&mv&mcinfo wr + */ +static const unsigned int reg_AFBC[AFBC_DEC_NUB][AFBC_REG_INDEX_NUB] = { + { + AFBC_ENABLE, + AFBC_MODE, + AFBC_SIZE_IN, + AFBC_DEC_DEF_COLOR, + AFBC_CONV_CTRL, + AFBC_LBUF_DEPTH, + AFBC_HEAD_BADDR, + AFBC_BODY_BADDR, + AFBC_SIZE_OUT, + AFBC_OUT_YSCOPE, + AFBC_STAT, + AFBC_VD_CFMT_CTRL, + AFBC_VD_CFMT_W, + AFBC_MIF_HOR_SCOPE, + AFBC_MIF_VER_SCOPE, + AFBC_PIXEL_HOR_SCOPE, + AFBC_PIXEL_VER_SCOPE, + AFBC_VD_CFMT_H, + }, + { + VD2_AFBC_ENABLE, + VD2_AFBC_MODE, + VD2_AFBC_SIZE_IN, + VD2_AFBC_DEC_DEF_COLOR, + VD2_AFBC_CONV_CTRL, + VD2_AFBC_LBUF_DEPTH, + VD2_AFBC_HEAD_BADDR, + VD2_AFBC_BODY_BADDR, + VD2_AFBC_OUT_XSCOPE, + VD2_AFBC_OUT_YSCOPE, + VD2_AFBC_STAT, + VD2_AFBC_VD_CFMT_CTRL, + VD2_AFBC_VD_CFMT_W, + VD2_AFBC_MIF_HOR_SCOPE, + VD2_AFBC_MIF_VER_SCOPE, + VD2_AFBC_PIXEL_HOR_SCOPE, + VD2_AFBC_PIXEL_VER_SCOPE, + VD2_AFBC_VD_CFMT_H, + + }, + +}; + +#define AFBC_DEC_SEL (eAFBC_DEC1) + +static enum eAFBC_DEC afbc_get_decnub(void) +{ + enum eAFBC_DEC sel_dec = eAFBC_DEC0; + + if (is_meson_gxl_cpu()) + sel_dec = eAFBC_DEC0; + else if (is_meson_txlx_cpu()) + sel_dec = eAFBC_DEC1; + else if (is_meson_g12a_cpu()) + sel_dec = AFBC_DEC_SEL; + /* TL1 only have AFBC0 */ + else if (is_meson_tl1_cpu()) + sel_dec = eAFBC_DEC0; + return sel_dec; +} + +static const unsigned int *afbc_get_regbase(void) +{ + return ®_AFBC[afbc_get_decnub()][0]; +} + +bool dimh_afbc_is_supported(void) +{ + bool ret = false; + + /*currently support txlx and g12a*/ + if (is_meson_txlx_cpu() || + is_meson_g12a_cpu() + /*|| is_meson_tl1_cpu()*/) + ret = false; + return ret; +} + +static void afbc_sw_trig(bool on); + +void dimh_enable_afbc_input(struct vframe_s *vf) +{ + unsigned int r, u, v, w_aligned, h_aligned; + unsigned int out_height = 0; + unsigned int vfmt_rpt_first = 1, vt_ini_phase = 0; + const unsigned int *reg = afbc_get_regbase(); + + if (!dimh_afbc_is_supported()) + return; + + if ((vf->type & VIDTYPE_COMPRESS)) { + /* only reg for the first time*/ + dimh_afbc_reg_sw(true); + afbc_sw_trig(true); + } else { + afbc_sw_trig(false); + return; + } + w_aligned = round_up((vf->width - 1), 32); + h_aligned = round_up((vf->height - 1), 4); + r = (3 << 24) | + (10 << 16) | + (1 << 14) | /*burst1 1*/ + (vf->bitdepth & BITDEPTH_MASK); + if (vf->bitdepth & BITDEPTH_SAVING_MODE) + r |= (1 << 28); /* mem_saving_mode */ + if (vf->type & VIDTYPE_SCATTER) + r |= (1 << 29); + out_height = h_aligned; + if ((vf->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) { + r |= 0x40; + vt_ini_phase = 0xc; + out_height = h_aligned >> 1; + } else if ((vf->type & VIDTYPE_TYPEMASK) == + VIDTYPE_INTERLACE_BOTTOM) { + r |= 0x80; + vt_ini_phase = 0x4; + vfmt_rpt_first = 0; + out_height = h_aligned >> 1; + } + dim_RDMA_WR(reg[eAFBC_MODE], r); + r = 0x100; + /* TL1 add bit[13:12]: fmt_mode; 0:yuv444; 1:yuv422; 2:yuv420 + * di does not support yuv444, so for fmt yuv444 di will bypass+ + */ + if (is_meson_tl1_cpu()) { + if (vf->type & VIDTYPE_VIU_444) + r |= (0 << 12); + else if (vf->type & VIDTYPE_VIU_422) + r |= (1 << 12); + else + r |= (2 << 12); + } + dim_RDMA_WR(reg[eAFBC_CONV_CTRL], r); + u = (vf->bitdepth >> (BITDEPTH_U_SHIFT)) & 0x3; + v = (vf->bitdepth >> (BITDEPTH_V_SHIFT)) & 0x3; + dim_RDMA_WR(reg[eAFBC_DEC_DEF_COLOR], + 0x3FF00000 | /*Y,bit20+*/ + 0x80 << (u + 10) | + 0x80 << v); + /* chroma formatter */ + dim_RDMA_WR(reg[eAFBC_VD_CFMT_CTRL], + (1 << 21) | /* HFORMATTER_YC_RATIO_2_1 */ + (1 << 20) | /* HFORMATTER_EN */ + (vfmt_rpt_first << 16) | /* VFORMATTER_RPTLINE0_EN */ + (vt_ini_phase << 8) | + (16 << 1) | /* VFORMATTER_PHASE_BIT */ + 0); /* different with inp */ + + dim_RDMA_WR(reg[eAFBC_VD_CFMT_W], + (w_aligned << 16) | (w_aligned / 2)); + dim_RDMA_WR(reg[eAFBC_MIF_HOR_SCOPE], + (0 << 16) | ((w_aligned >> 5) - 1)); + dim_RDMA_WR(reg[eAFBC_MIF_VER_SCOPE], + (0 << 16) | ((h_aligned >> 2) - 1)); + + dim_RDMA_WR(reg[eAFBC_PIXEL_HOR_SCOPE], + (0 << 16) | (vf->width - 1)); + dim_RDMA_WR(reg[eAFBC_VD_CFMT_H], out_height); + + dim_RDMA_WR(reg[eAFBC_PIXEL_VER_SCOPE], + 0 << 16 | (vf->height - 1)); + dim_RDMA_WR(reg[eAFBC_SIZE_IN], h_aligned | w_aligned << 16); + dim_RDMA_WR(reg[eAFBC_SIZE_OUT], out_height | w_aligned << 16); + dim_RDMA_WR(reg[eAFBC_HEAD_BADDR], vf->compHeadAddr >> 4); + dim_RDMA_WR(reg[eAFBC_BODY_BADDR], vf->compBodyAddr >> 4); +} + +static void afbcx_power_sw(enum eAFBC_DEC decsel, bool on) /*g12a*/ +{ + unsigned int reg_ctrl; + + if (decsel == eAFBC_DEC0) + reg_ctrl = VD1_AFBCD0_MISC_CTRL; + else + reg_ctrl = VD2_AFBCD1_MISC_CTRL; + if (on) + dim_RDMA_WR_BITS(reg_ctrl, 0, 0, 8); + else + dim_RDMA_WR_BITS(reg_ctrl, 0x55, 0, 8); +} + +static void afbcx_sw(bool on) /*g12a*/ +{ + unsigned int tmp; + unsigned int mask; + unsigned int reg_ctrl, reg_en; + enum eAFBC_DEC dec_sel; + + dec_sel = afbc_get_decnub(); + + if (dec_sel == eAFBC_DEC0) { + reg_ctrl = VD1_AFBCD0_MISC_CTRL; + reg_en = AFBC_ENABLE; + } else { + reg_ctrl = VD2_AFBCD1_MISC_CTRL; + reg_en = VD2_AFBC_ENABLE; + } + + mask = (3 << 20) | (1 << 12) | (1 << 9); + /*clear*/ + tmp = dim_RDMA_RD(reg_ctrl) & (~mask); + + if (on) { + tmp = tmp | + (2 << 20) | + (1 << 12) | + (1 << 9); + dim_RDMA_WR(reg_ctrl, tmp); + dim_RDMA_WR_BITS(VD2_AFBCD1_MISC_CTRL, + (reg_ctrl == VD1_AFBCD0_MISC_CTRL) ? 0 : 1, + 8, 1); + dim_RDMA_WR(reg_en, 0x1600); + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); + /*TL1 add mem control bit */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + dim_RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 1, 22, 1); + } else { + dim_RDMA_WR(reg_ctrl, tmp); + dim_RDMA_WR(reg_en, 0x1600); + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) + dim_RDMA_WR_BITS(VD1_AFBCD0_MISC_CTRL, 0, 22, 1); + } +#if 0 + PR_INF("%s,on[%d],CTRL[0x%x],en[0x%x]\n", __func__, on, + dim_RDMA_RD(VD1_AFBCD0_MISC_CTRL), + dim_RDMA_RD(VD1_AFBCD0_MISC_CTRL)); +#endif +} + +static void afbc_sw_old(bool on)/*txlx*/ +{ + enum eAFBC_DEC dec_sel; + unsigned int reg_en; + + dec_sel = afbc_get_decnub(); + + if (dec_sel == eAFBC_DEC0) { + /*reg_ctrl = VD1_AFBCD0_MISC_CTRL;*/ + reg_en = AFBC_ENABLE; + } else { + /*reg_ctrl = VD2_AFBCD1_MISC_CTRL;*/ + reg_en = VD2_AFBC_ENABLE; + } + + if (on) { + /* DI inp(current data) switch to AFBC */ + if (dim_RDMA_RD_BITS(VIU_MISC_CTRL0, 29, 1) != 1) + dim_RDMA_WR_BITS(VIU_MISC_CTRL0, 1, 29, 1); + if (dim_RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) != 1) + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 1, 16, 1); + if (dim_RDMA_RD_BITS(VIU_MISC_CTRL1, 0, 1) != 1) + dim_RDMA_WR_BITS(VIU_MISC_CTRL1, 1, 0, 1); + if (dec_sel == eAFBC_DEC0) { + /*gxl only?*/ + if (dim_RDMA_RD_BITS(VIU_MISC_CTRL0, 19, 1) != 1) + dim_RDMA_WR_BITS(VIU_MISC_CTRL0, 1, 19, 1); + } + if (dim_RDMA_RD(reg_en) != 0x1600) + dim_RDMA_WR(reg_en, 0x1600); + + } else { + dim_RDMA_WR(reg_en, 0); + /* afbc to vpp(replace vd1) enable */ + + if (dim_RDMA_RD_BITS(VIU_MISC_CTRL1, 0, 1) != 0 || + dim_RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) != 0) { + dim_RDMA_WR_BITS(VIU_MISC_CTRL1, 0, 0, 1); + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 0, 16, 1); + } + } +} + +static bool afbc_is_used(void) +{ + bool ret = false; + + if (dim_RDMA_RD_BITS(VIUB_MISC_CTRL0, 16, 1) == 1) + ret = true; + + /*dim_print("%s:%d\n",__func__,ret);*/ + + return ret; +} + +static void afbc_power_sw(bool on) +{ + /*afbc*/ + enum eAFBC_DEC dec_sel; + unsigned int vpu_sel; + + dec_sel = afbc_get_decnub(); + if (dec_sel == eAFBC_DEC0) + vpu_sel = VPU_AFBC_DEC; + else + vpu_sel = VPU_AFBC_DEC1; + + ext_ops.switch_vpu_mem_pd_vmod(vpu_sel, on); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + afbcx_power_sw(dec_sel, on); +} + +static int afbc_reg_unreg_flag; +void dimh_afbc_reg_sw(bool on) +{ + if (!dimh_afbc_is_supported()) + return; + + if (on && (!afbc_reg_unreg_flag)) { + afbc_power_sw(true); + afbc_reg_unreg_flag = 1; + } + if ((!on) && afbc_reg_unreg_flag) { + afbc_sw_trig(false); + afbc_power_sw(false); + afbc_reg_unreg_flag = 0; + } +} + +static void afbc_sw(bool on) +{ + if (is_meson_gxl_cpu() || is_meson_txlx_cpu()) + afbc_sw_old(on); + else + afbcx_sw(on); +} + +static void afbc_sw_trig(bool on) +{ + afbc_sw(on); +} + +static void afbc_input_sw(bool on) +{ + const unsigned int *reg = afbc_get_regbase(); + unsigned int reg_AFBC_ENABLE; + + if (!dimh_afbc_is_supported()) + return; + + reg_AFBC_ENABLE = reg[eAFBC_ENABLE]; + + /*dim_print("%s:0x%x\n", __func__,reg_AFBC_ENABLE);*/ + if (on) + dim_RDMA_WR_BITS(reg_AFBC_ENABLE, 1, 8, 1); + else + dim_RDMA_WR_BITS(reg_AFBC_ENABLE, 0, 8, 1); +} + +void dimh_enable_mc_di_pre_g12(struct DI_MC_MIF_s *mcinford_mif, + struct DI_MC_MIF_s *mcinfowr_mif, + struct DI_MC_MIF_s *mcvecwr_mif, + unsigned char mcdi_en) +{ + dim_RDMA_WR_BITS(MCDI_MOTINEN, (mcdi_en ? 3 : 0), 0, 2); + if (is_meson_g12a_cpu() || + is_meson_g12b_cpu() || + is_meson_sm1_cpu()) + dim_RDMA_WR(MCDI_CTRL_MODE, (mcdi_en ? 0x1bfef7ff : 0)); + else + dim_RDMA_WR(MCDI_CTRL_MODE, (mcdi_en ? 0x1bfff7ff : 0)); + + dim_RDMA_WR_BITS(DI_PRE_CTRL, (mcdi_en ? 3 : 0), 16, 2); + + dim_RDMA_WR_BITS(MCINFRD_SCOPE_X, mcinford_mif->size_x, 16, 13); + dim_RDMA_WR_BITS(MCINFRD_SCOPE_Y, mcinford_mif->size_y, 16, 13); + dim_RDMA_WR_BITS(MCINFRD_CTRL1, mcinford_mif->canvas_num, 16, 8); + dim_RDMA_WR_BITS(MCINFRD_CTRL1, 2, 0, 3); + + dim_RDMA_WR_BITS(MCVECWR_X, mcvecwr_mif->size_x, 0, 13); + dim_RDMA_WR_BITS(MCVECWR_Y, mcvecwr_mif->size_y, 0, 13); + dim_RDMA_WR_BITS(MCVECWR_CTRL, mcvecwr_mif->canvas_num, 0, 8); + dim_RDMA_WR_BITS(MCVECWR_CAN_SIZE, mcvecwr_mif->size_y, 0, 13); + dim_RDMA_WR_BITS(MCVECWR_CAN_SIZE, mcvecwr_mif->size_x, 16, 13); + + dim_RDMA_WR_BITS(MCINFWR_X, mcinfowr_mif->size_x, 0, 13); + dim_RDMA_WR_BITS(MCINFWR_Y, mcinfowr_mif->size_y, 0, 13); + dim_RDMA_WR_BITS(MCINFWR_CTRL, mcinfowr_mif->canvas_num, 0, 8); + dim_RDMA_WR_BITS(MCINFWR_CAN_SIZE, mcinfowr_mif->size_y, 0, 13); + dim_RDMA_WR_BITS(MCINFWR_CAN_SIZE, mcinfowr_mif->size_x, 16, 13); +} + +void dimh_enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, + struct DI_MC_MIF_s *di_mcinfowr_mif, + struct DI_MC_MIF_s *di_mcvecwr_mif, + unsigned char mcdi_en) +{ + bool me_auto_en = true; + unsigned int ctrl_mode = 0; + + dim_RDMA_WR_BITS(DI_MTN_CTRL1, (mcdi_en ? 3 : 0), 12, 2); + if (is_meson_gxlx_cpu() || is_meson_txhd_cpu()) + me_auto_en = false; + + ctrl_mode = (me_auto_en ? 0x1bfff7ff : 0x1bfe37ff); + dim_RDMA_WR(MCDI_CTRL_MODE, (mcdi_en ? ctrl_mode : 0)); + dim_RDMA_WR_BITS(MCDI_MOTINEN, (mcdi_en ? 3 : 0), 0, 2); + + dim_RDMA_WR(MCDI_MCVECWR_X, di_mcvecwr_mif->size_x); + dim_RDMA_WR(MCDI_MCVECWR_Y, di_mcvecwr_mif->size_y); + dim_RDMA_WR(MCDI_MCINFOWR_X, di_mcinfowr_mif->size_x); + dim_RDMA_WR(MCDI_MCINFOWR_Y, di_mcinfowr_mif->size_y); + + dim_RDMA_WR(MCDI_MCINFORD_X, di_mcinford_mif->size_x); + dim_RDMA_WR(MCDI_MCINFORD_Y, di_mcinford_mif->size_y); + dim_RDMA_WR(MCDI_MCVECWR_CANVAS_SIZE, + (di_mcvecwr_mif->size_x << 16) + di_mcvecwr_mif->size_y); + dim_RDMA_WR(MCDI_MCINFOWR_CANVAS_SIZE, + (di_mcinfowr_mif->size_x << 16) + di_mcinfowr_mif->size_y); + dim_RDMA_WR(MCDI_MCINFORD_CANVAS_SIZE, + (di_mcinford_mif->size_x << 16) + di_mcinford_mif->size_y); + + dim_RDMA_WR(MCDI_MCVECWR_CTRL, + di_mcvecwr_mif->canvas_num | + (0 << 14) | /* sync latch en */ + (dimp_get(eDI_MP_pre_urgent) << 8) | /* urgent */ + (1 << 12) | /*enable reset by frame rst*/ + (0x4031 << 16)); + dim_RDMA_WR(MCDI_MCINFOWR_CTRL, + di_mcinfowr_mif->canvas_num | + (0 << 14) | /* sync latch en */ + (dimp_get(eDI_MP_pre_urgent) << 8) | /* urgent */ + (1 << 12) | /*enable reset by frame rst*/ + (0x4042 << 16)); + dim_RDMA_WR(MCDI_MCINFORD_CTRL, + di_mcinford_mif->canvas_num | + (0 << 10) | /* sync latch en */ + (dimp_get(eDI_MP_pre_urgent) << 8) | /* urgent */ + (1 << 9) | /*enable reset by frame rst*/ + (0x42 << 16)); +} + +void dimh_enable_mc_di_post_g12(struct DI_MC_MIF_s *mcvecrd_mif, + int urgent, bool reverse, int invert_mv) +{ + unsigned int end_x; + + dim_VSYNC_WR_MPEG_REG(MCVECRD_CTRL1, + mcvecrd_mif->canvas_num << 16 | + 2 << 8 | + (reverse ? 3 : 0) << 4 | + 2); + end_x = mcvecrd_mif->size_x + mcvecrd_mif->start_x; + dim_VSYNC_WR_MPEG_REG(MCVECRD_SCOPE_X, + mcvecrd_mif->start_x | + end_x << 16); + dim_VSYNC_WR_MPEG_REG(MCVECRD_SCOPE_Y, + (reverse ? 1 : 0) << 30 | + mcvecrd_mif->start_y | + mcvecrd_mif->end_y << 16); + dim_VSYNC_WR_MPEG_REG_BITS(MCVECRD_CTRL2, urgent, 16, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, mcvecrd_mif->vecrd_offset, + 12, 3); + if (mcvecrd_mif->blend_en) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcen_mode), 0, 2); + if (!di_cfg_top_get(eDI_CFG_ref_2)) { + /*(!dimp_get(eDI_MP_post_wr_en)) {*/ + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 3, 18, 2); + } else {/*OTT-3210*/ + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 2, 18, 2); + } + } else { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 2, 18, 2); + } + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcuv_en), 10, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + invert_mv, 17, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcdebug_mode), 2, 3); +} + +void dimh_enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif, + int urgent, bool reverse, int invert_mv) +{ + di_mcvecrd_mif->size_y = + (di_mcvecrd_mif->end_y - di_mcvecrd_mif->start_y + 1); + dim_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_X, + (reverse ? 1 : 0) << 30 | + di_mcvecrd_mif->start_x << 16 | + (di_mcvecrd_mif->size_x + + di_mcvecrd_mif->start_x)); + dim_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_Y, + (reverse ? 1 : 0) << 30 | + di_mcvecrd_mif->start_y << 16 | + di_mcvecrd_mif->end_y); + dim_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_CANVAS_SIZE, + (di_mcvecrd_mif->size_x << 16) | + di_mcvecrd_mif->size_y); + dim_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_CTRL, + di_mcvecrd_mif->canvas_num | + (urgent << 8) | /* urgent */ + (1 << 9) | /* canvas enable */ + (0 << 10) | + (0x31 << 16)); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, di_mcvecrd_mif->vecrd_offset, + 12, 3); + if (di_mcvecrd_mif->blend_en) + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcen_mode), 0, 2); + else + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcuv_en), 10, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + invert_mv, 17, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 3, 18, 2); + } + } else + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcuv_en), 9, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcdebug_mode), 2, 3); +} + +static void set_di_inp_fmt_more(unsigned int repeat_l0_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int hfmt_en = 1, nrpt_phase0_en = 0; + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_RDMA_WR(DI_INP_FMT_CTRL, + (hz_rpt << 28) | /* hz rpt pixel */ + (hz_ini_phase << 24) | /* hz ini phase */ + (0 << 23) | /* repeat p0 enable */ + (hz_yc_ratio << 21) | /* hz yc ratio */ + (hfmt_en << 20) | /* hz enable */ + (nrpt_phase0_en << 17) | /* nrpt_phase0 enable */ + (repeat_l0_en << 16) | /* repeat l0 enable */ + (0 << 12) | /* skip line num */ + (vt_ini_phase << 8) | /* vt ini phase */ + (vt_phase_step << 1) | /* vt phase step (3.4) */ + (vfmt_en << 0) /* vt enable */ + ); + + dim_RDMA_WR(DI_INP_FMT_W, + (y_length << 16) | /* hz format width */ + (c_length << 0) /* vt format width */ + ); +} + +static void set_di_inp_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +{ + unsigned int bytes_per_pixel; + unsigned int demux_mode; + unsigned int chro_rpt_lastl_ctrl, vfmt_rpt_first = 0; + unsigned int luma0_rpt_loop_start; + unsigned int luma0_rpt_loop_end; + unsigned int luma0_rpt_loop_pat; + unsigned int chroma0_rpt_loop_start; + unsigned int chroma0_rpt_loop_end; + unsigned int chroma0_rpt_loop_pat; + unsigned int vt_ini_phase = 0; + unsigned int reset_on_gofield; + + if (mif->set_separate_en != 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = mif->src_prog ? 0 : 1; + chroma0_rpt_loop_end = mif->src_prog ? 0 : 1; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = mif->src_prog ? 0 : 0x80; + + vfmt_rpt_first = 1; + if (mif->output_field_num == 0) + vt_ini_phase = 0xe; + else + vt_ini_phase = 0xa; + + if (mif->src_prog) { + if (mif->output_field_num == 0) { + vt_ini_phase = 0xc; + } else { + vt_ini_phase = 0x4; + vfmt_rpt_first = 0; + } + } + + } else if (mif->set_separate_en != 0 && mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x0; + chroma0_rpt_loop_pat = 0x0; + } else if (mif->set_separate_en == 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 1; + chroma0_rpt_loop_end = 1; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x80; + } else { + chro_rpt_lastl_ctrl = 0; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x00; + chroma0_rpt_loop_pat = 0x00; + } + + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + demux_mode = mif->video_mode; + + /* ---------------------- */ + /* General register */ + /* ---------------------- */ + reset_on_gofield = 1;/* default enable according to vlsi */ + dim_RDMA_WR(DI_INP_GEN_REG, + (reset_on_gofield << 29) | + (urgent << 28) | /* chroma urgent bit */ + (urgent << 27) | /* luma urgent bit. */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | /*burst_size_cr*/ + (1 << 10) | /*burst_size_cb*/ + (3 << 8) | /*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1) | + (0 << 0)/* cntl_enable */ + ); + if (mif->set_separate_en == 2) { + /* Enable NV12 Display */ + dim_RDMA_WR_BITS(DI_INP_GEN_REG2, 1, 0, 1); + } else { + dim_RDMA_WR_BITS(DI_INP_GEN_REG2, 0, 0, 1); + } + + dim_RDMA_WR_BITS(DI_INP_GEN_REG3, mif->bit_mode & 0x3, 8, 2); + dim_RDMA_WR(DI_INP_CANVAS0, + (mif->canvas0_addr2 << 16) | /* cntl_canvas0_addr2 */ + (mif->canvas0_addr1 << 8) | /* cntl_canvas0_addr1 */ + (mif->canvas0_addr0 << 0) /* cntl_canvas0_addr0 */ + ); + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_RDMA_WR(DI_INP_LUMA_X0, (mif->luma_x_end0 << 16) | + /* cntl_luma_x_end0 */ + (mif->luma_x_start0 << 0)/* cntl_luma_x_start0 */ + ); + dim_RDMA_WR(DI_INP_LUMA_Y0, (mif->luma_y_end0 << 16) | + /* cntl_luma_y_end0 */ + (mif->luma_y_start0 << 0) /* cntl_luma_y_start0 */ + ); + dim_RDMA_WR(DI_INP_CHROMA_X0, (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_RDMA_WR(DI_INP_CHROMA_Y0, (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_RDMA_WR(DI_INP_RPT_LOOP, + (0 << 28) | + (0 << 24) | + (0 << 20) | + (0 << 16) | + (chroma0_rpt_loop_start << 12) | + (chroma0_rpt_loop_end << 8) | + (luma0_rpt_loop_start << 4) | + (luma0_rpt_loop_end << 0) + ); + + dim_RDMA_WR(DI_INP_LUMA0_RPT_PAT, luma0_rpt_loop_pat); + dim_RDMA_WR(DI_INP_CHROMA0_RPT_PAT, chroma0_rpt_loop_pat); + + /* Dummy pixel value */ + dim_RDMA_WR(DI_INP_DUMMY_PIXEL, 0x00808000); + if ((mif->set_separate_en != 0)) {/* 4:2:0 block mode.*/ + set_di_inp_fmt_more(vfmt_rpt_first,/* hfmt_en */ + 1,/* hz_yc_ratio */ + 0,/* hz_ini_phase */ + 1,/* vfmt_en */ + mif->src_prog ? 0 : 1,/* vt_yc_ratio */ + vt_ini_phase,/* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + /* y_length */ + mif->chroma_x_end0 - mif->chroma_x_start0 + 1, + /* c length */ + 0); /* hz repeat. */ + } else { + set_di_inp_fmt_more(vfmt_rpt_first, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + ((mif->luma_x_end0 >> 1) - + (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat. */ + } +} + +static void set_di_mem_fmt_more(int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_RDMA_WR(DI_MEM_FMT_CTRL, + (hz_rpt << 28) | /* hz rpt pixel */ + (hz_ini_phase << 24) | /* hz ini phase */ + (0 << 23) | /* repeat p0 enable */ + (hz_yc_ratio << 21) | /* hz yc ratio */ + (hfmt_en << 20) | /* hz enable */ + (1 << 17) | /* nrpt_phase0 enable */ + (0 << 16) | /* repeat l0 enable */ + (0 << 12) | /* skip line num */ + (vt_ini_phase << 8) | /* vt ini phase */ + (vt_phase_step << 1) | /* vt phase step (3.4) */ + (vfmt_en << 0) /* vt enable */ + ); + + dim_RDMA_WR(DI_MEM_FMT_W, + (y_length << 16) | /* hz format width */ + (c_length << 0) /* vt format width */ + ); +} + +static void set_di_chan2_fmt_more(int hfmt_en, + int hz_yc_ratio,/* 2bit */ + int hz_ini_phase,/* 4bit */ + int vfmt_en, + int vt_yc_ratio,/* 2bit */ + int vt_ini_phase,/* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_RDMA_WR(DI_CHAN2_FMT_CTRL, + (hz_rpt << 28) | /* hz rpt pixel */ + (hz_ini_phase << 24) | /* hz ini phase */ + (0 << 23) | /* repeat p0 enable */ + (hz_yc_ratio << 21) | /* hz yc ratio */ + (hfmt_en << 20) | /* hz enable */ + (1 << 17) | /* nrpt_phase0 enable */ + (0 << 16) | /* repeat l0 enable */ + (0 << 12) | /* skip line num */ + (vt_ini_phase << 8) | /* vt ini phase */ + (vt_phase_step << 1) | /* vt phase step (3.4) */ + (vfmt_en << 0) /* vt enable */ + ); + + dim_RDMA_WR(DI_CHAN2_FMT_W, (y_length << 16) | /* hz format width */ + (c_length << 0) /* vt format width */ + ); +} + +static void set_di_mem_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +{ + unsigned int bytes_per_pixel; + unsigned int demux_mode; + unsigned int chro_rpt_lastl_ctrl; + unsigned int luma0_rpt_loop_start; + unsigned int luma0_rpt_loop_end; + unsigned int luma0_rpt_loop_pat; + unsigned int chroma0_rpt_loop_start; + unsigned int chroma0_rpt_loop_end; + unsigned int chroma0_rpt_loop_pat; + unsigned int reset_on_gofield; + + if (mif->set_separate_en != 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 1; + chroma0_rpt_loop_end = 1; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x80; + } else if (mif->set_separate_en != 0 && mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x0; + chroma0_rpt_loop_pat = 0x0; + } else if (mif->set_separate_en == 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x00; + } else { + chro_rpt_lastl_ctrl = 0; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x00; + chroma0_rpt_loop_pat = 0x00; + } + + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + demux_mode = mif->video_mode; + + /* ---------------------- */ + /* General register */ + /* ---------------------- */ + reset_on_gofield = 1;/* default enable according to vlsi */ + dim_RDMA_WR(DI_MEM_GEN_REG, + (reset_on_gofield << 29) | /* reset on go field */ + (urgent << 28) | /* urgent bit. */ + (urgent << 27) | /* urgent bit. */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | /*burst_size_cr*/ + (1 << 10) | /*burst_size_cb*/ + (3 << 8) | /*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1) | + (0 << 0) /* cntl_enable */ + ); + if (mif->set_separate_en == 2) { + /* Enable NV12 Display */ + dim_RDMA_WR_BITS(DI_MEM_GEN_REG2, 1, 0, 1); + } else { + dim_RDMA_WR_BITS(DI_MEM_GEN_REG2, 0, 0, 1); + } + dim_RDMA_WR_BITS(DI_MEM_GEN_REG3, mif->bit_mode & 0x3, 8, 2); + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + dim_RDMA_WR(DI_MEM_CANVAS0, + (mif->canvas0_addr2 << 16) | + /* cntl_canvas0_addr2 */ + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_RDMA_WR(DI_MEM_LUMA_X0, + (mif->luma_x_end0 << 16) | + (mif->luma_x_start0 << 0) /* cntl_luma_x_start0 */ + ); + dim_RDMA_WR(DI_MEM_LUMA_Y0, + (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0) /* cntl_luma_y_start0 */ + ); + dim_RDMA_WR(DI_MEM_CHROMA_X0, + (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0) + ); + dim_RDMA_WR(DI_MEM_CHROMA_Y0, + (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0) + ); + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_RDMA_WR(DI_MEM_RPT_LOOP, (0 << 28) | + (0 << 24) | + (0 << 20) | + (0 << 16) | + (chroma0_rpt_loop_start << 12) | + (chroma0_rpt_loop_end << 8) | + (luma0_rpt_loop_start << 4) | + (luma0_rpt_loop_end << 0) + ); + + dim_RDMA_WR(DI_MEM_LUMA0_RPT_PAT, luma0_rpt_loop_pat); + dim_RDMA_WR(DI_MEM_CHROMA0_RPT_PAT, chroma0_rpt_loop_pat); + + /* Dummy pixel value */ + dim_RDMA_WR(DI_MEM_DUMMY_PIXEL, 0x00808000); + if ((mif->set_separate_en != 0)) {/* 4:2:0 block mode.*/ + set_di_mem_fmt_more( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + /* y_length */ + mif->chroma_x_end0 - mif->chroma_x_start0 + 1, + /* c length */ + 0); /* hz repeat. */ + } else { + set_di_mem_fmt_more(1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + ((mif->luma_x_end0 >> 1) + - (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat. */ + } +} + +static void set_di_if0_fmt_more(int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_VSYNC_WR_MPEG_REG(VIU_VD1_FMT_CTRL, + (hz_rpt << 28) | /* hz rpt pixel */ + (hz_ini_phase << 24) | /* hz ini phase */ + (0 << 23) | /* repeat p0 enable*/ + (hz_yc_ratio << 21) | /* hz yc ratio */ + (hfmt_en << 20) | /* hz enable */ + (1 << 17) | /* nrpt_phase0 en*/ + (0 << 16) | /* repeat l0 en*/ + (0 << 12) | /* skip line num */ + (vt_ini_phase << 8) | /* vt ini phase */ + (vt_phase_step << 1) | /*vt phase step(3.4*/ + (vfmt_en << 0) /* vt enable */ + ); + + dim_VSYNC_WR_MPEG_REG(VIU_VD1_FMT_W, + (y_length << 16) | /* hz format width */ + (c_length << 0) /* vt format width */ + ); +} + +static void set_di_if1_fmt_more(int hfmt_en, + int hz_yc_ratio,/* 2bit */ + int hz_ini_phase,/* 4bit */ + int vfmt_en, + int vt_yc_ratio,/* 2bit */ + int vt_ini_phase,/* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_VSYNC_WR_MPEG_REG(DI_IF1_FMT_CTRL, + (hz_rpt << 28) /* hz rpt pixel */ + | (hz_ini_phase << 24) /* hz ini phase */ + | (0 << 23) /* repeat p0 enable */ + | (hz_yc_ratio << 21) /* hz yc ratio */ + | (hfmt_en << 20) /* hz enable */ + | (1 << 17) /* nrpt_phase0 enable*/ + | (0 << 16) /* repeat l0 enable */ + | (0 << 12) /* skip line num */ + | (vt_ini_phase << 8) /* vt ini phase */ + | (vt_phase_step << 1) /* vt phase step_3.4*/ + | (vfmt_en << 0) /* vt enable */ + ); + + dim_VSYNC_WR_MPEG_REG(DI_IF1_FMT_W, + (y_length << 16) | (c_length << 0)); +} + +static void set_di_if2_fmt_more(int hfmt_en, + int hz_yc_ratio,/* 2bit */ + int hz_ini_phase,/* 4bit */ + int vfmt_en, + int vt_yc_ratio,/* 2bit */ + int vt_ini_phase,/* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_VSYNC_WR_MPEG_REG(DI_IF2_FMT_CTRL, + (hz_rpt << 28) /* hz rpt pixel */ + | (hz_ini_phase << 24) /* hz ini phase */ + | (0 << 23) /* repeat p0 enable */ + | (hz_yc_ratio << 21) /* hz yc ratio */ + | (hfmt_en << 20) /* hz enable */ + | (1 << 17) /* nrpt_phase0 enable*/ + | (0 << 16) /* repeat l0 enable */ + | (0 << 12) /* skip line num */ + | (vt_ini_phase << 8) /* vt ini phase */ + | (vt_phase_step << 1) /* vt phase step(3.4)*/ + | (vfmt_en << 0) /* vt enable */ + ); + + dim_VSYNC_WR_MPEG_REG(DI_IF2_FMT_W, + (y_length << 16) | (c_length << 0)); +} + +static const u32 vpat[] = {0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + +static void set_di_if2_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt) +{ + unsigned int bytes_per_pixel, demux_mode; + unsigned int pat, loop = 0, chro_rpt_lastl_ctrl = 0; + + if (mif->set_separate_en == 1) { + pat = vpat[(vskip_cnt << 1) + 1]; + /*top*/ + if (mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; + loop = 0x11; + pat <<= 4; + } + } else { + loop = 0; + pat = vpat[vskip_cnt]; + } + #if 0 + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + #else + if (mif->set_separate_en) { + bytes_per_pixel = 0; + } else { + if (mif->video_mode) + bytes_per_pixel = 2; + else + bytes_per_pixel = 1; + } + #endif + demux_mode = mif->video_mode; + + /* ---------------------- */ + /* General register */ + /* ---------------------- */ + + dim_VSYNC_WR_MPEG_REG(DI_IF2_GEN_REG, + (1 << 29) | /* reset on go field */ + (urgent << 28) | /* urgent */ + (urgent << 27) | /* luma urgent */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | /*burst_size_cr*/ + (1 << 10) | /*burst_size_cb*/ + (3 << 8) | /*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1) | + (1 << 0)/* cntl_enable */ + ); + /* post bit mode config, if0 config in video.c + * dim_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG3, mif->bit_mode, 8, 2); + */ + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF2_CANVAS0, (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | (mif->canvas0_addr0 << 0)); + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF2_LUMA_X0, (mif->luma_x_end0 << 16) | + (mif->luma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF2_LUMA_Y0, (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF2_CHROMA_X0, (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF2_CHROMA_Y0, (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF2_RPT_LOOP, + (loop << 24) | + (loop << 16) | + (loop << 8) | + (loop << 0) + ); + + dim_VSYNC_WR_MPEG_REG(DI_IF2_LUMA0_RPT_PAT, pat); + dim_VSYNC_WR_MPEG_REG(DI_IF2_CHROMA0_RPT_PAT, pat); + + /* Dummy pixel value */ + dim_VSYNC_WR_MPEG_REG(DI_IF2_DUMMY_PIXEL, 0x00808000); + if (mif->set_separate_en != 0) { /* 4:2:0 block mode. */ + set_di_if2_fmt_more(1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + mif->chroma_x_end0 - + mif->chroma_x_start0 + 1, + 0); /* hz repeat. */ + } else { + set_di_if2_fmt_more(1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + ((mif->luma_x_end0 >> 1) - + (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat */ + } +} + +static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt) +{ + unsigned int bytes_per_pixel, demux_mode; + unsigned int pat, loop = 0, chro_rpt_lastl_ctrl = 0; + + if (mif->set_separate_en == 1) { + pat = vpat[(vskip_cnt << 1) + 1]; + /*top*/ + if (mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; + loop = 0x11; + pat <<= 4; + } + } else { + loop = 0; + pat = vpat[vskip_cnt]; + } + #if 0 + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + #else + if (mif->set_separate_en) { + bytes_per_pixel = 0; + } else { + if (mif->video_mode) + bytes_per_pixel = 2; + else + bytes_per_pixel = 1; + } + #endif + demux_mode = mif->video_mode; + + /* ---------------------- */ + /* General register */ + /* ---------------------- */ + + dim_VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, + (1 << 29) | /* reset on go field */ + (urgent << 28) | /* urgent */ + (urgent << 27) | /* luma urgent */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | /*burst_size_cr*/ + (1 << 10) | /*burst_size_cb*/ + (3 << 8) | /*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1) | + (1 << 0) /* cntl_enable */ + ); + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF1_CANVAS0, + (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF1_LUMA_X0, + (mif->luma_x_end0 << 16) | + (mif->luma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF1_LUMA_Y0, + (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF1_CHROMA_X0, + (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF1_CHROMA_Y0, + (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF1_RPT_LOOP, + (loop << 24) | + (loop << 16) | + (loop << 8) | + (loop << 0) + ); + + dim_VSYNC_WR_MPEG_REG(DI_IF1_LUMA0_RPT_PAT, pat); + dim_VSYNC_WR_MPEG_REG(DI_IF1_CHROMA0_RPT_PAT, pat); + + /* Dummy pixel value */ + dim_VSYNC_WR_MPEG_REG(DI_IF1_DUMMY_PIXEL, 0x00808000); + if (mif->set_separate_en != 0) { /* 4:2:0 block mode. */ + set_di_if1_fmt_more(1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + mif->chroma_x_end0 - + mif->chroma_x_start0 + 1, + 0); /* hz repeat. */ + } else { + set_di_if1_fmt_more(1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + ((mif->luma_x_end0 >> 1) - + (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat */ + } +} + +static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +{ + unsigned int bytes_per_pixel; + unsigned int demux_mode; + unsigned int chro_rpt_lastl_ctrl; + unsigned int luma0_rpt_loop_start; + unsigned int luma0_rpt_loop_end; + unsigned int luma0_rpt_loop_pat; + unsigned int chroma0_rpt_loop_start; + unsigned int chroma0_rpt_loop_end; + unsigned int chroma0_rpt_loop_pat; + unsigned int reset_on_gofield; + + if (mif->set_separate_en != 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 1; + chroma0_rpt_loop_end = 1; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x80; + } else if (mif->set_separate_en != 0 && mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x0; + chroma0_rpt_loop_pat = 0x0; + } else if (mif->set_separate_en == 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x00; + } else { + chro_rpt_lastl_ctrl = 0; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x00; + chroma0_rpt_loop_pat = 0x00; + } + #if 0 + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + #else + if (mif->set_separate_en) { + bytes_per_pixel = 0; + } else { + if (mif->video_mode) + bytes_per_pixel = 2; + else + bytes_per_pixel = 1; + } + #endif + demux_mode = mif->video_mode; + + /* ---------------------- */ + /* General register */ + /* ---------------------- */ + reset_on_gofield = 1;/* default enable according to vlsi */ + dim_RDMA_WR(DI_CHAN2_GEN_REG, + (reset_on_gofield << 29) | + (urgent << 28) | /* urgent */ + (urgent << 27) | /* luma urgent */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | + (bytes_per_pixel << 14) | + (1 << 12) | /*burst_size_cr*/ + (1 << 10) | /*burst_size_cb*/ + (3 << 8) | /*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1) | + (0 << 0) /* cntl_enable */ + ); + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + if (mif->set_separate_en == 2) { + /* Enable NV12 Display */ + dim_RDMA_WR_BITS(DI_CHAN2_GEN_REG2, 1, 0, 1); + } else { + dim_RDMA_WR_BITS(DI_CHAN2_GEN_REG2, 0, 0, 1); + } + dim_RDMA_WR_BITS(DI_CHAN2_GEN_REG3, mif->bit_mode & 0x3, 8, 2); + dim_RDMA_WR(DI_CHAN2_CANVAS0, (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_RDMA_WR(DI_CHAN2_LUMA_X0, (mif->luma_x_end0 << 16) | + /* cntl_luma_x_end0 */ + (mif->luma_x_start0 << 0)); + dim_RDMA_WR(DI_CHAN2_LUMA_Y0, (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + dim_RDMA_WR(DI_CHAN2_CHROMA_X0, (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_RDMA_WR(DI_CHAN2_CHROMA_Y0, (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_RDMA_WR(DI_CHAN2_RPT_LOOP, + (0 << 28) | + (0 << 24) | + (0 << 20) | + (0 << 16) | + (0 << 12) | + (0 << 8) | + (luma0_rpt_loop_start << 4) | + (luma0_rpt_loop_end << 0) + ); + + dim_RDMA_WR(DI_CHAN2_LUMA0_RPT_PAT, luma0_rpt_loop_pat); + + /* Dummy pixel value */ + dim_RDMA_WR(DI_CHAN2_DUMMY_PIXEL, 0x00808000); + + if ((mif->set_separate_en != 0)) { /* 4:2:0 block mode. */ + set_di_chan2_fmt_more( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - + mif->luma_x_start0 + 1, /* y_length */ + mif->chroma_x_end0 - + mif->chroma_x_start0 + 1,/* c length */ + 0); /* hz repeat. */ + } else { + set_di_chan2_fmt_more( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + mif->luma_x_end0 - + mif->luma_x_start0 + 1, /* y_length */ + ((mif->luma_x_end0 >> 1) - + (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat. */ + } +} + +static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, int hold_line, + int vskip_cnt, int post_write_en) +{ + unsigned int pat, loop = 0; + unsigned int bytes_per_pixel, demux_mode; + + if (mif->set_separate_en == 1) { + pat = vpat[(vskip_cnt << 1) + 1]; + if (mif->src_field_mode == 0) {/* top */ + loop = 0x11; + pat <<= 4; + } + } else { + loop = 0; + pat = vpat[vskip_cnt]; + + if (post_write_en) { + bytes_per_pixel = + mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + demux_mode = mif->video_mode; + dim_VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG, + (1 << 29) | /* reset on go field */ + (urgent << 28) | /* urgent */ + (urgent << 27) | /* luma urgent */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | + (1 << 10) | + (3 << 8) | + (0 << 6) | + ((mif->set_separate_en != 0) << 1) | + (1 << 0) /* cntl_enable */ + ); + } + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(VD1_IF0_CANVAS0, + (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_X0, (mif->luma_x_end0 << 16) | + (mif->luma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(VD1_IF0_LUMA_Y0, (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_X0, (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA_Y0, (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + } + + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(VD1_IF0_RPT_LOOP, + (loop << 24) | + (loop << 16) | + (loop << 8) | + (loop << 0)); + dim_VSYNC_WR_MPEG_REG(VD1_IF0_LUMA0_RPT_PAT, pat); + dim_VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA0_RPT_PAT, pat); + + if (post_write_en) { + /* 4:2:0 block mode. */ + if (mif->set_separate_en != 0) { + set_di_if0_fmt_more( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + /* y_length */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + /* c length */ + mif->chroma_x_end0 - mif->chroma_x_start0 + 1, + 0); /* hz repeat. */ + } else { + set_di_if0_fmt_more( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + /* y_length */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + /* c length */ + ((mif->luma_x_end0 >> 1) - ( + mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat */ + } + } +} + +static void set_di_if0_fmt_more_g12(int hfmt_en, + int hz_yc_ratio, /* 2bit */ + int hz_ini_phase, /* 4bit */ + int vfmt_en, + int vt_yc_ratio, /* 2bit */ + int vt_ini_phase, /* 4bit */ + int y_length, + int c_length, + int hz_rpt /* 1bit */ + ) +{ + int vt_phase_step = (16 >> vt_yc_ratio); + + dim_VSYNC_WR_MPEG_REG(DI_IF0_FMT_CTRL, + (hz_rpt << 28) | /* hz rpt pixel */ + (hz_ini_phase << 24) | /* hz ini phase */ + (0 << 23) | /* repeat p0 enable */ + (hz_yc_ratio << 21) | /* hz yc ratio */ + (hfmt_en << 20) | /* hz enable */ + (1 << 17) | /* nrpt_phase0 enable */ + (0 << 16) | /* repeat l0 enable */ + (0 << 12) | /* skip line num */ + (vt_ini_phase << 8) | /* vt ini phase */ + (vt_phase_step << 1) | /* vt phase step (3.4) */ + (vfmt_en << 0) /* vt enable */ + ); + + dim_VSYNC_WR_MPEG_REG(DI_IF0_FMT_W, + (y_length << 16) | /* hz format width */ + (c_length << 0) /* vt format width */ + ); +} + +static void set_di_if0_mif_g12(struct DI_MIF_s *mif, int urgent, int hold_line, + int vskip_cnt, int post_write_en) +{ + unsigned int pat, loop = 0; + unsigned int bytes_per_pixel, demux_mode; + + if (mif->set_separate_en == 1) { + pat = vpat[(vskip_cnt << 1) + 1]; + if (mif->src_field_mode == 0) {/* top */ + loop = 0x11; + pat <<= 4; + } + } else { + loop = 0; + pat = vpat[vskip_cnt]; + + bytes_per_pixel = + mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + demux_mode = mif->video_mode; + dim_VSYNC_WR_MPEG_REG(DI_IF0_GEN_REG, + (1 << 29) | /* reset on go field */ + (urgent << 28) | /* urgent */ + (urgent << 27) | /* luma urgent */ + (1 << 25) | /* no dummy data. */ + (hold_line << 19) | /* hold lines */ + (1 << 18) | /* push dummy pixel */ + (demux_mode << 16) | /* demux_mode */ + (bytes_per_pixel << 14) | + (1 << 12) | + (1 << 10) | + (3 << 8) | + (0 << 6) | + ((mif->set_separate_en != 0) << 1) | + (1 << 0) /* cntl_enable */ + ); + /* ---------------------- */ + /* Canvas */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF0_CANVAS0, + (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); + if (mif->set_separate_en == 2) { + /* Enable NV12 Display */ + dim_RDMA_WR_BITS(DI_IF0_GEN_REG2, 1, 0, 1); + } else { + dim_RDMA_WR_BITS(DI_IF0_GEN_REG2, 0, 0, 1); + } + + /* ---------------------- */ + /* Picture 0 X/Y start,end */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF0_LUMA_X0, + (mif->luma_x_end0 << 16) | + (mif->luma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF0_LUMA_Y0, + (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF0_CHROMA_X0, + (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF0_CHROMA_Y0, + (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); + } + /* ---------------------- */ + /* Repeat or skip */ + /* ---------------------- */ + dim_VSYNC_WR_MPEG_REG(DI_IF0_REPEAT_LOOP, + (loop << 24) | + (loop << 16) | + (loop << 8) | + (loop << 0)); + dim_VSYNC_WR_MPEG_REG(DI_IF0_LUMA0_RPT_PAT, pat); + dim_VSYNC_WR_MPEG_REG(DI_IF0_CHROMA0_RPT_PAT, pat); + + /* 4:2:0 block mode. */ + if (mif->set_separate_en != 0) { + set_di_if0_fmt_more_g12( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 1, /* vfmt_en */ + 1, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + /* y_length */ + mif->luma_x_end0 - mif->luma_x_start0 + 1, + /* c length */ + mif->chroma_x_end0 - mif->chroma_x_start0 + 1, + 0); /* hz repeat. */ + } else { + set_di_if0_fmt_more_g12( + 1, /* hfmt_en */ + 1, /* hz_yc_ratio */ + 0, /* hz_ini_phase */ + 0, /* vfmt_en */ + 0, /* vt_yc_ratio */ + 0, /* vt_ini_phase */ + /* y_length */ + mif->luma_x_end0 - + mif->luma_x_start0 + 1, + /* c length */ + ((mif->luma_x_end0 >> 1) - + (mif->luma_x_start0 >> 1) + 1), + 0); /* hz repeat */ + } +} + +static unsigned int di_mc_update; +void dimh_patch_post_update_mc(void) +{ + if (di_mc_update == DI_MC_SW_ON_MASK) + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_CTRL, 1, 9, 1); +} + +void dimh_patch_post_update_mc_sw(unsigned int cmd, bool on) +{ + unsigned int l_flg = di_mc_update; + + switch (cmd) { + case DI_MC_SW_IC: + if (is_meson_gxtvbb_cpu() || + is_meson_txl_cpu() || + is_meson_txlx_cpu() || + is_meson_txhd_cpu()) { + di_mc_update |= DI_MC_SW_IC; + } + break; + case DI_MC_SW_REG: + if (on) { + di_mc_update |= cmd; + di_mc_update &= ~DI_MC_SW_OTHER; + } else { + di_mc_update &= ~(cmd | DI_MC_SW_OTHER); + } + break; + case DI_MC_SW_OTHER: + +/* case DI_MC_SW_POST:*/ + if (on) + di_mc_update |= cmd; + else + di_mc_update &= ~cmd; + + break; + } + + if (l_flg != di_mc_update) + pr_debug("%s:0x%x->0x%x\n", __func__, l_flg, di_mc_update); +} + +void dimh_post_ctrl(enum DI_HW_POST_CTRL contr, unsigned int post_write_en) +{ + unsigned int reg_val; + + if (!post_write_en || !cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + return; + + switch (contr) { + case DI_HW_POST_CTRL_INIT: + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, + 0x80000000 | + dimp_get(eDI_MP_line_num_post_frst)); + break; + case DI_HW_POST_CTRL_RESET: /*replace post_frame_reset_g12a*/ + reg_val = (0xc3200000 | dimp_get(eDI_MP_line_num_post_frst)); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, reg_val); + reg_val = (0x83200000 | dimp_get(eDI_MP_line_num_post_frst)); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, reg_val); + + break; + } +} + +void dimh_initial_di_post_2(int hsize_post, int vsize_post, + int hold_line, bool post_write_en) +{ + di_post_set_flow(post_write_en, eDI_POST_FLOW_STEP1_STOP);/*dbg a*/ + dim_VSYNC_WR_MPEG_REG(DI_POST_SIZE, + (hsize_post - 1) | ((vsize_post - 1) << 16)); + + /* if post size < MIN_POST_WIDTH, force old ei */ + if (hsize_post < MIN_POST_WIDTH) + dim_VSYNC_WR_MPEG_REG_BITS(DI_EI_CTRL3, 0, 31, 1); + else + dim_VSYNC_WR_MPEG_REG_BITS(DI_EI_CTRL3, 1, 31, 1); + + /* DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post >> 2) - 1); */ + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_Y, + ((vsize_post >> 2) << 16) | + (2 * (vsize_post >> 2) - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_Y, + ((2 * (vsize_post >> 2)) << 16) | + (3 * (vsize_post >> 2) - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_Y, + ((3 * (vsize_post >> 2)) << 16) | + (vsize_post - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_X, (hsize_post - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_X, (hsize_post - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_X, (hsize_post - 1)); + dim_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_X, (hsize_post - 1)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (post_write_en) { + #if 0 + dim_print("%s:VD1_AFBCD0_MISC_CTRL\n", __func__); + #endif + /*di if0 mif to di post*/ + dim_VSYNC_WR_MPEG_REG_BITS(VIUB_MISC_CTRL0, 0, 4, 1); + /*di_mif0_en:select mif to di*/ + #if 0 + DI_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, + 1, 8, 1); + #endif + dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, + 0, 8, 1); + } else { + dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, + 1, 8, 1); + dim_VSYNC_WR_MPEG_REG_BITS(VIUB_MISC_CTRL0, 0, 4, 1); + } + + } else { + /* enable ma,disable if0 to vpp */ + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0x50000) { + dim_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 5, 16, 3); + if (post_write_en) + dim_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, + 1, 28, 1); + } + } + dim_VSYNC_WR_MPEG_REG(DI_POST_CTRL, + (0 << 0) | + (0 << 1) | + (0 << 2) | + (0 << 3) | + (0 << 4) | + (0 << 5) | + (0 << 6) | + ((post_write_en ? 1 : 0) << 7) | + ((post_write_en ? 0 : 1) << 8) | + (0 << 9) | + (0 << 10) | + (0 << 11) | + (0 << 12) | + (hold_line << 16) | + (0 << 29) | + (0x3 << 30) + ); +} + +static void post_bit_mode_config(unsigned char if0, + unsigned char if1, + unsigned char if2, + unsigned char post_wr) +{ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) + return; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dim_DI_Wr_reg_bits(DI_IF0_GEN_REG3, if0 & 0x3, 8, 2); + else + dim_DI_Wr_reg_bits(VD1_IF0_GEN_REG3, if0 & 0x3, 8, 2); + dim_DI_Wr_reg_bits(DI_IF1_GEN_REG3, if1 & 0x3, 8, 2); + dim_DI_Wr_reg_bits(DI_IF2_GEN_REG3, if2 & 0x3, 8, 2); + dim_DI_Wr_reg_bits(DI_DIWR_Y, post_wr & 0x1, 14, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL) && ((post_wr & 0x3) == 0x3)) + dim_DI_Wr_reg_bits(DI_DIWR_CTRL, 0x3, 22, 2); +} + +void dimh_post_switch_buffer( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + struct DI_MC_MIF_s *di_mcvecrd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, + int post_field_num, int hold_line, int urgent, + int invert_mv, bool pd_enable, bool mc_enable, + int vskip_cnt +) +{ + int ei_only, buf1_en; + + ei_only = ei_en && !blend_en && (di_vpp_en || di_ddr_en); + buf1_en = (!ei_only && (di_ddr_en || di_vpp_en)); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_VSYNC_WR_MPEG_REG(DI_IF0_CANVAS0, + (di_buf0_mif->canvas0_addr2 << 16) | + (di_buf0_mif->canvas0_addr1 << 8) | + (di_buf0_mif->canvas0_addr0 << 0)); + if (!di_ddr_en) { + dim_VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG, + 0, 0, 1); + } + if (mc_enable) { + dim_VSYNC_WR_MPEG_REG_BITS(MCVECRD_CTRL1, + di_mcvecrd_mif->canvas_num, + 16, 8); + } + /*motion for current display field.*/ + if (blend_mtn_en) { + dim_VSYNC_WR_MPEG_REG_BITS(MTNRD_CTRL1, + di_mtnprd_mif->canvas_num, + 16, 8); + /* current field mtn canvas index.*/ + } + } else { + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0x50000) + dim_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 5, 16, 3); + if (di_ddr_en) + dim_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 1, 28, 1); + if (ei_en || di_vpp_en || di_ddr_en) + set_di_if0_mif(di_buf0_mif, urgent, + hold_line, vskip_cnt, di_ddr_en); + if (mc_enable) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_CTRL, + /* canvas enable */ + (1 << 9) | + (urgent << 8) | + di_mcvecrd_mif->canvas_num, + 0, 10); + } + /*motion for current display field.*/ + if (blend_mtn_en) { + dim_VSYNC_WR_MPEG_REG(DI_MTNRD_CTRL, + (di_mtnprd_mif->canvas_num << 8) | + (urgent << 16)); + /*current field mtn canvas index.*/ + } + } + + if (!ei_only && (di_ddr_en || di_vpp_en)) { + dim_VSYNC_WR_MPEG_REG(DI_IF1_CANVAS0, + (di_buf1_mif->canvas0_addr2 << 16) | + (di_buf1_mif->canvas0_addr1 << 8) | + (di_buf1_mif->canvas0_addr0 << 0)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_VSYNC_WR_MPEG_REG(DI_IF2_CANVAS0, + (di_buf2_mif->canvas0_addr2 << 16) | + (di_buf2_mif->canvas0_addr1 << 8) | + (di_buf2_mif->canvas0_addr0 << 0)); + } + + if (di_ddr_en) { + dim_VSYNC_WR_MPEG_REG(DI_DIWR_CTRL, + di_diwr_mif->canvas_num | + (urgent << 16) | + (2 << 26) | + (di_ddr_en << 30)); + post_bit_mode_config(di_buf0_mif->bit_mode, + di_buf1_mif->bit_mode, + di_buf2_mif->bit_mode, + di_diwr_mif->bit_mode); + } + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, blend_en, 31, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, blend_mode, 20, 2); + if ((dimp_get(eDI_MP_pldn_ctrl_rflsh) == 1) && pd_enable) + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 7, 22, 3); + + if (mc_enable) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + invert_mv, + 17, 1);/* invert mv */ + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + di_mcvecrd_mif->vecrd_offset, 12, 3); + if (di_mcvecrd_mif->blend_en) { + if (blend_mode == 1) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcen_mode), 0, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 2, 18, 2); + } else { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_mcen_mode), 0, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 1, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 3, 18, 2); + } + } else { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 2, 18, 2); + } + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_VSYNC_WR_MPEG_REG_BITS(DI_POST_GL_THD, + hold_line, 16, 5); + hold_line = 0; + } + + if (!is_meson_txlx_cpu()) + invert_mv = 0; + if (dimp_get(eDI_MP_post_ctrl) != 0) + dim_VSYNC_WR_MPEG_REG(DI_POST_CTRL, + dimp_get(eDI_MP_post_ctrl) | + (0x3 << 30)); + else { + dim_VSYNC_WR_MPEG_REG(DI_POST_CTRL, + ((ei_en | blend_en) << 0) | /* line buf 0 enable */ + ((blend_mode == 1 ? 1 : 0) << 1) | + (ei_en << 2) | /* ei enable */ + (blend_mtn_en << 3) | /* mtn line buffer enable */ + (blend_mtn_en << 4) | /* mtnp read mif enable */ + (blend_en << 5) | + (1 << 6) | /* di mux output enable */ + (di_ddr_en << 7) | /* di wr to SDRAM enable.*/ + (di_vpp_en << 8) | /* di to VPP enable. */ + (0 << 9) | /* mif0 to VPP enable. */ + (0 << 10) | /* post drop first. */ + (0 << 11) | + (di_vpp_en << 12) | /* post viu link */ + (invert_mv << 14) | + (hold_line << 16) | /* post hold line number */ + (post_field_num << 29) | /* post field number. */ + (0x3 << 30) /* post soft rst post frame rst. */ + ); + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) && di_ddr_en) { +#if 0 + post_frame_reset_g12a(); +#endif + } else if (di_ddr_en && mc_enable) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_CTRL, 1, 9, 1); + } +} + +static void set_post_mtnrd_mif(struct DI_SIM_MIF_s *mtnprd_mif, + unsigned char urgent) +{ + dim_VSYNC_WR_MPEG_REG(DI_MTNPRD_X, + (mtnprd_mif->start_x << 16) | + (mtnprd_mif->end_x)); + dim_VSYNC_WR_MPEG_REG(DI_MTNPRD_Y, + (mtnprd_mif->start_y << 16) | + (mtnprd_mif->end_y)); + dim_VSYNC_WR_MPEG_REG(DI_MTNRD_CTRL, + (mtnprd_mif->canvas_num << 8) | + (urgent << 16) + ); +} + +static void set_post_mtnrd_mif_g12(struct DI_SIM_MIF_s *mtnprd_mif) +{ + dim_VSYNC_WR_MPEG_REG(MTNRD_SCOPE_X, + (mtnprd_mif->end_x << 16) | + (mtnprd_mif->start_x)); + dim_VSYNC_WR_MPEG_REG(MTNRD_SCOPE_Y, + (mtnprd_mif->end_y << 16) | + (mtnprd_mif->start_y)); + dim_VSYNC_WR_MPEG_REG_BITS(MTNRD_CTRL1, + mtnprd_mif->canvas_num, 16, 8); + dim_VSYNC_WR_MPEG_REG_BITS(MTNRD_CTRL1, 0, 0, 3); +} + +void dimh_enable_di_post_2( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, int post_field_num, + int hold_line, int urgent, int invert_mv, + int vskip_cnt +) +{ + int ei_only; + int buf1_en; + + ei_only = ei_en && !blend_en && (di_vpp_en || di_ddr_en); + buf1_en = (!ei_only && (di_ddr_en || di_vpp_en)); + + if (ei_en || di_vpp_en || di_ddr_en) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + set_di_if0_mif_g12(di_buf0_mif, di_vpp_en, + hold_line, vskip_cnt, di_ddr_en); + /* if di post vpp link disable vd1 for new if0 */ + if (!di_ddr_en) { + dim_VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG, + 0, 0, 1); + } + } else + set_di_if0_mif(di_buf0_mif, di_vpp_en, + hold_line, vskip_cnt, di_ddr_en); + } + + set_di_if1_mif(di_buf1_mif, di_vpp_en, hold_line, vskip_cnt); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + set_di_if2_mif(di_buf2_mif, + di_vpp_en, hold_line, vskip_cnt); + /* motion for current display field. */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + set_post_mtnrd_mif_g12(di_mtnprd_mif); + else + set_post_mtnrd_mif(di_mtnprd_mif, urgent); + if (di_ddr_en) { + dim_VSYNC_WR_MPEG_REG(DI_DIWR_X, + (di_diwr_mif->start_x << 16) | + (di_diwr_mif->end_x)); + dim_VSYNC_WR_MPEG_REG(DI_DIWR_Y, + (3 << 30) | + (di_diwr_mif->start_y << 16) | + /* wr ext en from gxtvbb */ + (1 << 15) | + (di_diwr_mif->end_y)); + dim_VSYNC_WR_MPEG_REG(DI_DIWR_CTRL, + di_diwr_mif->canvas_num | + (urgent << 16) | + (2 << 26) | + (di_ddr_en << 30)); + post_bit_mode_config(di_buf0_mif->bit_mode, + di_buf1_mif->bit_mode, + di_buf2_mif->bit_mode, + di_diwr_mif->bit_mode); + } + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 7, 22, 3); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + blend_en & 0x1, 31, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + blend_mode & 0x3, 20, 2); + if (!is_meson_txlx_cpu()) + invert_mv = 0; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_VSYNC_WR_MPEG_REG_BITS(DI_POST_GL_THD, + hold_line, 16, 5); + hold_line = 0; + } + dim_VSYNC_WR_MPEG_REG(DI_POST_CTRL, + ((ei_en | blend_en) << 0) | /* line buffer 0 enable */ + ((blend_mode == 1 ? 1 : 0) << 1) | + (ei_en << 2) | /* ei enable */ + (blend_mtn_en << 3) | /* mtn line buffer enable */ + (blend_mtn_en << 4) | /* mtnp read mif enable */ + (blend_en << 5) | + (1 << 6) | /* di mux output enable */ + /* di write to SDRAM enable. */ + (di_ddr_en << 7) | + (di_vpp_en << 8) | /* di to VPP enable. */ + (0 << 9) | /* mif0 to VPP enable. */ + (0 << 10) | /* post drop first. */ + (0 << 11) | + (di_vpp_en << 12) | /* post viu link */ + (invert_mv << 14) | /* invert mv */ + (hold_line << 16) | /* post hold line number */ + (post_field_num << 29) | /* post field number. */ + (0x3 << 30) /* post soft rst post frame rst. */ + ); +} + +void dimh_pst_trig_resize(void) +{ + dim_VSYNC_WR_MPEG_REG(DI_POST_SIZE, (32 - 1) | ((128 - 1) << 16)); +} + +void dimh_disable_post_deinterlace_2(void) +{ + dim_VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); + dim_VSYNC_WR_MPEG_REG(DI_POST_SIZE, (32 - 1) | ((128 - 1) << 16)); + dim_VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, 0x3 << 30); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_VSYNC_WR_MPEG_REG(DI_IF2_GEN_REG, 0x3 << 30); + /* disable ma,enable if0 to vpp,enable afbc to vpp */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0) + dim_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 0, 16, 4); + /* DI inp(current data) switch to memory */ + dim_VSYNC_WR_MPEG_REG_BITS(VIUB_MISC_CTRL0, 0, 16, 1); + } + /* dim_VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, + * Rd(DI_IF1_GEN_REG) & 0xfffffffe); + */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + /*dbg a dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, 0);*/ + di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP); + dim_print("%s:VD1_AFBCD0_MISC_CTRL 0", __func__); + dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, 0, 8, 2); + dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, 0, 20, 2); + } +} + +void dimh_enable_di_post_mif(enum gate_mode_e mode) +{ + unsigned char gate = 0; + + switch (mode) { + case GATE_OFF: + gate = 1; + break; + case GATE_ON: + gate = 2; + break; + case GATE_AUTO: + gate = 2; + break; + default: + gate = 0; + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + /* enable if0 external gate freerun hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 2, 2); + /* enable if1 external gate freerun hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 4, 2); + /* enable if1 external gate freerun hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 6, 2); + /* enable di wr external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 8, 2); + /* enable mtn rd external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 10, 2); + /* enable mv rd external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 12, 2); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + /* enable if1 external gate freerun hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + ((gate == 0) ? 2 : gate), 2, 2); + /* enable if2 external gate freerun hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + ((gate == 0) ? 2 : gate), 4, 2); + /* enable di wr external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 6, 2); + /* enable mtn rd external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 8, 2); + /* enable mv rd external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 10, 2); + } +} + +void dim_hw_disable(bool mc_enable) +{ + dimh_enable_di_pre_mif(false, mc_enable); + dim_DI_Wr(DI_POST_SIZE, (32 - 1) | ((128 - 1) << 16)); + dim_DI_Wr_reg_bits(DI_IF1_GEN_REG, 0, 0, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_DI_Wr_reg_bits(DI_IF2_GEN_REG, 0, 0, 1); + /* disable ma,enable if0 to vpp,enable afbc to vpp */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (Rd_reg_bits(VIU_MISC_CTRL0, 16, 4) != 0) + dim_DI_Wr_reg_bits(VIU_MISC_CTRL0, 0, 16, 4); + /* DI inp(current data) switch to memory */ + dim_DI_Wr_reg_bits(VIUB_MISC_CTRL0, 0, 16, 1); + } + dim_DI_Wr(DI_POST_CTRL, 0); +} + +/* + * old pulldown windows share below ctrl + * registers + * with new pulldown windows + */ +void dim_film_mode_win_config(unsigned int width, unsigned int height) +{ + unsigned int win0_start_x, win0_end_x, win0_start_y, win0_end_y; + unsigned int win1_start_x, win1_end_x, win1_start_y, win1_end_y; + unsigned int win2_start_x, win2_end_x, win2_start_y, win2_end_y; + unsigned int win3_start_x, win3_end_x, win3_start_y, win3_end_y; + unsigned int win4_start_x, win4_end_x, win4_start_y, win4_end_y; + + win0_start_x = 0; + win1_start_x = 0; + win2_start_x = 0; + win3_start_x = 0; + win4_start_x = 0; + win0_end_x = width - 1; + win1_end_x = width - 1; + win2_end_x = width - 1; + win3_end_x = width - 1; + win4_end_x = width - 1; + win0_start_y = 0; + win1_start_y = (height >> 3); /* 1/8 */ + win0_end_y = win1_start_y - 1; + win2_start_y = win1_start_y + (height >> 2); /* 1/4 */ + win1_end_y = win2_start_y - 1; + win3_start_y = win2_start_y + (height >> 2); /* 1/4 */ + win2_end_y = win3_start_y - 1; + win4_start_y = win3_start_y + (height >> 2); /* 1/4 */ + win3_end_y = win4_start_y - 1; + win4_end_y = win4_start_y + (height >> 3) - 1; /* 1/8 */ + + dim_RDMA_WR(DI_MC_REG0_X, (win0_start_x << 16) | win0_end_x); + dim_RDMA_WR(DI_MC_REG0_Y, (win0_start_y << 16) | win0_end_y); + dim_RDMA_WR(DI_MC_REG1_X, (win1_start_x << 16) | win1_end_x); + dim_RDMA_WR(DI_MC_REG1_Y, (win1_start_y << 16) | win1_end_y); + dim_RDMA_WR(DI_MC_REG2_X, (win2_start_x << 16) | win2_end_x); + dim_RDMA_WR(DI_MC_REG2_Y, (win2_start_y << 16) | win2_end_y); + dim_RDMA_WR(DI_MC_REG3_X, (win3_start_x << 16) | win3_end_x); + dim_RDMA_WR(DI_MC_REG3_Y, (win3_start_y << 16) | win3_end_y); + dim_RDMA_WR(DI_MC_REG4_X, (win4_start_x << 16) | win4_end_x); + dim_RDMA_WR(DI_MC_REG4_Y, (win4_start_y << 16) | win4_end_y); +} + +/* + * old pulldown detction module, global field diff/num & frame + * diff/numm and 5 window included + */ +void dim_read_pulldown_info(unsigned int *glb_frm_mot_num, + unsigned int *glb_fid_mot_num) +{ + /* + * addr will increase by 1 automatically + */ + dim_DI_Wr(DI_INFO_ADDR, 1); + *glb_frm_mot_num = (Rd(DI_INFO_DATA) & 0xffffff); + dim_DI_Wr(DI_INFO_ADDR, 4); + *glb_fid_mot_num = (Rd(DI_INFO_DATA) & 0xffffff); +} + +#if 0 /*move from deinterlace_hw.c to pulldown_drv.c*/ + +void read_new_pulldown_info(struct FlmModReg_t *pFMReg) +{ + int i = 0; + + for (i = 0; i < 6; i++) { + pFMReg->rROFrmDif02[i] = Rd(DIPD_RO_COMB_0 + i); + pFMReg->rROFldDif01[i] = Rd(DIPD_RO_COMB_6 + i); + } + + /* pFMReg->rROFrmDif02[0] = Rd(DIPD_RO_COMB_0); */ + /* pFMReg->rROFldDif01[0] = Rd(DIPD_RO_COMB_6); */ + + for (i = 0; i < 9; i++) + pFMReg->rROCmbInf[i] = Rd(DIPD_RO_COMB_12 + i); +} + +#endif +/* + * DIPD_RO_COMB_0~DIPD_RO_COMB11 and DI_INFO_DATA + * will be reset, so call this function after all + * data have be fetched + */ +void dim_pulldown_info_clear_g12a(void) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) + dim_RDMA_WR_BITS(DI_PRE_CTRL, 1, 30, 1); +} + +/* + * manual reset contrd, cont2rd, mcinford mif + * which fix after g12a + */ +static void reset_pre_simple_rd_mif_g12(unsigned char madi_en, + unsigned char mcdi_en) +{ + unsigned int reg_val = 0; + + if (madi_en || mcdi_en) { + dim_RDMA_WR_BITS(CONTRD_CTRL2, 1, 31, 1); + dim_RDMA_WR_BITS(CONT2RD_CTRL2, 1, 31, 1); + dim_RDMA_WR_BITS(MCINFRD_CTRL2, 1, 31, 1); + reg_val = dim_RDMA_RD(DI_PRE_CTRL); + if (madi_en) + reg_val |= (1 << 25); + if (mcdi_en) + reg_val |= (1 << 10); + /* enable cont rd&mcinfo rd, manual start */ + dim_RDMA_WR(DI_PRE_CTRL, reg_val); + dim_RDMA_WR_BITS(CONTRD_CTRL2, 0, 31, 1); + dim_RDMA_WR_BITS(CONT2RD_CTRL2, 0, 31, 1); + dim_RDMA_WR_BITS(MCINFRD_CTRL2, 0, 31, 1); + } +} + +/* + * frame reset for pre which have nothing with encoder + * go field + */ +void dim_pre_frame_reset_g12(unsigned char madi_en, + unsigned char mcdi_en) +{ + unsigned int reg_val = 0; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12B)) { + reset_pre_simple_rd_mif_g12(madi_en, mcdi_en); + } else { + reg_val = dim_RDMA_RD(DI_PRE_CTRL); + if (madi_en) + reg_val |= (1 << 25); + if (mcdi_en) + reg_val |= (1 << 10); + dim_RDMA_WR(DI_PRE_CTRL, reg_val); + } + /* reset simple mif which framereset not cover */ + dim_RDMA_WR_BITS(CONTWR_CAN_SIZE, 1, 14, 1); + dim_RDMA_WR_BITS(MTNWR_CAN_SIZE, 1, 14, 1); + dim_RDMA_WR_BITS(MCVECWR_CAN_SIZE, 1, 14, 1); + dim_RDMA_WR_BITS(MCINFWR_CAN_SIZE, 1, 14, 1); + + dim_RDMA_WR_BITS(CONTWR_CAN_SIZE, 0, 14, 1); + dim_RDMA_WR_BITS(MTNWR_CAN_SIZE, 0, 14, 1); + dim_RDMA_WR_BITS(MCVECWR_CAN_SIZE, 0, 14, 1); + dim_RDMA_WR_BITS(MCINFWR_CAN_SIZE, 0, 14, 1); + + reg_val = 0xc3200000 | dimp_get(eDI_MP_line_num_pre_frst); + dim_RDMA_WR(DI_PRE_GL_CTRL, reg_val); + reg_val = 0x83200000 | dimp_get(eDI_MP_line_num_pre_frst); + dim_RDMA_WR(DI_PRE_GL_CTRL, reg_val); +} + +/* + * frame + soft reset for the pre modules + */ +void dim_pre_frame_reset(void) +{ + dim_RDMA_WR_BITS(DI_PRE_CTRL, 3, 30, 2); +} + +/* + * frame reset for post which have nothing with encoder + * go field + */ +void post_frame_reset_g12a(void) +{ + unsigned int reg_val = 0; + + reg_val = (0xc0200000 | dimp_get(eDI_MP_line_num_post_frst)); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, reg_val); + reg_val = (0x80200000 | dimp_get(eDI_MP_line_num_post_frst)); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, reg_val); +} + +void dim_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, + bool mc_enable) +{ + unsigned short flag_val = 1; + + mc_pre_flag = dimp_get(eDI_MP_if2_disable) ? 1 : mc_pre_flag; + if (reverse) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF0_GEN_REG2, 3, 2, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MTNRD_CTRL1, 3, 4, 2); + } else { + dim_VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2, 0xf, 2, 4); + dim_VSYNC_WR_MPEG_REG_BITS(DI_MTNRD_CTRL, 0xf, 17, 4); + } + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG2, 3, 2, 2); + dim_VSYNC_WR_MPEG_REG_BITS(VD2_IF0_GEN_REG2, 0xf, 2, 4); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG2, 3, 2, 2); + if (mc_enable) { + /* motion vector read reverse*/ + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 1, 30, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 1, 30, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + if (is_meson_txlx_cpu()) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_pre_flag), 8, 2); + flag_val = + (dimp_get(eDI_MP_pre_flag) != 2) ? + 0 : 1; + } else { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 2); + flag_val = (mc_pre_flag != 2) ? 0 : 1; + } + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, flag_val, 11, 1); + /* disable if2 for wave if1 case, + *disable mc for pq issue + */ + if (dimp_get(eDI_MP_if2_disable)) { + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS( + DI_IF2_GEN_REG, 0, 0, 1); + if (cpu_after_eq( + MESON_CPU_MAJOR_ID_GXLX)) + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 18, 1); + } + } else + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 1); + } + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF0_GEN_REG2, 0, 2, 2); + dim_VSYNC_WR_MPEG_REG_BITS(MTNRD_CTRL1, 0, 4, 2); + } else { + dim_VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2, 0, 2, 4); + dim_VSYNC_WR_MPEG_REG_BITS(DI_MTNRD_CTRL, 0, 17, 4); + } + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG2, 0, 2, 2); + dim_VSYNC_WR_MPEG_REG_BITS(VD2_IF0_GEN_REG2, 0, 2, 4); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + dim_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG2, 0, 2, 2); + if (mc_enable) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 0, 30, 1); + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 0, 30, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + if (is_meson_txlx_cpu()) { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + dimp_get(eDI_MP_pre_flag), + 8, 2); + flag_val = + (dimp_get(eDI_MP_pre_flag) != 2) ? + 0 : 1; + } else { + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 2); + flag_val = (mc_pre_flag != 2) ? 0 : 1; + } + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, flag_val, 11, 1); + /* disable if2 for wave if1 case */ + if (dimp_get(eDI_MP_if2_disable)) { + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 11, 1); + dim_VSYNC_WR_MPEG_REG_BITS( + DI_IF2_GEN_REG, 0, 0, 1); + if (cpu_after_eq( + MESON_CPU_MAJOR_ID_GXLX)) + dim_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 18, 1); + } + } else + dim_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 1); + } + } +} + +void dim_set_power_control(unsigned char enable) +{ + ext_ops.switch_vpu_mem_pd_vmod(VPU_VIU_VD1, + enable ? true : false); + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + enable ? true : false); +} + +void dim_top_gate_control(bool top_en, bool mc_en) +{ + if (top_en) { + /* enable clkb input */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 0, 1); + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 15, 1); + /* enable slow clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, mc_en ? 1 : 0, 10, 1); + /* enable di arb */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 0, 2); + } else { + /* disable clkb input */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 0, 1); + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 15, 1); + /* disable slow clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 10, 1); + /* disable di arb */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 0, 2); + } +} + +void dim_pre_gate_control(bool gate, bool mc_enable) +{ + if (gate) { + /* enable ma pre clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 8, 1); + /* enable mc clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 11, 1); + /* enable pd clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 2, 2, 2); + /* enable motion clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 2, 4, 2); + /* enable deband clk gate freerun for hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 2, 6, 2); + /* enable input mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 16, 2); + /* enable mem mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 18, 2); + /* enable chan2 mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 20, 2); + /* enable nr wr mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 22, 2); + /* enable mtn wr mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 2, 24, 2); + if (mc_enable) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 12, 2); + else + /* enable me clk always run vlsi issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 3, 12, 2); + /* + * enable mc pre mv(wr) mcinfo w/r + * mif external gate + */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + 2, 26, 2); + } + /* cowork with auto gate to config reg */ + dim_DI_Wr_reg_bits(DI_PRE_CTRL, 3, 2, 2); + } else { + /* disable ma pre clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 8, 1); + /* disable mc clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 11, 1); + /* disable pd clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 2, 2); + /* disable motion clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 4, 2); + /* disable deband clk gate freerun for hw issue */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 6, 2); + /* disable input mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 16, 2); + /* disable mem mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 18, 2); + /* disable chan2 mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 20, 2); + /* disable nr wr mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 22, 2); + /* disable mtn wr mif external gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 24, 2); + if (mc_enable) { + /* disable mc pre mv(wr) mcinfo + * w/r mif external gate + */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + 1, 26, 2); + /* disable me clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 12, 2); + } + } +} + +void dim_post_gate_control(bool gate) +{ + if (gate) { + /* enable clk post div */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 12, 1); + /* enable post line buf/fifo/mux clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 9, 1); + /* enable blend1 clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 0, 2); + /* enable ei clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 2, 2); + /* enable ei_0 clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 4, 2); + } else { + /* disable clk post div */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 12, 1); + /* disable post line buf/fifo/mux clk */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 9, 1); + /* disable blend1 clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 0, 2); + /* disable ei clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 2, 2); + /* disable ei_0 clk gate */ + dim_DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 4, 2); + } +} + +static void di_async_reset(void)/*2019-01-17 add for debug*/ +{ + /*wrmif async reset*/ + dim_RDMA_WR_BITS(VIUB_SW_RESET, 1, 14, 1); + dim_RDMA_WR_BITS(VIUB_SW_RESET, 0, 14, 1); +} + +static void di_pre_rst_frame(void) +{ + dim_RDMA_WR(DI_PRE_CTRL, Rd(DI_PRE_CTRL) | (1 << 31)); +} + +static void di_pre_nr_enable(bool on) +{ + if (on) + dim_RDMA_WR_BITS(DI_PRE_CTRL, 1, 0, 1); + else + dim_RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); +} + +void dim_pre_nr_wr_done_sel(bool on) +{ + if (on) /*wait till response finish*/ + dim_RDMA_WR_BITS(DI_CANVAS_URGENT0, 1, 8, 1); + else + dim_RDMA_WR_BITS(DI_CANVAS_URGENT0, 0, 0, 1); +} + +void dim_rst_protect(bool on) +{ + if (on) + dim_RDMA_WR_BITS(DI_NRWR_Y, 1, 15, 1); + else + dim_RDMA_WR_BITS(DI_NRWR_Y, 0, 15, 1); +} + +/*bit 10,12,16,18 [3:1]*/ +/*#define PRE_ID_MASK (0x5140e) */ +#define PRE_ID_MASK (0x51400) + +/*bit 8,10,14,16*/ +#define PRE_ID_MASK_TL1 (0x14500) + +static bool di_pre_idle(void) +{ + bool ret = false; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if ((dim_RDMA_RD(DI_ARB_DBG_STAT_L1C1) & + PRE_ID_MASK_TL1) == PRE_ID_MASK_TL1) + ret = true; + } else { + if ((dim_RDMA_RD(DI_ARB_DBG_STAT_L1C1_OLD) & + PRE_ID_MASK) == PRE_ID_MASK) + ret = true; + } + + return ret; +} + +void dim_arb_sw(bool on) +{ + int i; + u32 REG_VPU_WRARB_REQEN_SLV_L1C1; + u32 REG_VPU_RDARB_REQEN_SLV_L1C1; + u32 REG_VPU_ARB_DBG_STAT_L1C1; + u32 WRARB_onval; + u32 WRARB_offval; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x3e; + } else { + REG_VPU_WRARB_REQEN_SLV_L1C1 = DI_WRARB_REQEN_SLV_L1C1_OLD; + REG_VPU_RDARB_REQEN_SLV_L1C1 = DI_RDARB_REQEN_SLV_L1C1_OLD; + REG_VPU_ARB_DBG_STAT_L1C1 = DI_ARB_DBG_STAT_L1C1_OLD; + if (on) + WRARB_onval = 0x3f; + else + WRARB_offval = 0x2b; + } + + if (on) { + dim_RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_onval); + dim_RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xffff); + } else { + /*close arb:*/ + dim_RDMA_WR(REG_VPU_WRARB_REQEN_SLV_L1C1, WRARB_offval); + dim_RDMA_WR(REG_VPU_RDARB_REQEN_SLV_L1C1, 0xf1f1); + + di_pre_nr_enable(false); /*by Feijun*/ + /*check status*/ + if (!di_pre_idle()) { + PR_ERR("%s:1:0x[%x]\n", __func__, + dim_RDMA_RD(REG_VPU_ARB_DBG_STAT_L1C1)); + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + + if (!di_pre_idle()) { + di_pre_rst_frame(); + + for (i = 0; i < 9; i++) { + if (di_pre_idle()) + break; + } + if (!di_pre_idle()) + PR_ERR("%s:2\n", __func__); + } + } + if (di_pre_idle()) + di_async_reset(); + } +} + +/* keep 0x1700' bit8 bit9 bit11 bit28 : 1*/ + +void dbg_set_DI_PRE_CTRL(void) +{ + unsigned int val; + unsigned int mask, tmp; + + mask = 0x10000b00; + + val = Rd(DI_PRE_CTRL); + tmp = (~mask) & val; + tmp = tmp | 0x10000000; + + dim_DI_Wr(DI_PRE_CTRL, tmp); +} + +/************************************* + *VIUB_SW_RESET's bits: + * [1][2] + * [10][11] + * [12][13][14] + * [16][17] + * [27] + * [28][31] + * all bits set 1 and then set 0 + *************************************/ +void di_async_reset2(void)/*2019-04-05 add for debug*/ +{ + unsigned int mask, val1, val2, val3; + + mask = 0x98037c06; + val1 = Rd(VIUB_SW_RESET); + val2 = val1 | mask; + + dim_DI_Wr(VIUB_SW_RESET, val2); + val3 = val2 & (~mask); + dim_DI_Wr(VIUB_SW_RESET, val3); + pr_info("%s:0x%x,0x%x,0x%x\n", __func__, val1, val2, val3); +} + +#define DI_NOP_REG1 (0x2fcb) +#define DI_NOP_REG2 (0x2fcd) + +void h_dbg_reg_set(unsigned int val) +{ + struct di_hpst_s *pst = get_hw_pst(); + enum eDI_PST_ST pst_st = pst->state; + unsigned int valb; + + dim_DI_Wr(DI_NOP_REG1, val); + + valb = pst_st; + if (pst->curr_ch) + valb = pst_st | 0x80000000; + + dim_DI_Wr(DI_NOP_REG2, valb); +} + +/*below for post */ +void post_mif_sw(bool on) +{ + if (on) { + dim_RDMA_WR_BITS(DI_IF0_GEN_REG, 1, 0, 1); + /*by feijun 2018-11-19*/ + dim_RDMA_WR_BITS(DI_IF1_GEN_REG, 1, 0, 1); + /*by feijun 2018-11-19*/ + dim_RDMA_WR_BITS(DI_IF2_GEN_REG, 1, 0, 1); + + dim_RDMA_WR_BITS(DI_POST_CTRL, 1, 7, 1); + } else { + dim_RDMA_WR_BITS(DI_IF0_GEN_REG, 0, 0, 1); + /*by feijun 2018-11-19*/ + dim_RDMA_WR_BITS(DI_IF1_GEN_REG, 0, 0, 1); + /*by feijun 2018-11-19*/ + dim_RDMA_WR_BITS(DI_IF2_GEN_REG, 0, 0, 1); + dim_RDMA_WR_BITS(DI_POST_CTRL, 0, 7, 1); + } + dim_print("%s:%d\n", __func__, on); +} + +void post_close_new(void) +{ + unsigned int data32; + + post_mif_sw(false); + data32 = Rd(DI_INTR_CTRL); + /*intr_mode*/ + dim_DI_Wr(DI_INTR_CTRL, (data32 & 0xffff0004) | (3 << 30)); + di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP); /*dbg a*/ +} + +/*asynchronous rest ,2018-11-19 from feijun: after set reset ,*/ +/*mif setting must set again*/ +void di_post_reset(void) +{ +#if 0 + 0x2001 = 0x48300; + 0x2001 = 0x0; + 0x2002 = 0x30c1; + 0x2002 = 0x0; + + 0x2001 = 0x483c0; + 0x2001 = 0x0; + 0x2002 = 0x3001; + 0x2002 = 0x0; +#endif + Wr(VIUB_SW_RESET, 0x483c0); + Wr(VIUB_SW_RESET, 0x0); + + Wr(VIUB_SW_RESET0, 0x3001); + Wr(VIUB_SW_RESET0, 0x0); + pr_info("%s\n", __func__); +} + +void post_dbg_contr(void) +{ + dim_RDMA_WR_BITS(DI_IF0_GEN_REG3, 1, 11, 1); + dim_RDMA_WR_BITS(DI_IF1_GEN_REG3, 1, 11, 1); + dim_RDMA_WR_BITS(DI_IF2_GEN_REG3, 1, 11, 1); +} + +void di_post_set_flow(unsigned int post_wr_en, enum eDI_POST_FLOW step) +{ + unsigned int val; + + if (!post_wr_en) + return; + + switch (step) { + case eDI_POST_FLOW_STEP1_STOP: + /*val = (0xc0200000 | line_num_post_frst);*/ + val = (0xc0000000 | 1); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, val); + break; + case eDI_POST_FLOW_STEP2_START: + /*val = (0x80200000 | line_num_post_frst);*/ + val = (0x80200000 | 1); + dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, val); + break; + } +} + +/*add 2019-04-25 for post crash debug*/ +void hpst_power_ctr(bool on) +{ + if (on) { + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + true); + dim_post_gate_control(true); + dimh_enable_di_post_mif(GATE_AUTO); + } else { + dimh_enable_di_post_mif(GATE_OFF); + dim_post_gate_control(false); + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + false); + } + pr_info("%s:%d\n", __func__, on); +} + +void hpst_dbg_power_ctr_trig(unsigned int cmd) +{ + if (cmd) + hpst_power_ctr(true); + else + hpst_power_ctr(false); +} + +void hpst_dbg_mem_pd_trig(unsigned int cmd) +{ + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + false); + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + true); +/* pr_info("%s\n", __func__);*/ +} + +void hpst_mem_pd_sw(unsigned int on) +{ + if (on) + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + true); + else + ext_ops.switch_vpu_mem_pd_vmod(VPU_DI_POST, + false); +} + +void hpst_vd1_sw(unsigned int on) +{ + if (on) + ext_ops.switch_vpu_mem_pd_vmod(VPU_VIU_VD1, + true); + else + ext_ops.switch_vpu_mem_pd_vmod(VPU_VIU_VD1, + false); +} + +void hpst_dbg_trig_gate(unsigned int cmd) +{ + dim_post_gate_control(false); + dim_post_gate_control(true); + pr_info("%s\n", __func__); +} + +void hpst_dbg_trig_mif(unsigned int cmd) +{ + dimh_enable_di_post_mif(GATE_OFF); + dimh_enable_di_post_mif(GATE_AUTO); + pr_info("%s\n", __func__); +} + +/**/ +/* + * enable/disable mc pre mif mcinfo&mv + */ +static void mc_pre_mif_ctrl_g12(bool enable) +{ + unsigned char mif_ctrl = 0; + + mif_ctrl = enable ? 1 : 0; + /* enable mcinfo rd mif */ + dim_RDMA_WR_BITS(DI_PRE_CTRL, mif_ctrl, 10, 1); + /* enable mv wr mif */ + dim_RDMA_WR_BITS(MCVECWR_CTRL, mif_ctrl, 12, 1); + /* enable mcinfo wr mif */ + dim_RDMA_WR_BITS(MCINFWR_CTRL, mif_ctrl, 12, 1); +} + +static void mc_pre_mif_ctrl(bool enable) +{ + if (enable) { + /* gate clk */ + dim_RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 0, 9, 1); + /* gate clk */ + dim_RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 0, 9, 1); + /* mcinfo rd req en =1 */ + dim_RDMA_WR_BITS(MCDI_MCINFORD_CTRL, 1, 9, 1); + /* mv wr req en =1 */ + dim_RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 1, 12, 1); + /* mcinfo wr req en =1 */ + dim_RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 1, 12, 1); + } else { + /* no gate clk */ + dim_RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 1, 9, 1); + /* no gate clk */ + dim_RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 1, 9, 1); + /* mcvec wr req en =0 */ + dim_RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 0, 12, 1); + /* mcinfo wr req en =0 */ + dim_RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 0, 12, 1); + /* mcinfo rd req en = 0 */ + dim_RDMA_WR_BITS(MCDI_MCINFORD_CTRL, 0, 9, 1); + } +} + +/* + * enable/disable madi pre mif, mtn&cont + */ +static void ma_pre_mif_ctrl_g12(bool enable) +{ + if (enable) { + /* enable cont wr mif */ + dim_RDMA_WR_BITS(CONTWR_CTRL, 1, 12, 1); + /* enable mtn wr mif */ + dim_RDMA_WR_BITS(MTNWR_CTRL, 1, 12, 1); + /* enable cont rd mif */ + } else { + dim_RDMA_WR_BITS(MTNWR_CTRL, 0, 12, 1); + dim_RDMA_WR_BITS(CONTWR_CTRL, 0, 12, 1); + /* disable cont rd */ + dim_RDMA_WR_BITS(DI_PRE_CTRL, 0, 25, 1); + } +} + +/* + * use logic enable/disable replace mif + */ +static void ma_pre_mif_ctrl(bool enable) +{ + if (!enable) { + /* mtn wr req en =0 */ + dim_RDMA_WR_BITS(DI_PRE_CTRL, 0, 1, 1); + /* cont wr req en =0 */ + dim_RDMA_WR_BITS(DI_MTN_1_CTRL1, 0, 31, 1); + /* disable cont rd */ + dim_RDMA_WR_BITS(DI_PRE_CTRL, 0, 25, 1); + } +} + +/* + * enable/disable inp&chan2&mem&nrwr mif + */ +static void di_pre_data_mif_ctrl(bool enable) +{ + if (enable) { + /* enable input mif*/ + dim_DI_Wr(DI_CHAN2_GEN_REG, Rd(DI_CHAN2_GEN_REG) | 0x1); + dim_DI_Wr(DI_MEM_GEN_REG, Rd(DI_MEM_GEN_REG) | 0x1); + #if 0 + if (Rd_reg_bits(VIU_MISC_CTRL1, 0, 1) == 1) { + DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) & ~0x1); + dim_RDMA_WR_BITS(VD2_AFBC_ENABLE, 1, 8, 1); + } else { + DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) | 0x1); + dim_RDMA_WR_BITS(VD2_AFBC_ENABLE, 0, 8, 1); + } + #else + if (afbc_is_used()) { + dim_DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) & ~0x1); + afbc_input_sw(true); + } else { + dim_DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) | 0x1); + afbc_input_sw(false); + } + #endif + /* nrwr no clk gate en=0 */ + /*dim_RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1);*/ + } else { + /* nrwr no clk gate en=1 */ + /*dim_RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1);*/ + /* nr wr req en =0 */ + dim_RDMA_WR_BITS(DI_PRE_CTRL, 0, 0, 1); + /* disable input mif*/ + dim_DI_Wr(DI_CHAN2_GEN_REG, Rd(DI_CHAN2_GEN_REG) & ~0x1); + dim_DI_Wr(DI_MEM_GEN_REG, Rd(DI_MEM_GEN_REG) & ~0x1); + dim_DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) & ~0x1); + #if 0 + /* disable AFBC input */ + if (Rd_reg_bits(VIU_MISC_CTRL1, 0, 1) == 1) + dim_RDMA_WR_BITS(VD2_AFBC_ENABLE, 0, 8, 1); + #else + /* disable AFBC input */ + if (afbc_is_used()) + afbc_input_sw(false); + + #endif + } +} + +static atomic_t mif_flag; +void dimh_enable_di_pre_mif(bool en, bool mc_enable) +{ + if (atomic_read(&mif_flag)) + return; + + if (dimp_get(eDI_MP_pre_mif_gate) && !en) + return; + atomic_set(&mif_flag, 1); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { + if (mc_enable) + mc_pre_mif_ctrl_g12(en); + ma_pre_mif_ctrl_g12(en); + } else { + if (mc_enable) + mc_pre_mif_ctrl(en); + ma_pre_mif_ctrl(en); + } + di_pre_data_mif_ctrl(en); + atomic_set(&mif_flag, 0); +} + +void dimh_combing_pd22_window_config(unsigned int width, unsigned int height) +{ + unsigned short y1 = 39, y2 = height - 41; + + if (height >= 540) { + y1 = 79; + y2 = height - 81; + } + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + dim_DI_Wr_reg_bits(DECOMB_WIND00, 0, 16, 13);/* dcomb x0 */ + /* dcomb x1 */ + dim_DI_Wr_reg_bits(DECOMB_WIND00, (width - 1), 0, 13); + dim_DI_Wr_reg_bits(DECOMB_WIND01, 0, 16, 13);/* dcomb y0 */ + dim_DI_Wr_reg_bits(DECOMB_WIND01, y1, 0, 13);/* dcomb y1 */ + dim_DI_Wr_reg_bits(DECOMB_WIND10, 0, 16, 13);/* dcomb x0 */ + /* dcomb x1 */ + dim_DI_Wr_reg_bits(DECOMB_WIND10, (width - 1), 0, 13); + /* dcomb y0 */ + dim_DI_Wr_reg_bits(DECOMB_WIND11, (y1 + 1), 16, 13); + dim_DI_Wr_reg_bits(DECOMB_WIND11, y2, 0, 13);/* dcomb y1 */ + } + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_X, 0, 0, 13);/* pd22 x0 */ + /* pd22 x1 */ + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_X, (width - 1), 16, 13); + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_Y, 0, 0, 13);/* pd22 y0 */ + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_Y, y1, 16, 13);/* pd y1 */ + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_X, 0, 0, 13);/* pd x0 */ + /* pd x1 */ + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_X, (width - 1), 16, 13); + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_Y, (y1 + 1), 0, 13);/* pd y0 */ + dim_DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_Y, y2, 16, 13);/* pd y2 */ +} + +void dimh_pulldown_vof_win_config(struct pulldown_detected_s *wins) +{ + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, + wins->regs[0].win_vs, 17, 12); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, + wins->regs[0].win_ve, 1, 12); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, + wins->regs[1].win_vs, 17, 12); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, + wins->regs[1].win_ve, 1, 12); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, + wins->regs[2].win_vs, 17, 12); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, + wins->regs[2].win_ve, 1, 12); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, + wins->regs[3].win_vs, 17, 12); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, + wins->regs[3].win_ve, 1, 12); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[0].win_ve > wins->regs[0].win_vs) + ? 1 : 0, 16, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[0].blend_mode, 8, 2); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[1].win_ve > wins->regs[1].win_vs) + ? 1 : 0, 17, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[1].blend_mode, 10, 2); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[2].win_ve > wins->regs[2].win_vs) + ? 1 : 0, 18, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[2].blend_mode, 12, 2); + + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[3].win_ve > wins->regs[3].win_vs) + ? 1 : 0, 19, 1); + dim_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[3].blend_mode, 14, 2); +} + +void dimh_load_regs(struct di_pq_parm_s *di_pq_ptr) +{ + unsigned int i = 0, j = 0, addr = 0, value = 0, mask = 0, len; + unsigned int table_name = 0, nr_table = 0; + bool ctrl_reg_flag = false; + struct am_reg_s *regs_p = NULL; + + if (dimp_get(eDI_MP_pq_load_dbg) == 1) + return; + if (dimp_get(eDI_MP_pq_load_dbg) == 2) + pr_info("[DI]%s hw load 0x%x pq table len %u.\n", + __func__, di_pq_ptr->pq_parm.table_name, + di_pq_ptr->pq_parm.table_len); + if (PTR_RET(di_pq_ptr->regs)) { + PR_ERR("[DI] table ptr error.\n"); + return; + } + pr_info("[DI]%s hw load 0x%x pq table len %u.\n", + __func__, di_pq_ptr->pq_parm.table_name, + di_pq_ptr->pq_parm.table_len); + nr_table = TABLE_NAME_NR | TABLE_NAME_DEBLOCK | TABLE_NAME_DEMOSQUITO; + regs_p = (struct am_reg_s *)di_pq_ptr->regs; + len = di_pq_ptr->pq_parm.table_len; + table_name = di_pq_ptr->pq_parm.table_name; + for (i = 0; i < len; i++) { + ctrl_reg_flag = false; + addr = regs_p->addr; + value = regs_p->val; + mask = regs_p->mask; + if (dimp_get(eDI_MP_pq_load_dbg) == 2) + pr_info("[%u][0x%x] = [0x%x]&[0x%x]\n", + i, addr, value, mask); + + for (j = 0; j < SKIP_CTRE_NUM; j++) { + if (addr == ctrl_regs[j]) + break; + } + + if (regs_p->mask != 0xffffffff) { + value = ((Rd(addr) & (~(mask))) | + (value & mask)); + } + regs_p++; + if (j < SKIP_CTRE_NUM) { + if (dimp_get(eDI_MP_pq_load_dbg) == 3) + pr_info("%s skip [0x%x]=[0x%x].\n", + __func__, addr, value); + continue; + } + if (table_name & nr_table) + ctrl_reg_flag + = get_ops_nr()->set_nr_ctrl_reg_table(addr, value); + + if (!ctrl_reg_flag) + dim_DI_Wr(addr, value); + if (dimp_get(eDI_MP_pq_load_dbg) == 2) + pr_info("[%u][0x%x] = [0x%x] %s\n", i, addr, + value, Rd(addr) != value ? "fail" : "success"); + } +} + +/*note:*/ +/* function: patch for txl for progressive source */ +/* 480p/576p/720p from hdmi will timeout */ +/* prog_flg: in: 1:progressive; */ +/* cnt: in: di_pre_stru.field_count_for_cont*/ +/* mc_en: in: mcpre_en*/ +void dimh_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en) +{ + unsigned int di_mtn_1_ctrl1 = 0; /*ary add tmp*/ + + if (!prog_flg || !is_meson_txl_cpu()) + return; + + /*printk("prog patch\n");*/ + if (cnt >= 3) { + di_mtn_1_ctrl1 |= 1 << 29;/* enable txt */ + + if (mc_en) { + dim_RDMA_WR(DI_MTN_CTRL1, + (0xffffcfff & dim_RDMA_RD(DI_MTN_CTRL1))); + + /* enable me(mc di) */ + if (cnt == 4) { + di_mtn_1_ctrl1 &= (~(1 << 30)); + /* enable contp2rd and contprd */ + dim_RDMA_WR(MCDI_MOTINEN, 1 << 1 | 1); + } + if (cnt == 5) + dim_RDMA_WR(MCDI_CTRL_MODE, 0x1bfff7ff); + } + } else { + if (mc_en) { + /* txtdet_en mode */ + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 1, 1); + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 9, 1); + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 16, 1); + dim_RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 28, 1); + dim_RDMA_WR(MCDI_MOTINEN, 0); + dim_RDMA_WR(DI_MTN_CTRL1, + (0xffffcfff & dim_RDMA_RD(DI_MTN_CTRL1))); + /* disable me(mc di) */ + } + dim_RDMA_WR(DNR_CTRL, 0); + } + dim_RDMA_WR(DI_MTN_1_CTRL1, di_mtn_1_ctrl1); +} + +void dim_init_setting_once(void) +{ + if (di_get_flg_hw_int()) + return; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + dim_wr_cue_int(); + + di_set_flg_hw_int(true); +} + +int dim_seq_file_module_para_hw(struct seq_file *seq) +{ + seq_puts(seq, "hw---------------\n"); +#if 0 + seq_printf(seq, "%-15s:%d\n", "pq_load_dbg", pq_load_dbg); + seq_printf(seq, "%-15s:%d\n", "lmv_lock_win_en", lmv_lock_win_en); + seq_printf(seq, "%-15s:%d\n", "lmv_dist", lmv_dist); + seq_printf(seq, "%-15s:%d\n", "pr_mcinfo_cnt", pr_mcinfo_cnt); + seq_printf(seq, "%-15s:%d\n", "offset_lmv", offset_lmv); + seq_printf(seq, "%-15s:%d\n", "post_ctrl", post_ctrl); + seq_printf(seq, "%-15s:%d\n", "if2_disable", if2_disable); + seq_printf(seq, "%-15s:%d\n", "pre_flag", pre_flag); + + seq_printf(seq, "%-15s:%d\n", "pre_mif_gate", pre_mif_gate); + seq_printf(seq, "%-15s:%d\n", "pre_urgent", pre_urgent); + seq_printf(seq, "%-15s:%d\n", "pre_hold_line", pre_hold_line); + seq_printf(seq, "%-15s:%d\n", "pre_ctrl, uint", pre_ctrl); + seq_printf(seq, "%-15s:%d\n", "line_num_post_frst", + line_num_post_frst); + seq_printf(seq, "%-15s:%d\n", "line_num_pre_frst", line_num_pre_frst); + seq_printf(seq, "%-15s:%d\n", "pd22_flg_calc_en", pd22_flg_calc_en); + + /***********************/ + seq_printf(seq, "%-15s:%d\n", "mcen_mode", mcen_mode); + seq_printf(seq, "%-15s:%d\n", "mcuv_en", mcuv_en); + seq_printf(seq, "%-15s:%d\n", "mcdebug_mode", mcdebug_mode); + seq_printf(seq, "%-15s:%d\n", "pldn_ctrl_rflsh", pldn_ctrl_rflsh); +#endif + return 0; +} + diff --git a/drivers/amlogic/media/di_multi/deinterlace_hw.h b/drivers/amlogic/media/di_multi/deinterlace_hw.h new file mode 100644 index 000000000000..ed00b85118b0 --- /dev/null +++ b/drivers/amlogic/media/di_multi/deinterlace_hw.h @@ -0,0 +1,277 @@ +/* + * drivers/amlogic/media/di_multi/deinterlace_hw.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _DI_HW_H +#define _DI_HW_H +#include + +#include "../deinterlace/di_pqa.h" + +/* if post size < 80, filter of ei can't work */ +#define MIN_POST_WIDTH 80 +#define MIN_BLEND_WIDTH 27 + +#define SKIP_CTRE_NUM 13 +/*move from deinterlace.c*/ +enum eAFBC_REG { + eAFBC_ENABLE, + eAFBC_MODE, + eAFBC_SIZE_IN, + eAFBC_DEC_DEF_COLOR, + eAFBC_CONV_CTRL, + eAFBC_LBUF_DEPTH, + eAFBC_HEAD_BADDR, + eAFBC_BODY_BADDR, + eAFBC_SIZE_OUT, + eAFBC_OUT_YSCOPE, + eAFBC_STAT, + eAFBC_VD_CFMT_CTRL, + eAFBC_VD_CFMT_W, + eAFBC_MIF_HOR_SCOPE, + eAFBC_MIF_VER_SCOPE, + eAFBC_PIXEL_HOR_SCOPE, + eAFBC_PIXEL_VER_SCOPE, + eAFBC_VD_CFMT_H, +}; + +enum eAFBC_DEC { + eAFBC_DEC0, + eAFBC_DEC1, +}; + +#define AFBC_REG_INDEX_NUB (18) +#define AFBC_DEC_NUB (2) + +struct DI_MIF_s { + unsigned short luma_x_start0; + unsigned short luma_x_end0; + unsigned short luma_y_start0; + unsigned short luma_y_end0; + unsigned short chroma_x_start0; + unsigned short chroma_x_end0; + unsigned short chroma_y_start0; + unsigned short chroma_y_end0; + unsigned int nocompress; + unsigned set_separate_en:2; + unsigned src_field_mode:1; + unsigned src_prog:1; + unsigned video_mode:1; + unsigned output_field_num:1; + unsigned bit_mode:2; + /* + * unsigned burst_size_y:2; set 3 as default + * unsigned burst_size_cb:2;set 1 as default + * unsigned burst_size_cr:2;set 1 as default + */ + unsigned canvas0_addr0:8; + unsigned canvas0_addr1:8; + unsigned canvas0_addr2:8; +}; + +struct DI_SIM_MIF_s { + unsigned short start_x; + unsigned short end_x; + unsigned short start_y; + unsigned short end_y; + unsigned short canvas_num; + unsigned short bit_mode; +}; + +struct DI_MC_MIF_s { + unsigned short start_x; + unsigned short start_y; + unsigned short end_y; + unsigned short size_x; + unsigned short size_y; + unsigned short canvas_num; + unsigned short blend_en; + unsigned short vecrd_offset; +}; + +enum gate_mode_e { + GATE_AUTO, + GATE_ON, + GATE_OFF, +}; + +struct mcinfo_lmv_s { + unsigned char lock_flag; + char lmv; + unsigned short lock_cnt; +}; + +struct di_pq_parm_s { + struct am_pq_parm_s pq_parm; + struct am_reg_s *regs; + struct list_head list; +}; + +void dim_read_pulldown_info(unsigned int *glb_frm_mot_num, + unsigned int *glb_fid_mot_num); + +#if 0 + +void read_new_pulldown_info(struct FlmModReg_t *pFMRegp); +#endif +void dim_pulldown_info_clear_g12a(void); +void dimh_combing_pd22_window_config(unsigned int width, unsigned int height); +void dimh_hw_init(bool pulldown_en, bool mc_enable); +void dimh_hw_uninit(void); +void dimh_enable_di_pre_aml(struct DI_MIF_s *di_inp_mif, + struct DI_MIF_s *di_mem_mif, + struct DI_MIF_s *di_chan2_mif, + struct DI_SIM_MIF_s *di_nrwr_mif, + struct DI_SIM_MIF_s *di_mtnwr_mif, + struct DI_SIM_MIF_s *di_contp2rd_mif, + struct DI_SIM_MIF_s *di_contprd_mif, + struct DI_SIM_MIF_s *di_contwr_mif, + unsigned char madi_en, + unsigned char pre_field_num, + unsigned char pre_vdin_link); +void dimh_enable_afbc_input(struct vframe_s *vf); + +void dimh_mc_pre_mv_irq(void); +void dimh_enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, + struct DI_MC_MIF_s *di_mcinfowr_mif, + struct DI_MC_MIF_s *di_mcvecwr_mif, + unsigned char mcdi_en); +void dimh_enable_mc_di_pre_g12(struct DI_MC_MIF_s *di_mcinford_mif, + struct DI_MC_MIF_s *di_mcinfowr_mif, + struct DI_MC_MIF_s *di_mcvecwr_mif, + unsigned char mcdi_en); + +void dimh_enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif, + int urgent, bool reverse, int invert_mv); +void dimh_enable_mc_di_post_g12(struct DI_MC_MIF_s *di_mcvecrd_mif, + int urgent, bool reverse, int invert_mv); + +void dimh_disable_post_deinterlace_2(void); +void dimh_initial_di_post_2(int hsize_post, int vsize_post, + int hold_line, bool write_en); +void dimh_enable_di_post_2( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, + int post_field_num, int hold_line, int urgent, + int invert_mv, int vskip_cnt +); +void dimh_post_switch_buffer( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + struct DI_MC_MIF_s *di_mcvecrd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, + int post_field_num, int hold_line, int urgent, + int invert_mv, bool pd_en, bool mc_enable, + int vskip_cnt +); +void dim_post_read_reverse_irq(bool reverse, + unsigned char mc_pre_flag, bool mc_enable); +void dim_top_gate_control(bool top_en, bool mc_en); +void dim_pre_gate_control(bool enable, bool mc_enable); +void dim_post_gate_control(bool gate); +void dim_set_power_control(unsigned char enable); +void dim_hw_disable(bool mc_enable); +void dimh_enable_di_pre_mif(bool enable, bool mc_enable); +void dimh_enable_di_post_mif(enum gate_mode_e mode); + +void dimh_combing_pd22_window_config(unsigned int width, unsigned int height); +void dimh_calc_lmv_init(void); +void dimh_calc_lmv_base_mcinfo(unsigned int vf_height, + unsigned long mcinfo_adr, + unsigned int mcinfo_size); +void dimh_init_field_mode(unsigned short height); +void dim_film_mode_win_config(unsigned int width, unsigned int height); +void dimh_pulldown_vof_win_config(struct pulldown_detected_s *wins); +void dimh_load_regs(struct di_pq_parm_s *di_pq_ptr); +void dim_pre_frame_reset_g12(unsigned char madi_en, unsigned char mcdi_en); +void dim_pre_frame_reset(void); +void dimh_interrupt_ctrl(unsigned char ma_en, + unsigned char det3d_en, unsigned char nrds_en, + unsigned char post_wr, unsigned char mc_en); +void dimh_txl_patch_prog(int prog_flg, unsigned int cnt, bool mc_en); +bool dimh_afbc_is_supported(void); + +void dimh_afbc_reg_sw(bool on); + +void dump_vd2_afbc(void); + +u8 *dim_vmap(ulong addr, u32 size, bool *bflg); +void dim_unmap_phyaddr(u8 *vaddr); +int dim_print(const char *fmt, ...); + +#define DI_MC_SW_OTHER (1 << 0) +#define DI_MC_SW_REG (1 << 1) +/*#define DI_MC_SW_POST (1 << 2)*/ +#define DI_MC_SW_IC (1 << 2) + +#define DI_MC_SW_ON_MASK (DI_MC_SW_REG | DI_MC_SW_OTHER | DI_MC_SW_IC) + +void dimh_patch_post_update_mc(void); +void dimh_patch_post_update_mc_sw(unsigned int cmd, bool on); + +void dim_rst_protect(bool on); +void dim_pre_nr_wr_done_sel(bool on); +void dim_arb_sw(bool on); +void dbg_set_DI_PRE_CTRL(void); +void di_async_reset2(void); /*2019-04-05 add for debug*/ + +enum DI_HW_POST_CTRL { + DI_HW_POST_CTRL_INIT, + DI_HW_POST_CTRL_RESET, +}; + +void dimh_post_ctrl(enum DI_HW_POST_CTRL contr, + unsigned int post_write_en); +void dimh_int_ctr(unsigned int set_mod, unsigned char ma_en, + unsigned char det3d_en, unsigned char nrds_en, + unsigned char post_wr, unsigned char mc_en); + +void h_dbg_reg_set(unsigned int val); + +enum eDI_POST_FLOW { + eDI_POST_FLOW_STEP1_STOP, + eDI_POST_FLOW_STEP2_START, +/* eDI_POST_FLOW_STEP3_RESET_INT,*/ +}; + +void di_post_set_flow(unsigned int post_wr_en, enum eDI_POST_FLOW step); +void post_mif_sw(bool on); +void post_dbg_contr(void); +void post_close_new(void); +void di_post_reset(void); +void dimh_pst_trig_resize(void); + +void hpst_power_ctr(bool on); +void hpst_dbg_power_ctr_trig(unsigned int cmd); +void hpst_dbg_mem_pd_trig(unsigned int cmd); +void hpst_dbg_trig_gate(unsigned int cmd); +void hpst_dbg_trig_mif(unsigned int cmd); +void hpst_mem_pd_sw(unsigned int on); +void hpst_vd1_sw(unsigned int on); + +void dim_init_setting_once(void); +void dim_hw_init_reg(void); + +#endif diff --git a/drivers/amlogic/media/di_multi/di_api.c b/drivers/amlogic/media/di_multi/di_api.c new file mode 100644 index 000000000000..33e91540f814 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_api.c @@ -0,0 +1,107 @@ +/* + * drivers/amlogic/media/di_multi/di_api.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include "di_api.h" +/********************************** + * DI api is used for other module + *********************************/ +static const struct di_ext_ops di_ext = { + .di_post_reg_rd = l_DI_POST_REG_RD, + .di_post_wr_reg_bits = l_DI_POST_WR_REG_BITS, + .post_update_mc = NULL, +}; + +void dim_attach_to_local(void) +{ + dil_attach_ext_api(&di_ext); +} + +bool dim_attach_ext_api(struct di_ext_ops *di_api) +{ + #if 1 + if (!di_api) + return false; + + memcpy(di_api, &di_ext, sizeof(struct di_ext_ops)); + #else + di_api = &di_ext; + #endif + return true; +} + +/*EXPORT_SYMBOL(dim_attach_ext_api);*/ + +/********************************** + * ext_api used by DI + ********************************/ +#define ARY_TEMP2 +#ifdef ARY_TEMP2 +void ext_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on) +{ + switch_vpu_mem_pd_vmod(vmod, + on ? VPU_MEM_POWER_ON : VPU_MEM_POWER_DOWN); +} + +const struct ext_ops_s ext_ops = { + .switch_vpu_mem_pd_vmod = ext_switch_vpu_mem_pd_vmod, + /*no use ?*/ +/* .vf_get_receiver_name = vf_get_receiver_name,*/ + .switch_vpu_clk_gate_vmod = switch_vpu_clk_gate_vmod, + .get_current_vscale_skip_count = get_current_vscale_skip_count, + .canvas_pool_alloc_canvas_table = canvas_pool_alloc_canvas_table, +}; + +#else +void n_switch_vpu_mem_pd_vmod(unsigned int vmod, bool on) +{ +} + +char *n_vf_get_receiver_name(const char *provider_name) +{ + return ""; +} + +void n_switch_vpu_clk_gate_vmod(unsigned int vmod, int flag) +{ +} + +int n_get_current_vscale_skip_count(struct vframe_s *vf) +{ + return 0; +} + +u32 n_canvas_pool_alloc_canvas_table(const char *owner, u32 *tab, + int size, + enum canvas_map_type_e type) +{ + return 0; +} + +const struct ext_ops_s ext_ops = { + .switch_vpu_mem_pd_vmod = n_switch_vpu_mem_pd_vmod, + .vf_get_receiver_name = n_vf_get_receiver_name, + .switch_vpu_clk_gate_vmod = n_switch_vpu_clk_gate_vmod, + .get_current_vscale_skip_count = n_get_current_vscale_skip_count, + .canvas_pool_alloc_canvas_table = n_canvas_pool_alloc_canvas_table, +}; + +#endif + diff --git a/drivers/amlogic/media/di_multi/di_api.h b/drivers/amlogic/media/di_multi/di_api.h new file mode 100644 index 000000000000..0cd08deb12a8 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_api.h @@ -0,0 +1,55 @@ +/* + * drivers/amlogic/media/di_multi/di_api.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_API_H__ +#define __DI_API_H__ + +#include +#include +#include "../di_local/di_local.h" + +/*--------------------------*/ +unsigned int l_DI_POST_REG_RD(unsigned int addr); +int l_DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len); + +/*--------------------------*/ +bool di_attach_ext_api(struct di_ext_ops *di_api); + +/*attach di_ops to di_local*/ +bool dil_attach_ext_api(const struct di_ext_ops *di_api); +void dim_attach_to_local(void); + +/*--------------------------*/ +int get_current_vscale_skip_count(struct vframe_s *vf); + +struct ext_ops_s { + void (*switch_vpu_mem_pd_vmod)(unsigned int vmod, bool on); +/* char *(*vf_get_receiver_name)(const char *provider_name);*/ + void (*switch_vpu_clk_gate_vmod)(unsigned int vmod, int flag); + int (*get_current_vscale_skip_count)(struct vframe_s *vf); + u32 (*canvas_pool_alloc_canvas_table)(const char *owner, u32 *tab, + int size, + enum canvas_map_type_e type); +}; + +extern const struct ext_ops_s ext_ops; + +/*--------------------------*/ +void dil_get_rev_mem(unsigned long *mstart, unsigned int *msize); +void dil_get_flg(unsigned int *flg); + +#endif /*__DI_API_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_data.h b/drivers/amlogic/media/di_multi/di_data.h new file mode 100644 index 000000000000..d9ddb8f6f0d4 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_data.h @@ -0,0 +1,21 @@ +/* + * drivers/amlogic/media/di_multi/di_data.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_DATA_H__ +#define __DI_DATA_H__ + +#endif /*__DI_DATA_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_data_l.h b/drivers/amlogic/media/di_multi/di_data_l.h new file mode 100644 index 000000000000..bdec462730b3 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_data_l.h @@ -0,0 +1,1374 @@ +/* + * drivers/amlogic/media/di_multi/di_data_l.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_DATA_L_H__ +#define __DI_DATA_L_H__ + +#include +#include +#include + +#include /*ary add*/ + +#include "../deinterlace/di_pqa.h" + +#define DI_CHANNEL_NUB (2) +#define DI_CHANNEL_MAX (4) + +#define TABLE_FLG_END (0xfffffffe) +#define TABLE_LEN_MAX (1000) +#define F_IN(x, a, b) (((x) > (a)) && ((x) < (b))) +#define COM_M(m, a, b) (((a) & (m)) == ((b) & (m))) +#define COM_MV(a, m, v) (((a) & (m)) == (v)) +#define COM_ME(a, m) (((a) & (m)) == (m)) + +#define DI_BIT0 0x01 +#define DI_BIT1 0x02 +#define DI_BIT2 0x04 +#define DI_BIT3 0x08 + +/***************************************** + * + * vframe mask + * + *****************************************/ + +#define DI_VFM_T_MASK_CHANGE \ + (VIDTYPE_VIU_422 \ + | VIDTYPE_VIU_SINGLE_PLANE \ + | VIDTYPE_VIU_444 \ + | VIDTYPE_INTERLACE \ + | VIDTYPE_COMPRESS \ + | VIDTYPE_MVC) + +/* ************************************** */ +/* *************** cfg top ************** */ +/* ************************************** */ +/* also see: di_cfg_top_ctr*/ +enum eDI_CFG_TOP_IDX { + /* cfg for top */ + eDI_CFG_BEGIN, + eDI_CFG_first_bypass, + eDI_CFG_ref_2, + eDI_CFG_END, + +}; + +#define K_DI_CFG_NUB (eDI_CFG_END - eDI_CFG_BEGIN + 1) +struct di_cfg_ctr_s { + char *name; + enum eDI_CFG_TOP_IDX id; + bool default_val; +}; + +/* ************************************** */ +/* *************** cfg x *************** */ +/* ************************************** */ +/*also see di_cfgx_ctr*/ +enum eDI_CFGX_IDX { + /* cfg channel x*/ + eDI_CFGX_BEGIN, + eDI_CFGX_BYPASS_ALL, /*bypass_all*/ + eDI_CFGX_END, + + /* debug cfg x */ + eDI_DBG_CFGX_BEGIN, + eDI_DBG_CFGX_IDX_VFM_IN, + eDI_DBG_CFGX_IDX_VFM_OT, + eDI_DBG_CFGX_END, +}; + +#define K_DI_CFGX_NUB (eDI_DBG_CFGX_END - eDI_CFGX_BEGIN + 1) + +struct di_cfgx_ctr_s { + char *name; + enum eDI_CFGX_IDX id; + bool default_val; +}; + +/* ****************************** */ +enum eDI_SUB_ID { + DI_SUB_ID_S0, /*DI_SUB_ID_MARST,*/ + DI_SUB_ID_S1, + DI_SUB_ID_S2, + DI_SUB_ID_S3, + /*DI_SUB_ID_NUB,*/ +}; + +/*debug vframe type */ +struct di_vframe_type_info { + char *name; + unsigned int mask; + char *other; +}; + +struct di_dbg_datax_s { + struct vframe_s vfm_input; /*debug input vframe*/ + struct vframe_s *pfm_out; /*debug di_get vframe*/ + +}; + +/*debug function*/ +enum eDI_DBG_F { + eDI_DBG_F_00, + eDI_DBG_F_01, + eDI_DBG_F_02, + eDI_DBG_F_03, + eDI_DBG_F_04, + eDI_DBG_F_05, + eDI_DBG_F_06, + eDI_DBG_F_07, + eDI_DBG_F_08, +}; + +struct di_dbg_func_s { + enum eDI_DBG_F index; + void (*func)(unsigned int para); + char *name; + char *info; +}; + +/*register*/ +struct reg_t { + unsigned int add; + unsigned int bit; + unsigned int wid; +/* unsigned int id;*/ + unsigned int df_val; + char *name; + char *bname; + char *info; +}; + +struct reg_acc { + void (*wr)(unsigned int adr, unsigned int val); + unsigned int (*rd)(unsigned int adr); + unsigned int (*bwr)(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len); + unsigned int (*brd)(unsigned int adr, unsigned int start, + unsigned int len); +}; + +/**************************************/ +/* time out */ +/**************************************/ + +enum eDI_TOUT_CONTR { +/* eDI_TOUT_CONTR_INT,*/ + eDI_TOUT_CONTR_EN, + eDI_TOUT_CONTR_FINISH, + eDI_TOUT_CONTR_CHECK, + + eDI_TOUT_CONTR_CLEAR, + eDI_TOUT_CONTR_RESET, +}; + +struct di_time_out_s { + bool en; + unsigned long timer_start; + unsigned int timer_thd; + unsigned int over_flow_cnt; + bool flg_over; +/* bool (*do_func)(void);*/ +}; + +struct di_func_tab_s { + unsigned int index; + bool (*func)(void); +}; + +/****************************************/ +/* do_table */ +/****************************************/ + +/*for do_table_ops_s id*/ +#define K_DO_TABLE_ID_PAUSE 0 +#define K_DO_TABLE_ID_STOP 1 +#define K_DO_TABLE_ID_START 2 + +/*for mark of do_table_ops_s id*/ +#define K_DO_TABLE_CAN_STOP 0x01 + +/*for op ret*/ +#define K_DO_TABLE_R_B_FINISH 0x01/*bit 0: 0:not finish, 1:finish*/ +/*bit 1: 0: to other index; 1: to next*/ +#define K_DO_TABLE_R_B_NEXT 0x02 +#define K_DO_TABLE_R_B_OTHER 0xf0 /*bit [7:4]: other index*/ +#define K_DO_TABLE_R_B_OTHER_SHIFT 4 /*bit [7:4]: other index*/ + +#define K_DO_R_FINISH (K_DO_TABLE_R_B_FINISH | K_DO_TABLE_R_B_NEXT) +#define K_DO_R_NOT_FINISH (0) +#define K_DO_R_JUMP(a) (K_DO_TABLE_R_B_FINISH | \ + (((a) << K_DO_TABLE_R_B_OTHER_SHIFT) & K_DO_TABLE_R_B_OTHER)) + +enum eDO_TABLE_CMD { + eDO_TABLE_CMD_NONE, + eDO_TABLE_CMD_STOP, + eDO_TABLE_CMD_START, + eDO_TABLE_CMD_PAUSE, + eDO_TABLE_CMD_STEP, + eDO_TABLE_CMD_STEP_BACK, +}; + +struct do_table_ops_s { + /*bool stop_mark;*/ + unsigned int id; + unsigned int mark; /*stop / pause*/ + bool (*con)(void *data);/*condition*/ + unsigned int (*do_op)(void *data); + unsigned int (*do_stop_op)(void *data); + char *name; + +}; + +struct do_table_s { + const struct do_table_ops_s *ptab; + unsigned int size; + unsigned int op_lst; + unsigned int op_crr; + void *data; + bool do_stop; /*need do stops */ + bool flg_stop; /*have stop */ + + bool do_pause; + bool do_step; /*step mode*/ + + bool flg_repeat; + char *name; + +}; + +/*************************************/ + +/**********************/ +/* vframe info */ +/**********************/ +struct di_vinfo_s { + /*use this for judge type change or not */ + unsigned int ch; + unsigned int vtype; + unsigned int src_type; + unsigned int trans_fmt; + unsigned int h; + unsigned int v; +}; + +/**************************************/ +/* PRE */ +/**************************************/ +enum eDI_PRE_ST { + eDI_PRE_ST_EXIT, + eDI_PRE_ST_IDLE, /*swith to next channel?*/ + eDI_PRE_ST_CHECK, + eDI_PRE_ST_SET, + eDI_PRE_ST_WAIT_INT, + eDI_PRE_ST_TIMEOUT, +}; + +enum eDI_PRE_ST4 { /*use this for co work with do table*/ + eDI_PRE_ST4_EXIT, + eDI_PRE_ST4_IDLE, /*swith to next channel?*/ + eDI_PRE_ST4_CHECK, /*check mode do_table and set*/ + eDI_PRE_ST4_DO_TABLE, /* do table statue;*/ +}; + +struct di_pre_set_s { + /*use to remember last hw pre setting;*/ + /*cfg: */ + bool cfg_mcpre_en; /*mcpre_en*/ + + unsigned int in_w; + unsigned int in_h; + unsigned int in_type; + unsigned int src_type; +}; + +struct di_hpre_s { + enum eDI_PRE_ST4 pre_st; + unsigned int curr_ch; + /*set when have vframe in; clear when int have get*/ + bool hw_flg_busy_pre; +/* bool trig_unreg;*/ /*add for unreg flow;*/ +/* enum eDI_SUB_ID hw_owner_pre;*/ + bool flg_wait_int; + struct di_pre_stru_s *pres; + struct di_post_stru_s *psts; + struct di_time_out_s tout; /*for time out*/ + bool flg_int_done; + unsigned int check_recycle_buf_cnt; + + struct di_pre_set_s set_lst; + struct di_pre_set_s set_curr; + + struct di_vinfo_s vinf_lst; + struct di_vinfo_s vinf_curr; + + /* use do table to swith mode*/ + struct do_table_s sdt_mode; + + unsigned int idle_cnt; /*use this avoid repeat idle <->check*/ + /*dbg flow:*/ + bool dbg_f_en; + unsigned int dbg_f_lstate; + unsigned int dbg_f_cnt; +}; + +/**************************************/ +/* POST */ +/**************************************/ +enum eDI_PST_ST { + eDI_PST_ST_EXIT, + eDI_PST_ST_IDLE, /*swith to next channel?*/ + eDI_PST_ST_CHECK, + eDI_PST_ST_SET, + eDI_PST_ST_WAIT_INT, + eDI_PST_ST_TIMEOUT, + eDI_PST_ST_DONE, /*use for bypass_all*/ +}; + +struct di_hpst_s { + enum eDI_PST_ST state; + unsigned int curr_ch; + /*set when have vframe in; clear when int have get*/ + bool hw_flg_busy_post; + struct di_pre_stru_s *pres; + struct di_post_stru_s *psts; + struct di_time_out_s tout; /*for time out*/ + bool flg_int_done; + + /*dbg flow:*/ + bool dbg_f_en; + unsigned int dbg_f_lstate; + unsigned int dbg_f_cnt; + +}; + +/**************************************/ +/* channel status */ +/**************************************/ +enum eDI_TOP_STATE { + eDI_TOP_STATE_NOPROB, + eDI_TOP_STATE_IDLE, /*idle not work*/ + /* STEP1 + * till peek vframe and set irq;before this state, event reg finish + */ + eDI_TOP_STATE_REG_STEP1, + eDI_TOP_STATE_REG_STEP1_P1, /*2019-05-21*/ + eDI_TOP_STATE_REG_STEP2, /*till alloc and ready*/ + eDI_TOP_STATE_READY, /*can do DI*/ + eDI_TOP_STATE_BYPASS, /*complet bypass*/ + eDI_TOP_STATE_UNREG_STEP1, /*till pre/post is finish;*/ + /* do unreg and to IDLE. + * no need to wait cma release after this unreg event finish + */ + eDI_TOP_STATE_UNREG_STEP2, + +}; + +/**************************************/ +/* thread and cmd */ +/**************************************/ +struct di_task { + bool flg_init; + struct semaphore sem; + wait_queue_head_t wait_queue; + struct task_struct *thread; + unsigned int status; + + unsigned int wakeup; + unsigned int delay; + bool exit; +#if 1 /*not use cmd*/ + + /*local event*/ + struct kfifo fifo_cmd; + spinlock_t lock_cmd; + bool flg_cmd; + unsigned int err_cmd_cnt; +#endif +}; + +#define MAX_KFIFO_L_CMD_NUB 32 + +union DI_L_CMD_BITS { + unsigned int cmd32; + struct { + unsigned int id:8, /*low bit*/ + ch:8, /*channel*/ + p2:8, + p3:8; + } b; +}; + +#define LCMD1(id, ch) ((id) | ((ch) << 8)) + +enum eCMD_LOCAL { + eCMD_NONE, + eCMD_REG, + eCMD_UNREG, + eCMD_READY, + eCMD_CHG, + NR_FINISH, +}; + +/**************************************/ +/*QUE*/ +/**************************************/ +enum QUE_TYPE { /*mast start from 0 */ + QUE_IN_FREE, /*5*/ + QUE_PRE_READY, /*6*/ + QUE_POST_FREE, /*7*/ + QUE_POST_READY, /*8*/ + QUE_POST_BACK, /*new*/ + /*----------------*/ + QUE_DBG, + QUE_NUB, +}; + +/*#define QUE_NUB (5)*/ +enum eDI_BUF_TYPE { + eDI_BUF_T_IN = 1, /*VFRAME_TYPE_IN*/ + eDI_BUF_T_LOCAL, /*VFRAME_TYPE_LOCAL*/ + eDI_BUF_T_POST, /*VFRAME_TYPE_POST*/ +}; + +#define MAX_FIFO_SIZE (32) + +/************************************** + * + * summmary variable + * also see:di_sum_name_tab + **************************************/ + +enum eDI_SUM { + eDI_SUM_O_PEEK_CNT, /*video_peek_cnt*/ + eDI_SUM_REG_UNREG_CNT, /*di_reg_unreg_cnt*/ + eDI_SUM_NUB, +}; + +struct di_sum_s { + char *name; + enum eDI_SUM index; + unsigned int default_val; +}; + +/************************************** + * + * module para + * int + * eDI_MP_SUB_DI_B + * eDI_MP_SUB_NR_B + * eDI_MP_SUB_PD_B + * eDI_MP_SUB_MTN_B + * eDI_MP_SUB_3D_B + **************************************/ +enum eDI_MP_UI_T { + /*keep same order with di_mp_ui_top*/ + eDI_MP_UI_T_BEGIN, + /**************************************/ + eDI_MP_SUB_DI_B, + + eDI_MP_force_prog, /*force_prog bool*/ + edi_mp_combing_fix_en, /*combing_fix_en bool*/ + eDI_MP_cur_lev, /*cur_lev*/ + eDI_MP_pps_dstw, /*pps_dstw*/ + eDI_MP_pps_dsth, /*pps_dsth*/ + eDI_MP_pps_en, /*pps_en*/ + eDI_MP_pps_position, /*pps_position*/ + eDI_MP_pre_enable_mask, /*pre_enable_mask*/ + eDI_MP_post_refresh, /*post_refresh*/ + eDI_MP_nrds_en, /*nrds_en*/ + eDI_MP_bypass_3d, /*bypass_3d*/ + eDI_MP_bypass_trick_mode, /*bypass_trick_mode*/ + eDI_MP_invert_top_bot, /*invert_top_bot */ + eDI_MP_skip_top_bot, + eDI_MP_force_width, + eDI_MP_force_height, + eDI_MP_prog_proc_config, + eDI_MP_start_frame_drop_count, + eDI_MP_same_field_top_count, /*long?*/ + eDI_MP_same_field_bot_count, /*long?*/ + eDI_MP_vpp_3d_mode, + eDI_MP_force_recovery_count, + eDI_MP_pre_process_time, /*no use?*/ + eDI_MP_bypass_post, + eDI_MP_post_wr_en, + eDI_MP_post_wr_support, + eDI_MP_bypass_post_state, + eDI_MP_use_2_interlace_buff, + eDI_MP_debug_blend_mode, + eDI_MP_nr10bit_support, + eDI_MP_di_stop_reg_flag, + eDI_MP_mcpre_en, + eDI_MP_check_start_drop_prog, + eDI_MP_overturn, /*? in init*/ + eDI_MP_full_422_pack, + eDI_MP_cma_print, + eDI_MP_pulldown_enable, + eDI_MP_di_force_bit_mode, + eDI_MP_calc_mcinfo_en, + eDI_MP_colcfd_thr, + eDI_MP_post_blend, + eDI_MP_post_ei, + eDI_MP_post_cnt, + eDI_MP_di_log_flag, + eDI_MP_di_debug_flag, + eDI_MP_buf_state_log_threshold, + eDI_MP_di_vscale_skip_enable, + eDI_MP_di_vscale_skip_count, + eDI_MP_di_vscale_skip_count_real, + eDI_MP_det3d_en, + eDI_MP_post_hold_line, + eDI_MP_post_urgent, + eDI_MP_di_printk_flag, + eDI_MP_force_recovery, +/* eDI_MP_debug_blend_mode,*/ + eDI_MP_di_dbg_mask, + eDI_MP_nr_done_check_cnt, + eDI_MP_pre_hsc_down_en, + eDI_MP_pre_hsc_down_width, + eDI_MP_show_nrwr, + /********deinterlace_hw.c*********/ + eDI_MP_pq_load_dbg, + eDI_MP_lmv_lock_win_en, + eDI_MP_lmv_dist, + eDI_MP_pr_mcinfo_cnt, + eDI_MP_offset_lmv, + eDI_MP_post_ctrl, + eDI_MP_if2_disable, + eDI_MP_pre_flag, + eDI_MP_pre_mif_gate, + eDI_MP_pre_urgent, + eDI_MP_pre_hold_line, + eDI_MP_pre_ctrl, + eDI_MP_line_num_post_frst, + eDI_MP_line_num_pre_frst, + eDI_MP_pd22_flg_calc_en, + eDI_MP_mcen_mode, + eDI_MP_mcuv_en, + eDI_MP_mcdebug_mode, + eDI_MP_pldn_ctrl_rflsh, + + eDI_MP_SUB_DI_E, + /**************************************/ + eDI_MP_SUB_NR_B, + eDI_MP_dnr_en, + eDI_MP_nr2_en, + eDI_MP_cue_en, + eDI_MP_invert_cue_phase, + eDI_MP_cue_pr_cnt, + eDI_MP_cue_glb_mot_check_en, + eDI_MP_glb_fieldck_en, + eDI_MP_dnr_pr, + eDI_MP_dnr_dm_en, + eDI_MP_SUB_NR_E, + /**************************************/ + eDI_MP_SUB_PD_B, + eDI_MP_flm22_ratio, + eDI_MP_pldn_cmb0, + eDI_MP_pldn_cmb1, + eDI_MP_flm22_sure_num, + eDI_MP_flm22_glbpxlnum_rat, + eDI_MP_flag_di_weave, + eDI_MP_flm22_glbpxl_maxrow, + eDI_MP_flm22_glbpxl_minrow, + eDI_MP_cmb_3point_rnum, + eDI_MP_cmb_3point_rrat, + /******film_fw1.c**/ + eDI_MP_pr_pd, + eDI_MP_prt_flg, + eDI_MP_flmxx_maybe_num, + eDI_MP_flm32_mim_frms, + eDI_MP_flm22_dif01a_flag, + eDI_MP_flm22_mim_frms, + eDI_MP_flm22_mim_smfrms, + eDI_MP_flm32_f2fdif_min0, + eDI_MP_flm32_f2fdif_min1, + eDI_MP_flm32_chk1_rtn, + eDI_MP_flm32_ck13_rtn, + eDI_MP_flm32_chk2_rtn, + eDI_MP_flm32_chk3_rtn, + eDI_MP_flm32_dif02_ratio, + eDI_MP_flm22_chk20_sml, + eDI_MP_flm22_chk21_sml, + eDI_MP_flm22_chk21_sm2, + eDI_MP_flm22_lavg_sft, + eDI_MP_flm22_lavg_lg, + eDI_MP_flm22_stl_sft, + eDI_MP_flm22_chk5_avg, + eDI_MP_flm22_chk6_max, + eDI_MP_flm22_anti_chk1, + eDI_MP_flm22_anti_chk3, + eDI_MP_flm22_anti_chk4, + eDI_MP_flm22_anti_ck140, + eDI_MP_flm22_anti_ck141, + eDI_MP_flm22_frmdif_max, + eDI_MP_flm22_flddif_max, + eDI_MP_flm22_minus_cntmax, + eDI_MP_flagdif01chk, + eDI_MP_dif01_ratio, + /*******vof_soft_top*****/ + eDI_MP_cmb32_blw_wnd, + eDI_MP_cmb32_wnd_ext, + eDI_MP_cmb32_wnd_tol, + eDI_MP_cmb32_frm_nocmb, + eDI_MP_cmb32_min02_sft, + eDI_MP_cmb32_cmb_tol, + eDI_MP_cmb32_avg_dff, + eDI_MP_cmb32_smfrm_num, + eDI_MP_cmb32_nocmb_num, + eDI_MP_cmb22_gcmb_rnum, + eDI_MP_flmxx_cal_lcmb, + eDI_MP_flm2224_stl_sft, + eDI_MP_SUB_PD_E, + /**************************************/ + eDI_MP_SUB_MTN_B, + eDI_MP_force_lev, + eDI_MP_dejaggy_flag, + eDI_MP_dejaggy_enable, + eDI_MP_cmb_adpset_cnt, + eDI_MP_cmb_num_rat_ctl4, + eDI_MP_cmb_rat_ctl4_minthd, + eDI_MP_small_local_mtn, + eDI_MP_di_debug_readreg, + eDI_MP_SUB_MTN_E, + /**************************************/ + eDI_MP_SUB_3D_B, + eDI_MP_chessbd_vrate, + eDI_MP_det3d_debug, + + eDI_MP_SUB_3D_E, + /**************************************/ + eDI_MP_UI_T_END, +}; + +#define K_DI_MP_UIT_NUB (eDI_MP_UI_T_END - eDI_MP_UI_T_BEGIN + 1) + +struct di_mp_uit_s { + char *name; + enum eDI_MP_UI_T id; + int default_val; +}; + +/*also see: di_mpx*/ +enum eDI_MP_UIX_T { + eDI_MP_UIX_BEGIN, + eDI_MP_UIX_RUN_FLG, /*run_flag*/ + eDI_MP_UIX_END, +}; + +#define K_DI_MP_UIX_NUB (eDI_MP_UIX_END - eDI_MP_UIX_BEGIN + 1) + +struct di_mp_uix_s { + char *name; + enum eDI_MP_UIX_T id; + unsigned int default_val; +}; + +/**************************************/ +/* DI WORKING MODE */ +/**************************************/ +enum eDI_WORK_MODE { + eDI_WORK_MODE_NONE, + eDI_WORK_MODE_bypass_complet, + eDI_WORK_MODE_bypass_all, /*dim_is_bypass*/ + eDI_WORK_MODE_bypass_pre, + eDI_WORK_MODE_bypass_post, + eDI_WORK_MODE_i, + eDI_WORK_MODE_p_as_i, + eDI_WORK_MODE_p_as_p, + eDI_WORK_MODE_p_use_ibuf, + eDI_WORK_MODE_all, + +}; + +/**************************************/ +/* vframe */ +/**************************************/ +struct dev_vfram_t { + const char *name; + /*receiver:*/ + struct vframe_receiver_s di_vf_recv; + /*provider:*/ + struct vframe_provider_s di_vf_prov; + + unsigned int indx; + /*status:*/ + bool bypass_complete; + bool reg; /*use this for vframe reg/unreg*/ +/* unsigned int data[32]; */ /*null*/ + +}; + +struct di_ores_s { + /* same as ori */ + struct di_pre_stru_s di_pre_stru; + struct di_post_stru_s di_post_stru; + + struct di_buf_s di_buf_local[MAX_LOCAL_BUF_NUM * 2]; + struct di_buf_s di_buf_in[MAX_IN_BUF_NUM]; + struct di_buf_s di_buf_post[MAX_POST_BUF_NUM]; + + struct queue_s queue[QUEUE_NUM]; + struct di_buf_pool_s di_buf_pool[VFRAME_TYPE_NUM]; + + struct vframe_s *vframe_in[MAX_IN_BUF_NUM]; + struct vframe_s vframe_in_dup[MAX_IN_BUF_NUM]; + struct vframe_s vframe_local[MAX_LOCAL_BUF_NUM * 2]; + struct vframe_s vframe_post[MAX_POST_BUF_NUM]; + /* ********** */ +}; + +enum eDI_CMA_ST { + eDI_CMA_ST_IDL, + eDI_CMA_ST_ALLOC, /*do*/ + eDI_CMA_ST_READY, + eDI_CMA_ST_RELEASE, /*do*/ +}; + +/********************************** + * mem + *********************************/ +struct di_mm_cfg_s { + /*support di size*/ + unsigned int di_h; + unsigned int di_w; + /**/ + unsigned int num_local; + unsigned int num_post; +}; + +struct di_mm_st_s { + /* use for reserved and alloc all*/ + unsigned long mem_start; + unsigned int mem_size; + struct page *total_pages; + + unsigned int flag_cma; + + unsigned int size_local; + unsigned int size_post; + int num_local; + int num_post; /*ppost*/ +}; + +struct di_mm_s { + struct di_mm_cfg_s cfg; + struct di_mm_st_s sts; +}; + +struct di_ch_s { + /*struct di_cfgx_s dbg_cfg;*/ + bool cfgx_en[K_DI_CFGX_NUB]; + unsigned int mp_uix[K_DI_MP_UIX_NUB];/*module para x*/ + + struct di_dbg_datax_s dbg_data; + + struct dev_vfram_t vfm; + struct dentry *dbg_rootx; /*dbg_fs*/ + + unsigned int ch_id; + struct di_ores_s rse_ori; + struct kfifo fifo[QUE_NUB]; + bool flg_fifo[QUE_NUB]; /*have ini: 1; else 0*/ +/* bool sub_act_flg;*/ + /************************/ + /*old glob*/ + /************************/ + /*bypass_state*/ + bool bypass_state; + + /*video_peek_cnt*/ + unsigned int sum[eDI_SUM_NUB + 1]; + unsigned int sum_get; + unsigned int sum_put; + +}; + +struct di_meson_data { + const char *name; + /*struct ic_ver icver;*/ + /*struct ddemod_reg_off regoff;*/ +}; + +struct di_mng_s { + /*workqueue*/ + struct workqueue_struct *wq_cma; + struct work_struct wq_work; + + /*use enum eDI_CMA_ST*/ + atomic_t cma_mem_state[DI_CHANNEL_NUB]; + /*1:alloc cma, 0:release cma set by mng, read by work que*/ + unsigned char cma_reg_cmd[DI_CHANNEL_NUB]; + + /*task:*/ + struct di_task tsk; + + /*channel state: use enum eDI_TOP_STATE */ + atomic_t ch_state[DI_CHANNEL_NUB]; + + bool in_flg[DI_CHANNEL_NUB]; + unsigned long mem_start[DI_CHANNEL_NUB]; + unsigned int mem_size[DI_CHANNEL_NUB]; + + bool sub_act_flg[DI_CHANNEL_NUB]; + /*struct mutex event_mutex[DI_CHANNEL_NUB];*/ + bool init_flg[DI_CHANNEL_NUB]; /*init_flag*/ + /*bool reg_flg[DI_CHANNEL_NUB];*/ /*reg_flag*/ + unsigned int reg_flg_ch; /*for x ch reg/unreg flg*/ + bool trig_unreg[DI_CHANNEL_NUB]; + bool hw_reg_flg; /*for di_reg_setting/di_unreg_setting*/ + bool act_flg ;/*active_flag*/ + + bool flg_hw_int; /*only once*/ + + struct di_mm_s mm; +}; + +/************************* + *debug register: + *************************/ +#define K_DI_SIZE_REG_LOG (1000) +#define K_DI_LAB_MOD (0xf001) +/*also see: dbg_mode_name*/ +enum eDI_DBG_MOD { + eDI_DBG_MOD_REGB, /* 0 */ + eDI_DBG_MOD_REGE, /* 1 */ + eDI_DBG_MOD_UNREGB, /* 2 */ + eDI_DBG_MOD_UNREGE, /* 3 */ + eDI_DBG_MOD_PRE_SETB, /* 4 */ + eDI_DBG_MOD_PRE_SETE, /* 5 */ + eDI_DBG_MOD_PRE_DONEB, /* 6 */ + eDI_DBG_MOD_PRE_DONEE, /* 7 */ + eDI_DBG_MOD_POST_SETB, /* 8 */ + eDI_DBG_MOD_POST_SETE, /* 9 */ + eDI_DBG_MOD_POST_IRQB, /* a */ + eDI_DBG_MOD_POST_IRQE, /* b */ + eDI_DBG_MOD_POST_DB, /* c */ + eDI_DBG_MOD_POST_DE, /* d */ + eDI_DBG_MOD_POST_CH_CHG, /* e */ + eDI_DBG_MOD_POST_TIMEOUT, /* F */ + + eDI_DBG_MOD_RVB, /*10 */ + eDI_DBG_MOD_RVE, /*11 */ + + eDI_DBG_MOD_POST_RESIZE, /*0x12 */ + eDI_DBG_MOD_END, + +}; + +enum eDI_LOG_TYPE { + eDI_LOG_TYPE_ALL = 1, + eDI_LOG_TYPE_REG, + eDI_LOG_TYPE_MOD, +}; + +struct di_dbg_reg { + unsigned int addr; + unsigned int val; + unsigned int st_bit:8, + b_w:8, + res:16; +}; + +struct di_dbg_mod { + unsigned int lable; /*0xf001: mean dbg mode*/ + unsigned int ch:8, + mod:8, + res:16; + unsigned int cnt;/*frame cnt*/ +}; + +union udbg_data { + struct di_dbg_reg reg; + struct di_dbg_mod mod; +}; + +struct di_dbg_reg_log { + bool en; + bool en_reg; + bool en_mod; + bool en_all; + bool en_notoverwrite; + + union udbg_data log[K_DI_SIZE_REG_LOG]; + unsigned int pos; + unsigned int wsize; + bool overflow; +}; + +struct di_dbg_data { + unsigned int vframe_type; /*use for type info*/ + unsigned int cur_channel; + struct di_dbg_reg_log reg_log; +}; + +struct di_data_l_s { + bool cfg_en[K_DI_CFG_NUB]; /*cfg_top*/ + int mp_uit[K_DI_MP_UIT_NUB]; /*eDI_MP_UI_T*/ + struct di_ch_s ch_data[DI_CHANNEL_NUB]; + int plane[DI_CHANNEL_NUB]; /*use for debugfs*/ + + struct di_dbg_data dbg_data; + struct di_mng_s mng; + struct di_hpre_s hw_pre; + struct di_hpst_s hw_pst; + struct dentry *dbg_root_top; /* dbg_fs*/ + /*pq_ops*/ + const struct pulldown_op_s *ops_pd; /* pulldown */ + const struct detect3d_op_s *ops_3d; /* detect_3d */ + const struct nr_op_s *ops_nr; /* nr */ + const struct mtn_op_s *ops_mtn; /* deinterlace_mtn */ + /*di ops for other module */ + /*struct di_ext_ops *di_api; */ + const struct di_meson_data *mdata; +}; + +/************************************** + * + * DEBUG infor + * + *************************************/ + +#define DBG_M_C_ALL 0x2000 /*all debug close*/ +#define DBG_M_O_ALL 0x1000 /*all debug open*/ + +#define DBG_M_DT 0x01 /*do table work*/ +#define DBG_M_REG 0x02 /*reg/unreg*/ +#define DBG_M_POST_REF 0x04 +#define DBG_M_TSK 0x08 +#define DBG_M_INIT 0x10 +#define DBG_M_EVENT 0x20 +#define DBG_M_FIRSTFRAME 0x40 +#define DBG_M_DBG 0x80 + +#define DBG_M_POLLING 0x100 +#define DBG_M_ONCE 0x200 + +extern unsigned int di_dbg; + +#define dbg_m(mark, fmt, args ...) \ + do { \ + if (di_dbg & DBG_M_C_ALL) \ + break; \ + if ((di_dbg & DBG_M_O_ALL) || \ + (di_dbg & (mark))) { \ + pr_info("dim:"fmt, ##args); \ + } \ + } while (0) + +#define PR_ERR(fmt, args ...) pr_err("dim:err:"fmt, ## args) +#define PR_WARN(fmt, args ...) pr_err("dim:warn:"fmt, ## args) +#define PR_INF(fmt, args ...) pr_info("dim:"fmt, ## args) + +#define dbg_dt(fmt, args ...) dbg_m(DBG_M_DT, fmt, ##args) +#define dbg_reg(fmt, args ...) dbg_m(DBG_M_REG, fmt, ##args) +#define dbg_post_ref(fmt, args ...) dbg_m(DBG_M_POST_REF, fmt, ##args) +#define dbg_poll(fmt, args ...) dbg_m(DBG_M_POLLING, fmt, ##args) +#define dbg_tsk(fmt, args ...) dbg_m(DBG_M_TSK, fmt, ##args) + +#define dbg_init(fmt, args ...) dbg_m(DBG_M_INIT, fmt, ##args) +#define dbg_ev(fmt, args ...) dbg_m(DBG_M_EVENT, fmt, ##args) +#define dbg_first_frame(fmt, args ...) dbg_m(DBG_M_FIRSTFRAME, fmt, ##args) +#define dbg_dbg(fmt, args ...) dbg_m(DBG_M_DBG, fmt, ##args) +#define dbg_once(fmt, args ...) dbg_m(DBG_M_ONCE, fmt, ##args) + +char *di_cfgx_get_name(enum eDI_CFGX_IDX idx); +bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx); +void di_cfgx_set(unsigned int ch, enum eDI_CFGX_IDX idx, bool en); + +static inline struct di_data_l_s *get_datal(void) +{ + return (struct di_data_l_s *)get_dim_de_devp()->data_l; +} + +static inline struct di_ch_s *get_chdata(unsigned int ch) +{ + return &get_datal()->ch_data[ch]; +} + +static inline struct di_mng_s *get_bufmng(void) +{ + return &get_datal()->mng; +} + +static inline unsigned long di_get_mem_start(unsigned int ch) +{ + return get_datal()->mng.mem_start[ch]; +} + +static inline void di_set_mem_info(unsigned int ch, + unsigned long mstart, unsigned int size) +{ + get_datal()->mng.mem_start[ch] = mstart; + get_datal()->mng.mem_size[ch] = size; +} + +static inline unsigned int *di_get_mem_size(unsigned int ch) +{ + return &get_datal()->mng.mem_size[ch]; +} + +static inline struct di_hpre_s *get_hw_pre(void) +{ + return &get_datal()->hw_pre; +} + +static inline struct di_hpst_s *get_hw_pst(void) +{ + return &get_datal()->hw_pst; +} + +/**************************************** + * flg_hw_int + * for hw set once + ****************************************/ +static inline bool di_get_flg_hw_int(void) +{ + return get_datal()->mng.flg_hw_int; +} + +static inline void di_set_flg_hw_int(bool on) +{ + get_datal()->mng.flg_hw_int = on; +} + +/********************** + * + * reg log: + *********************/ +static inline struct di_dbg_reg_log *get_dbg_reg_log(void) +{ + return &get_datal()->dbg_data.reg_log; +} + +/********************** + * + * flg_wait_int + *********************/ +static inline void di_pre_wait_irq_set(bool on) +{ + get_hw_pre()->flg_wait_int = on; +} + +static inline bool di_pre_wait_irq_get(void) +{ + return get_hw_pre()->flg_wait_int; +} + +static inline struct di_ores_s *get_orsc(unsigned int ch) +{ + return &get_datal()->ch_data[ch].rse_ori; +} + +static inline struct vframe_s **get_vframe_in(unsigned int ch) +{ + return &get_orsc(ch)->vframe_in[0]; +} + +static inline struct vframe_s *get_vframe_in_dup(unsigned int ch) +{ + return &get_orsc(ch)->vframe_in_dup[0]; +} + +static inline struct vframe_s *get_vframe_local(unsigned int ch) +{ + return &get_orsc(ch)->vframe_local[0]; +} + +static inline struct vframe_s *get_vframe_post(unsigned int ch) +{ + return &get_orsc(ch)->vframe_post[0]; +} + +static inline struct di_buf_s *get_buf_local(unsigned int ch) +{ + return &get_orsc(ch)->di_buf_local[0]; +} + +static inline struct di_buf_s *get_buf_in(unsigned int ch) +{ + return &get_orsc(ch)->di_buf_in[0]; +} + +static inline struct di_buf_s *get_buf_post(unsigned int ch) +{ + return &get_orsc(ch)->di_buf_post[0]; +} + +static inline struct queue_s *get_queue(unsigned int ch) +{ + return &get_orsc(ch)->queue[0]; +} + +static inline struct di_buf_pool_s *get_buf_pool(unsigned int ch) +{ + return &get_orsc(ch)->di_buf_pool[0]; +} + +static inline struct di_pre_stru_s *get_pre_stru(unsigned int ch) +{ + return &get_orsc(ch)->di_pre_stru; +} + +static inline struct di_post_stru_s *get_post_stru(unsigned int ch) +{ + return &get_orsc(ch)->di_post_stru; +} + +static inline enum eDI_SUB_ID get_current_channel(void) +{ + return get_datal()->dbg_data.cur_channel; +} + +static inline void set_current_channel(unsigned int channel) +{ + get_datal()->dbg_data.cur_channel = channel; +} + +static inline bool get_init_flag(unsigned char ch) +{ + return get_bufmng()->init_flg[ch]; +} + +static inline void set_init_flag(unsigned char ch, bool on) +{ + get_bufmng()->init_flg[ch] = on; +} + +extern const unsigned int di_ch2mask_table[DI_CHANNEL_MAX]; +/****************************************** + * + * reg / unreg + * + *****************************************/ +static inline bool get_reg_flag(unsigned char ch) +{ + unsigned int flg = get_bufmng()->reg_flg_ch; + bool ret = false; + + if (di_ch2mask_table[ch] & flg) + ret = true; + + /*dim_print("%s:%d\n", __func__, ret);*/ + return ret; +} + +static inline unsigned int get_reg_flag_all(void) +{ + return get_bufmng()->reg_flg_ch; +} + +static inline void set_reg_flag(unsigned char ch, bool on) +{ + unsigned int flg = get_bufmng()->reg_flg_ch; + + if (on) + get_bufmng()->reg_flg_ch = flg | di_ch2mask_table[ch]; + else + get_bufmng()->reg_flg_ch = flg & (~di_ch2mask_table[ch]); + /*dim_print("%s:%d\n", __func__, get_bufmng()->reg_flg_ch);*/ +} + +/****************************************** + * + * trig unreg: + * when unreg: set 1 + * when reg: set 0 + *****************************************/ + +static inline bool get_flag_trig_unreg(unsigned char ch) +{ + return get_bufmng()->trig_unreg[ch]; +} + +#if 0 +static inline unsigned int get_reg_flag_all(void) +{ + return get_bufmng()->reg_flg_ch; +} +#endif + +static inline void set_flag_trig_unreg(unsigned char ch, bool on) +{ + get_bufmng()->trig_unreg[ch] = on; +} + +static inline bool get_hw_reg_flg(void) +{ + return get_bufmng()->hw_reg_flg; +} + +static inline void set_hw_reg_flg(bool on) +{ + get_bufmng()->hw_reg_flg = on; +} + +static inline bool get_or_act_flag(void) +{ + return get_bufmng()->act_flg; +} + +static inline void set_or_act_flag(bool on) +{ + get_bufmng()->act_flg = on; +} + +/*sum*/ +static inline void di_sum_set_l(unsigned int ch, enum eDI_SUM id, + unsigned int val) +{ + get_chdata(ch)->sum[id] = val; +} + +static inline unsigned int di_sum_inc_l(unsigned int ch, enum eDI_SUM id) +{ + get_chdata(ch)->sum[id]++; + return get_chdata(ch)->sum[id]; +} + +static inline unsigned int di_sum_get_l(unsigned int ch, enum eDI_SUM id) +{ + return get_chdata(ch)->sum[id]; +} + +/*sum get and put*/ +static inline unsigned int get_sum_g(unsigned int ch) +{ + return get_datal()->ch_data[ch].sum_get; +} + +static inline void sum_g_inc(unsigned int ch) +{ + get_datal()->ch_data[ch].sum_get++; +} + +static inline void sum_g_clear(unsigned int ch) +{ + get_datal()->ch_data[ch].sum_get = 0; +} + +static inline unsigned int get_sum_p(unsigned int ch) +{ + return get_datal()->ch_data[ch].sum_put; +} + +static inline void sum_p_inc(unsigned int ch) +{ + get_datal()->ch_data[ch].sum_put++; +} + +static inline void sum_p_clear(unsigned int ch) +{ + get_datal()->ch_data[ch].sum_put = 0; +} + +/*bypass_state*/ +static inline bool di_bypass_state_get(unsigned int ch) +{ + return get_chdata(ch)->bypass_state; +} + +static inline void di_bypass_state_set(unsigned int ch, bool on) +{ + get_chdata(ch)->bypass_state = on; +} + +#if 0 +static inline struct semaphore *get_sema(void) +{ + return &get_dim_de_devp()->sema; +} +#endif + +static inline struct di_task *get_task(void) +{ + return &get_bufmng()->tsk; +} + +/****************************************** + * pq ops + *****************************************/ + +static inline const struct pulldown_op_s *get_ops_pd(void) +{ + return get_datal()->ops_pd; +} + +static inline const struct detect3d_op_s *get_ops_3d(void) +{ + return get_datal()->ops_3d; +} + +static inline const struct nr_op_s *get_ops_nr(void) +{ + return get_datal()->ops_nr; +} + +static inline const struct mtn_op_s *get_ops_mtn(void) +{ + return get_datal()->ops_mtn; +} + +#if 0 +static inline struct di_ext_ops *get_ops_api(void) +{ + return get_datal()->di_api; +} +#endif + +/****************************************** + * module para for di + *****************************************/ + +static inline int dimp_get(enum eDI_MP_UI_T idx) +{ + return get_datal()->mp_uit[idx]; +} + +static inline void dimp_set(enum eDI_MP_UI_T idx, int val) +{ + get_datal()->mp_uit[idx] = val; +} + +static inline int dimp_inc(enum eDI_MP_UI_T idx) +{ + get_datal()->mp_uit[idx]++; + return get_datal()->mp_uit[idx]; +} + +static inline int dimp_dec(enum eDI_MP_UI_T idx) +{ + get_datal()->mp_uit[idx]--; + return get_datal()->mp_uit[idx]; +} + +#define di_mpr(x) dimp_get(edi_mp_##x) + +/****************************************** + * mm + *****************************************/ +static inline struct di_mm_s *dim_mm_get(void) +{ + return &get_datal()->mng.mm; +} + +/**/ +void di_tout_int(struct di_time_out_s *tout, unsigned int thd); +bool di_tout_contr(enum eDI_TOUT_CONTR cmd, struct di_time_out_s *tout); + +#endif /*__DI_DATA_L_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_dbg.c b/drivers/amlogic/media/di_multi/di_dbg.c new file mode 100644 index 000000000000..e2c23d386f3a --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_dbg.c @@ -0,0 +1,1641 @@ +/* + * drivers/amlogic/media/di_multi/di_dbg.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include + +#include "di_data.h" +#include "di_dbg.h" + +#include "di_reg_tab.h" +#include "deinterlace.h" +#include "deinterlace_dbg.h" +#include "deinterlace_hw.h" +#include "di_data_l.h" +#include "di_que.h" +#include "di_task.h" +#include "di_prc.h" +#include "di_pre.h" +#include "di_post.h" + +/******************************** + *trace: + *******************************/ +#define CREATE_TRACE_POINTS +#include "dim_trace.h" + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE dim_trace +#include + +/**********************/ +/* data get */ +static struct dentry **dich_get_dbgroot(unsigned int ch) +{ + return &get_datal()->ch_data[ch].dbg_rootx; +} + +static struct dentry **dich_get_dbgroot_top(void) +{ + return &get_datal()->dbg_root_top; +} + +static int *di_get_plane(void) +{ + return &get_datal()->plane[0]; +} + +static struct vframe_s *di_get_dbg_vframe_in(unsigned int ch) +{ + return &get_datal()->ch_data[ch].dbg_data.vfm_input; +} + +static struct vframe_s **di_get_dbg_vframe_out(unsigned int ch) +{ + return &get_datal()->ch_data[ch].dbg_data.pfm_out; +} + +/******************************** + *timer: + *******************************/ + +u64 cur_to_msecs(void) +{ + u64 cur = sched_clock(); + + do_div(cur, NSEC_PER_MSEC); + return cur; +} + +u64 cur_to_usecs(void)/*2019*/ +{ + u64 cur = sched_clock(); + + do_div(cur, NSEC_PER_USEC); + return cur; +} + +/******************************** + *trace: + *******************************/ + +static void trace_pre(unsigned int index, unsigned long ctime) +{ + trace_dim_pre("PRE-IRQ-0", index, ctime); +} + +static void trace_post(unsigned int index, unsigned long ctime) +{ + trace_dim_post("POST-IRQ-1", index, ctime); +} + +#define DI_TRACE_LIMIT 8 +static void trace_pre_get(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pre_getxx("PRE-GET-01", index, ustime); +} + +static void trace_pre_set(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pre_setxx("PRE-SET-01", index, ustime); +} + +static void trace_pre_ready(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pre_ready("PRE-READY2", index, ustime); +} + +static void trace_post_ready(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_ready("PST-READY3", index, ustime); +} + +static void trace_post_get(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_getxx("PST-GET-04", index, ustime); +} + +static void trace_post_get2(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_get2x("PST-GET-0a", index, ustime); +} + +static void trace_post_set(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_setxx("PST-SET-05", index, ustime); +} + +static void trace_post_irq(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_irxxx("PST-IRQ-06", index, ustime); +} + +static void trace_post_doing(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_doing("PST-DOI-07", index, ustime); +} + +static void trace_post_peek(unsigned int index) +{ + u64 ustime; + + if (di_get_disp_cnt() > DI_TRACE_LIMIT) + return; + + ustime = cur_to_usecs(); + trace_dim_pst_peekx("PST-PEEK-8", index, ustime); +} + +const struct dim_tr_ops_s dim_tr_ops = { + .pre = trace_pre, + .post = trace_post, + + .pre_get = trace_pre_get, + .pre_set = trace_pre_set, + .pre_ready = trace_pre_ready, + .post_ready = trace_post_ready, + .post_get = trace_post_get, + .post_get2 = trace_post_get2, + + .post_set = trace_post_set, + .post_ir = trace_post_irq, + .post_do = trace_post_doing, + .post_peek = trace_post_peek, +}; + +static unsigned int seq_get_channel(struct seq_file *s) +{ + int *pCh; + + pCh = (int *)s->private; + return *pCh; +} + +/******************************** + *debug register: + *******************************/ +/* also see enum eDI_DBG_MOD */ +const char * const dbg_mode_name[] = { + "REGB", + "REGE", + "UNREGB", + "UNREGE", + "PRE_SETB", + "PRE_SETE", + "PRE_DONEB", + "PRE_DONEE", + "PST_SETB", + "PST_SETE", + "PST_IRQB", + "PST_IRQE", + "PST_DB", + "PST_DE", + "PST_CH_CHG", + "PST_TOUT", + "RVB", + "RVE", + "PST_RESIZE", +}; + +const char *ddbg_get_mod_name(unsigned int mod) +{ + if (mod >= eDI_DBG_MOD_END) + return "nothing!"; + + return dbg_mode_name[mod]; +} + +void ddbg_reg_save(unsigned int addr, unsigned int val, + unsigned int st, unsigned int bw) +{ + struct di_dbg_reg dbg_reg; + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + unsigned int pos; + + if (!plog->en_reg) + return; + if (plog->en_notoverwrite && plog->overflow) + return; + + pos = plog->pos; + + dbg_reg.addr = addr; + dbg_reg.val = val; + dbg_reg.st_bit = st; + dbg_reg.b_w = bw; + dbg_reg.res = 0; + + plog->log[pos].reg = dbg_reg; + pos++; + if (pos >= (K_DI_SIZE_REG_LOG - 1)) { + if (plog->en_notoverwrite) { + plog->overflow = 1; + + } else { + pos = 0; + plog->overflow = 1; + } + } + plog->wsize++; + plog->pos = pos; +} + +void dim_ddbg_mod_save(unsigned int mod, unsigned int ch, unsigned int cnt) +{ + struct di_dbg_mod dbg_mod; + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + unsigned int pos; +#if 1 +/*--------------------------*/ + if (ch) + h_dbg_reg_set(mod | 0x80000000); + else + h_dbg_reg_set(mod); +/*--------------------------*/ +#endif + if (!plog->en_mod) + return; + if (plog->en_notoverwrite && plog->overflow) + return; + pos = plog->pos; + + dbg_mod.lable = K_DI_LAB_MOD; + dbg_mod.ch = ch; + dbg_mod.mod = mod; + dbg_mod.cnt = cnt; + dbg_mod.res = 0; + + plog->log[pos].mod = dbg_mod; + pos++; + if (pos >= (K_DI_SIZE_REG_LOG - 1)) { + if (plog->en_notoverwrite) { + plog->overflow = 1; + + } else { + pos = 0; + plog->overflow = 1; + } + } + plog->wsize++; + plog->pos = pos; +} + +#if 0 +void ddbg_sw(bool on) +{ + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + + plog->en = on; +} +#else + +void ddbg_sw(enum eDI_LOG_TYPE mode, bool on) +{ + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + + switch (mode) { + case eDI_LOG_TYPE_ALL: + plog->en_all = on; + break; + case eDI_LOG_TYPE_REG: + plog->en_reg = on; + break; + case eDI_LOG_TYPE_MOD: + plog->en_mod = on; + break; + default: + PR_WARN("%s:mode overlow:%d\n", __func__, mode); + break; + } +} +#endif +void ddbg_reg_clear(void) +{ + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + + memset(plog, 0, sizeof(struct di_dbg_reg_log)); + plog->en_notoverwrite = 1; +} + +static int ddbg_log_reg_show(struct seq_file *seq, void *v) +{ + struct di_dbg_reg_log *plog = get_dbg_reg_log(); + unsigned int pos; + int i; + + if (plog->overflow) + pos = K_DI_SIZE_REG_LOG; + else + pos = plog->pos; + + seq_printf(seq, "%s:pos=%d,overflow=%d, size=%d\n", + __func__, plog->pos, plog->overflow, plog->wsize); + + for (i = 0; i < pos; i++) { + if (plog->log[i].mod.lable == K_DI_LAB_MOD) { + seq_printf(seq, "%d,ch[%d]:cnt[%d]:%s\n", + i, + plog->log[i].mod.ch, + plog->log[i].mod.cnt, + ddbg_get_mod_name(plog->log[i].mod.mod)); + continue; + } + + seq_printf(seq, "\t0x%x,0x%x,%d,%d\n", + plog->log[i].reg.addr, + plog->log[i].reg.val, + plog->log[i].reg.st_bit, + plog->log[i].reg.b_w); + } + + return 0; +} + +static ssize_t ddbg_log_reg_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, val; + char buf[80]; + int ret; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + switch (ret) { + case 2: + if (item == 0 && val == 0) { + /*help info:*/ + pr_info("help:\n"); + /*all:*/ + pr_info("\t1 0 : log all disable\n"); + pr_info("\t1 1 : log all enable\n"); + /*reg:*/ + pr_info("\t2 0 : log reg disable\n"); + pr_info("\t2 1 : log reg enable\n"); + /*mod:*/ + pr_info("\t3 0 : log mod disable\n"); + pr_info("\t3 1 : log mod enable\n"); + /*clean:*/ + pr_info("\t4 0 : clear\n"); + break; + } + switch (item) { + case 1: + case 2: + case 3: + pr_info("ddbg_sw: %d\n", val); + ddbg_sw(item, val); + break; + case 4: + pr_info("ddbg_reg_clear\n"); + ddbg_reg_clear(); + break; + }; + + break; + default: + pr_info("err:please enter: 0 x for help\n"); + return -EINVAL; + } + + return count; +} + +/**********************/ +static int seq_file_vframe(struct seq_file *seq, void *v, struct vframe_s *pVfm) +{ + if (!pVfm) { + seq_puts(seq, "war: dump vframe NULL\n"); + return 0; + } + seq_printf(seq, "%-15s:0x%p\n", "addr", pVfm); + seq_printf(seq, "%-15s:%d\n", "index", pVfm->index); + seq_printf(seq, "%-15s:%d\n", "index_disp", pVfm->index_disp); + seq_printf(seq, "%-15s:%d\n", "omx_index", pVfm->omx_index); + seq_printf(seq, "%-15s:0x%x\n", "type", pVfm->type); + seq_printf(seq, "%-15s:0x%x\n", "type_backup", pVfm->type_backup); + seq_printf(seq, "%-15s:0x%x\n", "type_original", pVfm->type_original); + seq_printf(seq, "%-15s:%d\n", "blend_mode", pVfm->blend_mode); + seq_printf(seq, "%-15s:%d\n", "duration", pVfm->duration); + seq_printf(seq, "%-15s:%d\n", "duration_pull", pVfm->duration_pulldown); + seq_printf(seq, "%-15s:%d\n", "pts", pVfm->pts); + + seq_printf(seq, "%-15s:%lld\n", "pts_us64", pVfm->pts_us64); + seq_printf(seq, "%-15s:%d\n", "next_vf_pts_valid", + pVfm->next_vf_pts_valid); + seq_printf(seq, "%-15s:%d\n", "next_vf_pts", pVfm->next_vf_pts); + seq_printf(seq, "%-15s:%d\n", "disp_pts", pVfm->disp_pts); + seq_printf(seq, "%-15s:%lld\n", "disp_pts_us64", pVfm->disp_pts_us64); + seq_printf(seq, "%-15s:%lld\n", "timestamp", pVfm->timestamp); + seq_printf(seq, "%-15s:%d\n", "flag", pVfm->flag); + seq_printf(seq, "%-15s:0x%x\n", "canvas0Addr", pVfm->canvas0Addr); + seq_printf(seq, "%-15s:0x%x\n", "canvas1Addr", pVfm->canvas1Addr); + seq_printf(seq, "%-15s:0x%x\n", "compHeadAddr", pVfm->compHeadAddr); + seq_printf(seq, "%-15s:0x%x\n", "compBodyAddr", pVfm->compBodyAddr); + seq_printf(seq, "%-15s:%d\n", "plane_num", pVfm->plane_num); + + seq_printf(seq, "%-15s:%d\n", "bufWidth", pVfm->bufWidth); + seq_printf(seq, "%-15s:%d\n", "width", pVfm->width); + seq_printf(seq, "%-15s:%d\n", "height", pVfm->height); + seq_printf(seq, "%-15s:%d\n", "compWidth", pVfm->compWidth); + seq_printf(seq, "%-15s:%d\n", "compHeight", pVfm->compHeight); + seq_printf(seq, "%-15s:%d\n", "ratio_control", pVfm->ratio_control); + seq_printf(seq, "%-15s:%d\n", "bitdepth", pVfm->bitdepth); + seq_printf(seq, "%-15s:%d\n", "signal_type", pVfm->signal_type); + + /* + * bit 29: present_flag + * bit 28-26: video_format + * "component", "PAL", "NTSC", "SECAM", + * "MAC", "unspecified" + * bit 25: range "limited", "full_range" + * bit 24: color_description_present_flag + * bit 23-16: color_primaries + * "unknown", "bt709", "undef", "bt601", + * "bt470m", "bt470bg", "smpte170m", "smpte240m", + * "film", "bt2020" + * bit 15-8: transfer_characteristic + * "unknown", "bt709", "undef", "bt601", + * "bt470m", "bt470bg", "smpte170m", "smpte240m", + * "linear", "log100", "log316", "iec61966-2-4", + * "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", + * "smpte-st-2084", "smpte-st-428" + * bit 7-0: matrix_coefficient + * "GBR", "bt709", "undef", "bt601", + * "fcc", "bt470bg", "smpte170m", "smpte240m", + * "YCgCo", "bt2020nc", "bt2020c" + */ + seq_printf(seq, "%-15s:0x%x\n", "orientation", pVfm->orientation); + seq_printf(seq, "%-15s:0x%x\n", "video_angle", pVfm->video_angle); + seq_printf(seq, "%-15s:0x%x\n", "source_type", pVfm->source_type); + + seq_printf(seq, "%-15s:0x%x\n", "phase", pVfm->phase); + seq_printf(seq, "%-15s:0x%x\n", "source_mode", pVfm->source_mode); + seq_printf(seq, "%-15s:0x%x\n", "sig_fmt", pVfm->sig_fmt); + seq_printf(seq, "%-15s:0x%x\n", "trans_fmt", pVfm->trans_fmt); + + seq_printf(seq, "%-15s:0x%x\n", "mode_3d_enable", + pVfm->mode_3d_enable); + + seq_printf(seq, "%-15s:0x%p\n", "early_process_fun", + pVfm->early_process_fun); + seq_printf(seq, "%-15s:0x%p\n", "process_fun", + pVfm->early_process_fun); + seq_printf(seq, "%-15s:0x%p\n", "private_data", + pVfm->early_process_fun); + +#if 1 + /* vframe properties */ + +#endif + + /* pixel aspect ratio */ + seq_printf(seq, "%-15s:%d\n", "pixel_ratio", pVfm->pixel_ratio); + + /* ready from decode on jiffies_64 */ + seq_printf(seq, "%-15s:%d\n", "use_cnt", atomic_read(&pVfm->use_cnt)); + seq_printf(seq, "%-15s:%d\n", "frame_dirty", pVfm->frame_dirty); + /* + *prog_proc_config: + *1: process p from decoder as filed + *0: process p from decoder as frame + */ + seq_printf(seq, "%-15s:0x%x\n", "prog_proc_config", + pVfm->prog_proc_config); + /* used for indicate current video is motion or static */ + seq_printf(seq, "%-15s:%d\n", "combing_cur_lev", + pVfm->combing_cur_lev); + return 0; +} + +/**********************/ +/* debug input vframe */ +/**********************/ +void didbg_vframe_in_copy(unsigned int ch, struct vframe_s *pvfm) +{ + struct vframe_s *pvfm_t; + + if (!di_cfgx_get(ch, eDI_DBG_CFGX_IDX_VFM_IN)) + return; + + pvfm_t = di_get_dbg_vframe_in(ch); + + memcpy(pvfm_t, pvfm, sizeof(struct vframe_s)); +} + +static int seq_file_vframe_in_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + + ch = seq_get_channel(seq); + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + + if (!di_cfgx_get(ch, eDI_DBG_CFGX_IDX_VFM_IN)) { + seq_puts(seq, "war: cfg[eDI_DBG_CFGX_IDX_VFM_IN] disable\n"); + return 0; + } + + seq_file_vframe(seq, v, di_get_dbg_vframe_in(ch)); + + return 0; +} + +/***********************/ +/* debug output vframe */ +/***********************/ +void didbg_vframe_out_save(struct vframe_s *pvfm) +{ + unsigned int ch; + struct vframe_s **pvfm_t; + + ch = DI_SUB_ID_S0; + if (!di_cfgx_get(ch, eDI_DBG_CFGX_IDX_VFM_OT)) + return; + + pvfm_t = di_get_dbg_vframe_out(ch); + *pvfm_t = pvfm; +} + +static int seq_file_vframe_out_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + + ch = seq_get_channel(seq); + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + + if (!di_cfgx_get(ch, eDI_DBG_CFGX_IDX_VFM_OT)) { + seq_puts(seq, "war: cfg[eDI_DBG_CFGX_IDX_VFM_OT] disable\n"); + return 0; + } + + seq_file_vframe(seq, v, *di_get_dbg_vframe_out(ch)); + + return 0; +} + +/**********************/ +/* debug vframe type */ +/**********************/ +const struct di_vframe_type_info di_vtype_info[] = { + {"interlace", VIDTYPE_INTERLACE, NULL}, + {"bottom", VIDTYPE_INTERLACE_BOTTOM, NULL}, + + {"interllace first", VIDTYPE_INTERLACE_FIRST, NULL}, + {"mvc", VIDTYPE_MVC, NULL}, + {"no video en", VIDTYPE_NO_VIDEO_ENABLE, NULL}, + {"v422", VIDTYPE_VIU_422, NULL}, + {"field", VIDTYPE_VIU_FIELD, NULL}, + + {"single plane", VIDTYPE_VIU_SINGLE_PLANE, NULL}, + {"v444", VIDTYPE_VIU_444, NULL}, + {"nv21", VIDTYPE_VIU_NV21, NULL}, + {"vscale disable", VIDTYPE_VSCALE_DISABLE, NULL}, + {"cvs toggle", VIDTYPE_CANVAS_TOGGLE, NULL}, + {"pre interlace", VIDTYPE_PRE_INTERLACE, NULL}, + {"high run", VIDTYPE_HIGHRUN, NULL}, + {"compress", VIDTYPE_COMPRESS, NULL}, + {"pic", VIDTYPE_PIC, NULL}, + {"scatter", VIDTYPE_SCATTER, NULL}, + {"vd2", VIDTYPE_VD2, NULL}, + {"compress loss", VIDTYPE_COMPRESS_LOSS, NULL}, + {"comb", VIDTYPE_COMB_MODE, NULL}, + {"tb detect", TB_DETECT_MASK, NULL}, + + /*finish*/ + {NULL, TABLE_FLG_END, NULL}, +}; + +static void didbg_vtype_set(unsigned int type) +{ + get_datal()->dbg_data.vframe_type = type; +} + +static unsigned int didbg_vtype_get(void) +{ + return get_datal()->dbg_data.vframe_type; +} + +static int seq_file_vtype_show(struct seq_file *seq, void *v) +{ + unsigned int vtype; + int i; + unsigned int mask; + + i = 0; + vtype = didbg_vtype_get(); + + seq_printf(seq, "%s:vtype[0x%x]\n", __func__, vtype); + + while (di_vtype_info[i].name) { + mask = di_vtype_info[i].mask; + + if ((vtype & mask) == mask) { + seq_printf(seq, "\t%-15s:y\n", di_vtype_info[i].name); + } else { + if (di_vtype_info[i].other) { + seq_printf(seq, "\t%-15s:yes\n", + di_vtype_info[i].other); + } else { + seq_printf(seq, "\t%-15s:no\n", + di_vtype_info[i].name); + } + } + i++; + } + + return 0; +} + +ssize_t seq_file_vtype_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + char buf[20]; + int ret; + + unsigned int vtype; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + /*reg, bit, width, val*/ + #if 1 + ret = kstrtouint(buf, 0, &vtype); + if (ret) { + pr_info("war:please enter vtype\n"); + return 0; + } + pr_info("save type:0x%x", vtype); + didbg_vtype_set(vtype); + #else + + ret = sscanfxxx(buf, "%x", &vtype); + + /*--------------------------*/ + + switch (ret) { + case 1: + pr_info("save type:0x%x", vtype); + didbg_vtype_set(vtype); + break; + default: + pr_info("war:please enter vtype\n"); + break; + } + #endif + return count; +} + +/************************************** + * + * show vframe current + * + **************************************/ +static int seq_file_curr_vframe_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + struct di_buf_s *p = NULL; + struct vframe_s *pvfm; + char *splt = "---------------------------"; + char *splt2 = "-------------"; + int itmp; + unsigned int tmpa[MAX_FIFO_SIZE]; + unsigned int psize; + + ch = seq_get_channel(seq); + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* post_doing_list */ + /********************************/ + seq_puts(seq, "vfm for: post_doing_list:\n"); + queue_for_each_entry(p, ch, QUEUE_POST_DOING, list) { + pvfm = p->vframe; + seq_file_vframe(seq, v, pvfm); + seq_printf(seq, "%s\n", splt2); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* pre_ready_list */ + /********************************/ + seq_puts(seq, "pre_ready_list:\n"); + di_que_list(ch, QUE_PRE_READY, &tmpa[0], &psize); + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(ch, tmpa[itmp]); + + pvfm = p->vframe; + seq_file_vframe(seq, v, pvfm); + seq_printf(seq, "%s\n", splt2); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* post_ready_list */ + /********************************/ + di_que_list(ch, QUE_POST_READY, &tmpa[0], &psize); + seq_printf(seq, "post_ready_list: curr(%d)\n", psize); + + for (itmp = 0; itmp < psize; itmp++) { + p = pw_qindex_2_buf(ch, tmpa[itmp]); + pvfm = p->vframe; + seq_file_vframe(seq, v, pvfm); + seq_printf(seq, "%s\n", splt2); + } + seq_printf(seq, "%s\n", splt); + + /********************************/ + /* display_list */ + /********************************/ + seq_puts(seq, "display_list:\n"); + queue_for_each_entry(p, ch, QUEUE_DISPLAY, list) { + pvfm = p->vframe; + seq_file_vframe(seq, v, pvfm); + seq_printf(seq, "%s\n", splt2); + } + seq_printf(seq, "%s\n", splt); + + return 0; +} + +/************************************** + * + * summmary variable + * + **************************************/ +static int seq_file_sum_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + char *sname; + unsigned int val; + unsigned int tsize; + int i; + + ch = seq_get_channel(seq); + + tsize = di_sum_get_tab_size();/*ARRAY_SIZE(di_sum_tab);*/ + + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + for (i = 0; i < tsize; i++) { + if (!di_sum_check(ch, i)) + continue; + di_sum_get_info(ch, i, &sname, &val); + seq_printf(seq, "\t%-2d:%-15s:%d\n", i, sname, val); + } + + seq_printf(seq, "%s:finish\n", __func__); + + return 0; +} + +/********************************/ +/* state */ +/********************************/ + +static int seq_file_state_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + + ch = seq_get_channel(seq); + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + + dim_state_show(seq, v, ch); + + return 0; +} + +static int seq_file_mif_show(struct seq_file *seq, void *v) +{ + unsigned int ch; + + ch = seq_get_channel(seq); + seq_printf(seq, "%s:ch[%d]\n", __func__, ch); + + dim_dump_mif_size_state_show(seq, v, ch); + + return 0; +} + +/********************************/ +#define DEFINE_SEQ_SHOW_ONLY(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +/*--------------------------*/ +#if 1 +/*note: this define can't used for x*/ +#define DEFINE_SEQ_SHOW_STORE(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .write = __name ## _store, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} +#endif +/*--------------------------*/ +#define DEFINE_SHOW_STORE(__name) \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = simple_open, \ + .read = __name ## _show, \ + .write = __name ## _store, \ +} + +/*--------------------------*/ +#define DEFINE_STORE_ONLY(__name) \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = simple_open, \ + .read = NULL, \ + .write = __name ## _store, \ +} + +/**********************/ + +static int rcfgx_show(struct seq_file *s, void *what) +{ + int i; + int *pCh; + + pCh = (int *)s->private; + + seq_printf(s, "%s:ch[%d]\n", __func__, *pCh); + + for (i = eDI_CFGX_BEGIN; i < eDI_DBG_CFGX_END; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", i, + di_cfgx_get_name(i), + di_cfgx_get(*pCh, i)); + } + + return 0; +} + +/*************************************************************/ +static ssize_t wcfgx_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, val; + char buf[80]; + int ret; + int *pCh; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pCh = (int *)file->private_data; + pr_info("%s:ch[%d]\n", __func__, *pCh); + + switch (ret) { + case 2: + if ((item <= eDI_CFGX_BEGIN) || + (item >= eDI_DBG_CFGX_END)) { + pr_info("war:cfg_item is overflow[%d,%d]:%d\n", + eDI_CFGX_BEGIN, + eDI_DBG_CFGX_END, + item); + break; + } + if (val > 1) + pr_info("war:cfg value[%d] is not bool\n", val); + + pr_info("change cfg:%s\n", di_cfgx_get_name(item)); + pr_info("\t%d -> %d\n", di_cfgx_get(*pCh, item), val); + di_cfgx_set(*pCh, item, val); + break; + default: + pr_info("err:please enter: cfg_item, value(bool)\n"); + return -EINVAL; + } + + return count; +} + +/*************************************************************** + * parameter show and store for top : DI + **************************************************************/ +static int mpr_di_show(struct seq_file *s, void *what) +{ + int i; + + seq_printf(s, "%s:\n", __func__); + + for (i = eDI_MP_SUB_DI_B; i < eDI_MP_SUB_DI_E; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", + i - eDI_MP_SUB_DI_B, + di_mp_uit_get_name(i), + di_mp_uit_get(i)); + } + + return 0; +} + +static ssize_t mpw_di_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, rid; + char buf[80]; + int ret, val; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pr_info("%s:\n", __func__); + + switch (ret) { + case 2: + /*check []*/ + if (item >= (eDI_MP_SUB_DI_E - eDI_MP_SUB_DI_B)) { + PR_WARN("index is overflow[%d,%d]:%d\n", + 0, + eDI_MP_SUB_DI_E - eDI_MP_SUB_DI_B, + item); + break; + } + rid = item + eDI_MP_SUB_DI_B; + pr_info("change mp :%s\n", + di_mp_uit_get_name(rid)); + pr_info("\t%d -> %d\n", di_mp_uit_get(rid), val); + di_mp_uit_set(rid, val); + break; + default: + PR_ERR("please enter: id, value(int)\n"); + return -EINVAL; + } + + return count; +} + +/*************************************************************** + * parameter show and store for top : nr + **************************************************************/ +static int mpr_nr_show(struct seq_file *s, void *what) +{ + int i; + + seq_printf(s, "%s:\n", __func__); + + for (i = eDI_MP_SUB_NR_B; i < eDI_MP_SUB_NR_E; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", + i - eDI_MP_SUB_NR_B, + di_mp_uit_get_name(i), + di_mp_uit_get(i)); + } + + return 0; +} + +static ssize_t mpw_nr_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, rid; + char buf[80]; + int ret, val; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pr_info("%s:\n", __func__); + + switch (ret) { + case 2: + /*check []*/ + if (item >= (eDI_MP_SUB_NR_E - eDI_MP_SUB_NR_B)) { + PR_WARN("index is overflow[%d,%d]:%d\n", + 0, + eDI_MP_SUB_NR_E - eDI_MP_SUB_NR_B, + item); + break; + } + rid = item + eDI_MP_SUB_NR_B; + pr_info("change mp:%s\n", + di_mp_uit_get_name(rid)); + pr_info("\t%d -> %d\n", di_mp_uit_get(rid), val); + di_mp_uit_set(rid, val); + break; + default: + PR_ERR("please enter: id, value(int)\n"); + return -EINVAL; + } + + return count; +} + +/*************************************************************** + * parameter show and store for top : pulldown + **************************************************************/ +static int mpr_pd_show(struct seq_file *s, void *what) +{ + int i; + + seq_printf(s, "%s:\n", __func__); + + for (i = eDI_MP_SUB_PD_B; i < eDI_MP_SUB_PD_E; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", + i - eDI_MP_SUB_PD_B, + di_mp_uit_get_name(i), + di_mp_uit_get(i)); + } + + return 0; +} + +static ssize_t mpw_pd_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, rid; + char buf[80]; + int ret, val; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pr_info("%s:\n", __func__); + + switch (ret) { + case 2: + /*check []*/ + if (item >= (eDI_MP_SUB_PD_E - eDI_MP_SUB_PD_B)) { + PR_WARN("index is overflow[%d,%d]:%d\n", + 0, + eDI_MP_SUB_PD_E - eDI_MP_SUB_PD_B, + item); + break; + } + rid = item + eDI_MP_SUB_PD_B; + pr_info("change mp:%s\n", + di_mp_uit_get_name(rid)); + pr_info("\t%d -> %d\n", di_mp_uit_get(rid), val); + di_mp_uit_set(rid, val); + break; + default: + PR_ERR("please enter: id, value(int)\n"); + return -EINVAL; + } + + return count; +} + +/*************************************************************** + * parameter show and store for top : mtn + **************************************************************/ +static int mpr_mtn_show(struct seq_file *s, void *what) +{ + int i; + + seq_printf(s, "%s:\n", __func__); + + for (i = eDI_MP_SUB_MTN_B; i < eDI_MP_SUB_MTN_E; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", + i - eDI_MP_SUB_MTN_B, + di_mp_uit_get_name(i), + di_mp_uit_get(i)); + } + + return 0; +} + +static ssize_t mpw_mtn_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, rid; + char buf[80]; + int ret, val; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pr_info("%s:\n", __func__); + + switch (ret) { + case 2: + /*check []*/ + if (item >= (eDI_MP_SUB_MTN_E - eDI_MP_SUB_MTN_B)) { + PR_WARN("index is overflow[%d,%d]:%d\n", + 0, + eDI_MP_SUB_MTN_E - eDI_MP_SUB_MTN_B, + item); + break; + } + rid = item + eDI_MP_SUB_MTN_B; + pr_info("change mp:%s\n", + di_mp_uit_get_name(rid)); + pr_info("\t%d -> %d\n", di_mp_uit_get(rid), val); + di_mp_uit_set(rid, val); + break; + default: + PR_ERR("please enter: id, value(int)\n"); + return -EINVAL; + } + + return count; +} + +/**********************/ +static int mpxr_show(struct seq_file *s, void *what) +{ + int i; + int *pCh; + + pCh = (int *)s->private; + + seq_printf(s, "%s:ch[%d]\n", __func__, *pCh); + + for (i = eDI_MP_UIX_BEGIN; i < eDI_MP_UIX_END; i++) { + seq_printf(s, "\tidx[%2d]:%-15s:%d\n", i, + di_mp_uix_get_name(i), + di_mp_uix_get(*pCh, i)); + } + + return 0; +} + +/*************************************************************/ +static ssize_t mpxw_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int item, val; + char buf[80]; + int ret; + int *pCh; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i", &item, &val); + + pCh = (int *)file->private_data; + pr_info("%s:ch[%d]\n", __func__, *pCh); + + switch (ret) { + case 2: + if ((item <= eDI_MP_UIX_BEGIN) || + (item >= eDI_MP_UIX_END)) { + PR_WARN("mpxw is overflow[%d,%d]:%d\n", + eDI_MP_UIX_BEGIN, + eDI_MP_UIX_END, + item); + break; + } + + pr_info("change mp ch[%d]:%s\n", *pCh, + di_mp_uix_get_name(item)); + pr_info("\t%d -> %d\n", di_mp_uix_get(*pCh, item), val); + di_mp_uix_set(*pCh, item, val); + break; + default: + PR_ERR("please enter: mpxw, value(unsigned int)\n"); + return -EINVAL; + } + + return count; +} + +static ssize_t buf_cnt_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + int w, h, pflg, mc; + char buf[80]; + int ret, cnt_flg; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %i %i %i", &w, &h, &pflg, &mc); + + pr_info("%s:\n", __func__); + cnt_flg = 0; + switch (ret) { + case 2: + cnt_flg = 1; + pflg = 0; + mc = 1; + break; + case 3: + cnt_flg = 1; + mc = 1; + break; + case 4: + cnt_flg = 1; + break; + default: + PR_ERR("please enter: w, h, pflg, mc\n"); + return -EINVAL; + } + + if (cnt_flg) + di_cnt_buf(w, h, pflg, mc, 1, 1); + return count; +} + +/**********************/ +void dbg_f_post_disable(unsigned int para) +{ + dimh_disable_post_deinterlace_2(); +} + +void dbg_f_trig_task(unsigned int para) +{ + task_send_ready(); +} + +const struct di_dbg_func_s di_func_tab[] = { + {eDI_DBG_F_00, dbg_f_post_disable, + "dimh_disable_post_deinterlace_2", "no para"}, + {eDI_DBG_F_01, dbg_f_trig_task, + "trig task", "no para"}, + {eDI_DBG_F_02, dpre_dbg_f_trig, + "trig pre flow debug", "bit[4]:ddebug on/off;bi[3:0]:cnt"}, + {eDI_DBG_F_03, dpst_dbg_f_trig, + "trig post flow debug", "bit[4]:ddebug on/off;bi[3:0]:cnt"}, + {eDI_DBG_F_04, hpst_dbg_power_ctr_trig, + "trig post power", "1: on; 0: off"}, + + {eDI_DBG_F_05, hpst_dbg_mem_pd_trig, + "trig post mem pd", "no para"}, + {eDI_DBG_F_06, hpst_dbg_trig_gate, + "trig post gate off/on", "no para"}, + {eDI_DBG_F_07, hpst_dbg_trig_mif, + "trig post mif off/free", "no para"}, +}; + +static ssize_t wfunc_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int findex, para; + char buf[20]; + int ret; + + int i; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%i %x", &findex, ¶); + + switch (ret) { + case 2: + pr_info("func:%d,para=0x%x\n", findex, para); + for (i = 0; i < ARRAY_SIZE(di_func_tab); i++) { + if (i == findex && di_func_tab[i].index == findex) { + if (di_func_tab[i].func) + di_func_tab[i].func(para); + pr_info("func:%s finish\n", + di_func_tab[i].name); + break; + } + } + break; + default: + pr_info("warn: please enter function index and para\n"); + return -EINVAL; + } + + return count; +} + +static int rfunc_show(struct seq_file *seq, void *v) +{ + int i; + + seq_puts(seq, "debug function list:\n"); + + for (i = 0; i < ARRAY_SIZE(di_func_tab); i++) { + if (di_func_tab[i].index != i) + seq_printf(seq, "warn: index(%d->%d) is not map\n", + i, di_func_tab[i].index); + seq_printf(seq, "index[%d]:%s:%s\n", + di_func_tab[i].index, + di_func_tab[i].name, + di_func_tab[i].info); + } + return 0; +} + +/**********************/ +static ssize_t reg_show(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char buf[80]; + + ssize_t len; + int *pInt; + + pInt = (int *)file->private_data; + pr_info("pInt=0x%p,val=%d\n", pInt, *pInt); + + len = snprintf(buf, sizeof(buf), "%s\n", + __func__); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static ssize_t reg_store(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + unsigned int reg, val; + char buf[80]; + int ret; + int *pInt; + + count = min_t(size_t, count, (sizeof(buf) - 1)); + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + buf[count] = 0; + + ret = sscanf(buf, "%x %i", ®, &val); + + switch (ret) { + case 1: + pr_info("reg:0x%x\n", reg); + + pInt = (int *)file->private_data; + pr_info("pInt=0x%p,val=%d\n", pInt, *pInt); + break; + case 2: + pr_info("reg:0x%x,val=%d\n", reg, val); + break; + default: + return -EINVAL; + } + + return count; +} + +/**********************/ +DEFINE_SEQ_SHOW_ONLY(dim_reg_cue_int); +/**********************/ +DEFINE_SEQ_SHOW_ONLY(rcfgx); +DEFINE_SEQ_SHOW_ONLY(seq_file_vframe_in); +DEFINE_SEQ_SHOW_ONLY(seq_file_vframe_out); +DEFINE_SEQ_SHOW_ONLY(seq_file_state); +DEFINE_SEQ_SHOW_ONLY(seq_file_mif); +DEFINE_SEQ_SHOW_ONLY(seq_file_sum); + +DEFINE_SEQ_SHOW_ONLY(reg_con); +DEFINE_SEQ_SHOW_ONLY(rfunc); +DEFINE_SEQ_SHOW_ONLY(mpxr); +DEFINE_SEQ_SHOW_ONLY(mpr_di); +DEFINE_SEQ_SHOW_ONLY(mpr_nr); +DEFINE_SEQ_SHOW_ONLY(mpr_pd); +DEFINE_SEQ_SHOW_ONLY(mpr_mtn); + +DEFINE_SEQ_SHOW_ONLY(seq_file_curr_vframe); + +DEFINE_STORE_ONLY(wcfgx); +DEFINE_STORE_ONLY(wfunc); +DEFINE_STORE_ONLY(mpxw); +DEFINE_STORE_ONLY(mpw_di); +DEFINE_STORE_ONLY(mpw_nr); +DEFINE_STORE_ONLY(mpw_pd); +DEFINE_STORE_ONLY(mpw_mtn); +DEFINE_STORE_ONLY(buf_cnt); + +DEFINE_SHOW_STORE(reg); + +DEFINE_SEQ_SHOW_STORE(seq_file_vtype); +DEFINE_SEQ_SHOW_STORE(ddbg_log_reg); + +/**********************/ + +struct di_dbgfs_files_t { + const char *name; + const umode_t mode; + const struct file_operations *fops; +}; + +static const struct di_dbgfs_files_t di_debugfs_files_top[] = { + {"vtype", S_IFREG | 0644, &seq_file_vtype_fops}, + {"reg_log", S_IFREG | 0644, &ddbg_log_reg_fops}, + {"regctr", S_IFREG | 0644, ®_con_fops}, + {"rfunc", S_IFREG | 0644, &rfunc_fops}, + {"wfunc", S_IFREG | 0644, &wfunc_fops}, + {"reg_cue", S_IFREG | 0644, &dim_reg_cue_int_fops}, + /*module parameter*/ + {"mr_di", S_IFREG | 0644, &mpr_di_fops}, + {"mw_di", S_IFREG | 0644, &mpw_di_fops}, + {"mr_nr", S_IFREG | 0644, &mpr_nr_fops}, + {"mw_nr", S_IFREG | 0644, &mpw_nr_fops}, + {"mr_pd", S_IFREG | 0644, &mpr_pd_fops}, + {"mw_pd", S_IFREG | 0644, &mpw_pd_fops}, + {"mr_mtn", S_IFREG | 0644, &mpr_mtn_fops}, + {"mw_mtn", S_IFREG | 0644, &mpw_mtn_fops}, + {"buf_cnt", S_IFREG | 0644, &buf_cnt_fops}, +}; + +static const struct di_dbgfs_files_t di_debugfs_files[] = { + {"rcfgx", S_IFREG | 0644, &rcfgx_fops}, + {"wcfgx", S_IFREG | 0644, &wcfgx_fops}, + {"rvfm_in", S_IFREG | 0644, &seq_file_vframe_in_fops}, + {"rvfm_out", S_IFREG | 0644, &seq_file_vframe_out_fops}, + {"state", S_IFREG | 0644, &seq_file_state_fops}, + {"dumpmif", S_IFREG | 0644, &seq_file_mif_fops}, + {"test_reg", S_IFREG | 0644, ®_fops}, + {"sum", S_IFREG | 0644, &seq_file_sum_fops}, + {"mpxr", S_IFREG | 0644, &mpxr_fops}, + {"mpxw", S_IFREG | 0644, &mpxw_fops}, + {"vfmc", S_IFREG | 0644, &seq_file_curr_vframe_fops}, +}; + +void didbg_fs_init(void) +{ + int i, j; + char name[5]; + /*char buf[3];*/ + + struct dentry **root_ent; + + struct dentry *ent; + int *pPlane = di_get_plane(); + + for (i = 0; i < DI_CHANNEL_NUB; i++) { +#if 0 + strcpy(name, "di"); + sprintf(buf, "%01d", i); + strncat(name, buf, sizeof(buf) - 1); +#endif + snprintf(name, sizeof(name), "di%01d", i); + root_ent = dich_get_dbgroot(i); + if (IS_ERR_OR_NULL(root_ent)) + continue; + *root_ent = debugfs_create_dir(name, NULL); + if (IS_ERR_OR_NULL(*root_ent)) + continue; + *(pPlane + i) = i; + /*printk("plane 0x%p\n", &plane_ch[i]);*/ + for (j = 0; j < ARRAY_SIZE(di_debugfs_files); j++) { + ent = debugfs_create_file(di_debugfs_files[j].name, + di_debugfs_files[j].mode, + *root_ent, (pPlane + i), + di_debugfs_files[j].fops); + if (!ent) + PR_ERR("debugfs create failed\n"); + } + } + /*top*/ + root_ent = dich_get_dbgroot_top(); + if (IS_ERR_OR_NULL(root_ent)) + return; + *root_ent = debugfs_create_dir("di_top", NULL); + if (IS_ERR_OR_NULL(*root_ent)) + return; + for (i = 0; i < ARRAY_SIZE(di_debugfs_files_top); i++) { + ent = debugfs_create_file(di_debugfs_files_top[i].name, + di_debugfs_files_top[i].mode, + *root_ent, NULL, + di_debugfs_files_top[i].fops); + if (!ent) + PR_ERR("debugfs top [%d]create failed\n", i); + } +} + +void didbg_fs_exit(void) +{ + struct dentry **root_ent; + int i; + + for (i = 0; i < DI_CHANNEL_NUB; i++) { + root_ent = dich_get_dbgroot(i); + debugfs_remove_recursive(*root_ent); + } + + /*top*/ + root_ent = dich_get_dbgroot_top(); + debugfs_remove_recursive(*root_ent); + + pr_info("%s:finish\n", __func__); +} + +/*-----------------------*/ + diff --git a/drivers/amlogic/media/di_multi/di_dbg.h b/drivers/amlogic/media/di_multi/di_dbg.h new file mode 100644 index 000000000000..6636f5af4d3f --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_dbg.h @@ -0,0 +1,69 @@ +/* + * drivers/amlogic/media/di_multi/di_dbg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_DBG_H__ +#define __DI_DBG_H__ + +#include +#include +#include + +void didbg_fs_init(void); +void didbg_fs_exit(void); + +void di_cfgx_init_val(void); + +void didbg_vframe_in_copy(unsigned int ch, struct vframe_s *pvfm); +void didbg_vframe_out_save(struct vframe_s *pvfm); + +/******************************** + *debug register: + *******************************/ +void ddbg_reg_save(unsigned int addr, unsigned int val, + unsigned int st, unsigned int bw); +void dim_ddbg_mod_save(unsigned int mod, + unsigned int ch, + unsigned int cnt); +void ddbg_sw(unsigned int mode, bool on); + +/******************************** + *time: + *******************************/ +u64 cur_to_msecs(void); +u64 cur_to_usecs(void); /*2019*/ + +/******************************** + *trace: + *******************************/ +struct dim_tr_ops_s { + void (*pre)(unsigned int index, unsigned long ctime); + void (*post)(unsigned int index, unsigned long ctime); + void (*pre_get)(unsigned int index); + void (*pre_set)(unsigned int index); + void (*pre_ready)(unsigned int index); + void (*post_ready)(unsigned int index); + void (*post_get)(unsigned int index); + void (*post_get2)(unsigned int index); + void (*post_set)(unsigned int index); + void (*post_ir)(unsigned int index); + void (*post_do)(unsigned int index); + void (*post_peek)(unsigned int index); +}; + +extern const struct dim_tr_ops_s dim_tr_ops; + +#endif /*__DI_DBG_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_post.c b/drivers/amlogic/media/di_multi/di_post.c new file mode 100644 index 000000000000..3451d2d1201c --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_post.c @@ -0,0 +1,389 @@ +/* + * drivers/amlogic/media/di_multi/di_post.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include +#include "deinterlace.h" +#include "deinterlace_dbg.h" + +#include "di_data_l.h" +#include "di_data.h" +#include "di_dbg.h" +#include "di_vframe.h" +#include "di_que.h" +#include "di_task.h" + +#include "di_prc.h" +#include "di_post.h" + +#include "nr_downscale.h" +#include "register.h" + +void dpost_clear(void)/*not been called*/ +{ + struct di_hpst_s *pst = get_hw_pst(); + + memset(pst, 0, sizeof(struct di_hpst_s)); +} + +void dpost_init(void) +{/*reg:*/ + struct di_hpst_s *pst = get_hw_pst(); + + pst->state = eDI_PST_ST_IDLE; + + /*timer out*/ + di_tout_int(&pst->tout, 40); /*ms*/ +} + +void pw_use_hw_post(enum eDI_SUB_ID channel, bool on) +{ + struct di_hpst_s *post = get_hw_pst(); + + post->hw_flg_busy_post = on; + if (on) + post->curr_ch = channel; +} + +static bool pw_try_sw_ch_next_post(enum eDI_SUB_ID channel) +{ + bool ret = false; + + struct di_hpst_s *post = get_hw_pst(); + enum eDI_SUB_ID lst_ch, nch; + + lst_ch = channel; + + nch = pw_ch_next_count(lst_ch); + if (!get_reg_flag(nch) || get_flag_trig_unreg(nch)) + return false; + + if (nch != channel) + dim_ddbg_mod_save(eDI_DBG_MOD_POST_CH_CHG, nch, 0);/*dbg*/ + + post->curr_ch = nch; + post->hw_flg_busy_post = true; + ret = true; + + /*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/ + return ret; +} + +/*****************************/ +/* debug */ +/*****************************/ + +/*****************************/ +/* STEP */ +/*****************************/ + +bool dpst_step_idle(void) +{ + struct di_hpst_s *pst = get_hw_pst(); + bool reflesh = false; + + if (!pw_try_sw_ch_next_post(pst->curr_ch)) + return false; + + pst->pres = get_pre_stru(pst->curr_ch); + pst->psts = get_post_stru(pst->curr_ch); + pst->state++;/*tmp*/ + reflesh = true; + + return reflesh; +} + +bool dpst_step_check(void) +{ + struct di_hpst_s *pst = get_hw_pst(); + unsigned int ch; + struct di_post_stru_s *ppost; + bool reflesh = false; + + ch = pst->curr_ch; + ppost = get_post_stru(ch); + + if (queue_empty(ch, QUEUE_POST_DOING)) { + ppost->post_peek_underflow++; + pst->state--; + return reflesh; + } + + pst->state++; + reflesh = true; + + return reflesh; +} + +bool dpst_step_set(void) +{ + struct di_buf_s *di_buf = NULL; + vframe_t *vf_p = NULL; + struct di_post_stru_s *ppost; + struct di_hpst_s *pst = get_hw_pst(); + unsigned int ch; + bool reflesh = false; + ulong flags = 0; + + ch = pst->curr_ch; + ppost = get_post_stru(ch); + + di_buf = get_di_buf_head(ch, QUEUE_POST_DOING); + if (dim_check_di_buf(di_buf, 20, ch)) { + PR_ERR("%s:err1\n", __func__); + return reflesh; + } + + vf_p = di_buf->vframe; + if (ppost->run_early_proc_fun_flag) { + if (vf_p->early_process_fun) + vf_p->early_process_fun = dim_do_post_wr_fun; + } + + dim_print("%s:pr_index=%d\n", __func__, di_buf->process_fun_index); + if (di_buf->process_fun_index) { /*not bypass?*/ + + ppost->post_wr_cnt++; + spin_lock_irqsave(&plist_lock, flags); + dim_post_process(di_buf, 0, vf_p->width - 1, + 0, vf_p->height - 1, vf_p); + spin_unlock_irqrestore(&plist_lock, flags); + + /*begin to count timer*/ + di_tout_contr(eDI_TOUT_CONTR_EN, &pst->tout); + + ppost->post_de_busy = 1; + ppost->irq_time = cur_to_msecs(); + + /*state*/ + pst->state++; + /*reflesh = true;*/ + } else { + ppost->de_post_process_done = 1; /*trig done*/ + pst->flg_int_done = 1; + + /*state*/ + pst->state++;/*pst->state = eDI_PST_ST_DONE;*/ + reflesh = true; + } + ppost->cur_post_buf = di_buf; + + return reflesh; +} + +bool dpst_step_wait_int(void) +{ + struct di_hpst_s *pst = get_hw_pst(); + unsigned int ch; + struct di_post_stru_s *ppost; + bool reflesh = false; + ulong flags = 0; + + ch = pst->curr_ch; + + dim_print("%s:ch[%d],done_flg[%d]\n", __func__, + pst->curr_ch, pst->flg_int_done); + if (pst->flg_int_done) { + /*finish to count timer*/ + di_tout_contr(eDI_TOUT_CONTR_FINISH, &pst->tout); + spin_lock_irqsave(&plist_lock, flags); + dim_post_de_done_buf_config(ch); + spin_unlock_irqrestore(&plist_lock, flags); + pst->flg_int_done = false; + /*state*/ + pst->state = eDI_PST_ST_IDLE; + reflesh = true; + } else { + /*check if timeout:*/ + if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pst->tout)) { + ppost = get_post_stru(ch); + PR_WARN("ch[%d]:post timeout[%d]\n", ch, + ppost->cur_post_buf->seq); + dim_ddbg_mod_save(eDI_DBG_MOD_POST_TIMEOUT, ch, 0); + /*state*/ + pst->state = eDI_PST_ST_TIMEOUT; + reflesh = true; + } + } + return reflesh; +} + +void dpst_timeout(unsigned int ch) +{ + hpst_dbg_mem_pd_trig(0); + post_close_new(); + #if 0 + di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP); + di_post_reset(); + #endif + dimh_pst_trig_resize(); +} + +bool dpst_step_timeout(void) +{ + struct di_hpst_s *pst = get_hw_pst(); + unsigned int ch; + bool reflesh = false; + ulong flags = 0; + + ch = pst->curr_ch; + dpst_timeout(ch); + spin_lock_irqsave(&plist_lock, flags); + dim_post_de_done_buf_config(ch); + spin_unlock_irqrestore(&plist_lock, flags); + pst->flg_int_done = false; + + /*state*/ + pst->state = eDI_PST_ST_IDLE; + reflesh = true; + + return reflesh; +} + +bool dpst_step_done(void)/*this step no use ?*/ +{ + struct di_hpst_s *pst = get_hw_pst(); + unsigned int ch; + bool reflesh = false; + + ch = pst->curr_ch; +/* dim_post_de_done_buf_config(ch);*/ + + /*state*/ + pst->state = eDI_PST_ST_IDLE; + reflesh = true; + + return reflesh; +} + +const struct di_func_tab_s di_pst_func_tab[] = { + {eDI_PST_ST_EXIT, NULL}, + {eDI_PST_ST_IDLE, dpst_step_idle}, + {eDI_PST_ST_CHECK, dpst_step_check}, + {eDI_PST_ST_SET, dpst_step_set}, + {eDI_PST_ST_WAIT_INT, dpst_step_wait_int}, + {eDI_PST_ST_TIMEOUT, dpst_step_timeout}, + {eDI_PST_ST_DONE, dpst_step_done}, +}; + +const char * const dpst_state_name[] = { + "EXIT", + "IDLE", /*swith to next channel?*/ + "CHECK", + "SET", + "WAIT_INT", + "TIMEOUT", + "DONE", +}; + +const char *dpst_state_name_get(enum eDI_PST_ST state) +{ + if (state > eDI_PST_ST_DONE) + return "nothing"; + + return dpst_state_name[state]; +} + +bool dpst_can_exit(unsigned int ch) +{ + struct di_hpst_s *pst = get_hw_pst(); + bool ret = false; + + if (ch != pst->curr_ch) { + ret = true; + } else { + if (pst->state <= eDI_PST_ST_IDLE) + ret = true; + } + pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n", + __func__, + ch, pst->curr_ch, + dpst_state_name_get(pst->state), + ret); + return ret; +} + +static bool dpst_process_step2(void) +{ + struct di_hpst_s *pst = get_hw_pst(); + enum eDI_PST_ST pst_st = pst->state; + unsigned int ch; + + ch = pst->curr_ch; + if (pst_st > eDI_PST_ST_EXIT) + dim_recycle_post_back(ch); + + if ((pst_st <= eDI_PST_ST_DONE) && + di_pst_func_tab[pst_st].func) + return di_pst_func_tab[pst_st].func(); + else + return false; +} + +void dpst_dbg_f_trig(unsigned int cmd) +{ + struct di_task *tsk = get_task(); + + struct di_hpst_s *pst = get_hw_pst(); + + if (down_interruptible(&tsk->sem)) { + PR_ERR("%s:can't get sem\n", __func__); + return; + } + + /*set on/off and trig*/ + if (cmd & 0x10) { + pst->dbg_f_en = 1; + pst->dbg_f_cnt = cmd & 0xf; + pst->dbg_f_lstate = pst->state; + } else { + pst->dbg_f_en = 0; + } + + up(&tsk->sem); +} + +void dpst_process(void) +{ + bool reflesh; + + struct di_hpst_s *pst = get_hw_pst(); + + if (pst->dbg_f_en) { + if (pst->dbg_f_cnt) { + dpst_process_step2(); + pst->dbg_f_cnt--; + } + if (pst->dbg_f_lstate != pst->state) { + pr_info("ch[%d]:state:%s->%s\n", + pst->curr_ch, + dpst_state_name_get(pst->dbg_f_lstate), + dpst_state_name_get(pst->state)); + + pst->dbg_f_lstate = pst->state; + } + return; + } + + reflesh = true; + + while (reflesh) + reflesh = dpst_process_step2(); +} diff --git a/drivers/amlogic/media/di_multi/di_post.h b/drivers/amlogic/media/di_multi/di_post.h new file mode 100644 index 000000000000..1b4d88dd011b --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_post.h @@ -0,0 +1,27 @@ +/* + * drivers/amlogic/media/di_multi/di_post.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_POST_H__ +#define __DI_POST_H__ + +void dpost_init(void); +void dpst_process(void); +const char *dpst_state_name_get(enum eDI_PST_ST state); +void dpst_dbg_f_trig(unsigned int cmd); +bool dpst_can_exit(unsigned int ch); + +#endif /*__DI_POST_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_pps.c b/drivers/amlogic/media/di_multi/di_pps.c new file mode 100644 index 000000000000..4f2094170038 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_pps.c @@ -0,0 +1,628 @@ +/* + * drivers/amlogic/media/di_multi/di_pps.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include "di_pps.h" +#include "register.h" + +#include + +#if 0 +/* pps filter coefficients */ +#define COEF_BICUBIC 0 +#define COEF_3POINT_TRIANGLE 1 +#define COEF_4POINT_TRIANGLE 2 +#define COEF_BILINEAR 3 +#define COEF_2POINT_BILINEAR 4 +#define COEF_BICUBIC_SHARP 5 +#define COEF_3POINT_TRIANGLE_SHARP 6 +#define COEF_3POINT_BSPLINE 7 +#define COEF_4POINT_BSPLINE 8 +#define COEF_3D_FILTER 9 +#define COEF_NULL 0xff +#define TOTAL_FILTERS 10 + +#define MAX_NONLINEAR_FACTOR 0x40 + +const u32 vpp_filter_coefs_bicubic_sharp[] = { + 3, + 33 | 0x8000, + /* 0x01f80090, 0x01f80100, 0xff7f0200, 0xfe7f0300, */ + 0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300, + 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900, + 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff, + 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, + 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd, + 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb, + 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, + 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9, + 0xf84848f8 +}; + +const u32 vpp_filter_coefs_bicubic[] = { + 4, + 33, + 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, + 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900, + 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff, + 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, + 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd, + 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb, + 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, + 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9, + 0xf84848f8 +}; + +const u32 vpp_filter_coefs_bilinear[] = { + 4, + 33, + 0x00800000, 0x007e0200, 0x007c0400, 0x007a0600, + 0x00780800, 0x00760a00, 0x00740c00, 0x00720e00, + 0x00701000, 0x006e1200, 0x006c1400, 0x006a1600, + 0x00681800, 0x00661a00, 0x00641c00, 0x00621e00, + 0x00602000, 0x005e2200, 0x005c2400, 0x005a2600, + 0x00582800, 0x00562a00, 0x00542c00, 0x00522e00, + 0x00503000, 0x004e3200, 0x004c3400, 0x004a3600, + 0x00483800, 0x00463a00, 0x00443c00, 0x00423e00, + 0x00404000 +}; + +const u32 vpp_3d_filter_coefs_bilinear[] = { + 2, + 33, + 0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, + 0x78080000, 0x760a0000, 0x740c0000, 0x720e0000, + 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000, + 0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, + 0x60200000, 0x5e220000, 0x5c240000, 0x5a260000, + 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000, + 0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, + 0x48380000, 0x463a0000, 0x443c0000, 0x423e0000, + 0x40400000 +}; + +const u32 vpp_filter_coefs_3point_triangle[] = { + 3, + 33, + 0x40400000, 0x3f400100, 0x3d410200, 0x3c410300, + 0x3a420400, 0x39420500, 0x37430600, 0x36430700, + 0x35430800, 0x33450800, 0x32450900, 0x31450a00, + 0x30450b00, 0x2e460c00, 0x2d460d00, 0x2c470d00, + 0x2b470e00, 0x29480f00, 0x28481000, 0x27481100, + 0x26491100, 0x25491200, 0x24491300, 0x234a1300, + 0x224a1400, 0x214a1500, 0x204a1600, 0x1f4b1600, + 0x1e4b1700, 0x1d4b1800, 0x1c4c1800, 0x1b4c1900, + 0x1a4c1a00 +}; + +/* point_num =4, filt_len =4, group_num = 64, [1 2 1] */ +const u32 vpp_filter_coefs_4point_triangle[] = { + 4, + 33, + 0x20402000, 0x20402000, 0x1f3f2101, 0x1f3f2101, + 0x1e3e2202, 0x1e3e2202, 0x1d3d2303, 0x1d3d2303, + 0x1c3c2404, 0x1c3c2404, 0x1b3b2505, 0x1b3b2505, + 0x1a3a2606, 0x1a3a2606, 0x19392707, 0x19392707, + 0x18382808, 0x18382808, 0x17372909, 0x17372909, + 0x16362a0a, 0x16362a0a, 0x15352b0b, 0x15352b0b, + 0x14342c0c, 0x14342c0c, 0x13332d0d, 0x13332d0d, + 0x12322e0e, 0x12322e0e, 0x11312f0f, 0x11312f0f, + 0x10303010 +}; + +/* + *4th order (cubic) b-spline + *filt_cubic point_num =4, filt_len =4, group_num = 64, [1 5 1] + */ +const u32 vpp_filter_coefs_4point_bspline[] = { + 4, + 33, + 0x15561500, 0x14561600, 0x13561700, 0x12561800, + 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00, + 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200, + 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700, + 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01, + 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201, + 0x05473301, 0x05463401, 0x04453601, 0x04433702, + 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02, + 0x033d3d03 +}; + +/*3rd order (quadratic) b-spline*/ +/*filt_quadratic, point_num =3, filt_len =3, group_num = 64, [1 6 1] */ +const u32 vpp_filter_coefs_3point_bspline[] = { + 3, + 33, + 0x40400000, 0x3e420000, 0x3c440000, 0x3a460000, + 0x38480000, 0x364a0000, 0x344b0100, 0x334c0100, + 0x314e0100, 0x304f0100, 0x2e500200, 0x2c520200, + 0x2a540200, 0x29540300, 0x27560300, 0x26570300, + 0x24580400, 0x23590400, 0x215a0500, 0x205b0500, + 0x1e5c0600, 0x1d5c0700, 0x1c5d0700, 0x1a5e0800, + 0x195e0900, 0x185e0a00, 0x175f0a00, 0x15600b00, + 0x14600c00, 0x13600d00, 0x12600e00, 0x11600f00, + 0x10601000 +}; + +/*filt_triangle, point_num =3, filt_len =2.6, group_num = 64, [1 7 1] */ +const u32 vpp_filter_coefs_3point_triangle_sharp[] = { + 3, + 33, + 0x40400000, 0x3e420000, 0x3d430000, 0x3b450000, + 0x3a460000, 0x38480000, 0x37490000, 0x354b0000, + 0x344c0000, 0x324e0000, 0x314f0000, 0x2f510000, + 0x2e520000, 0x2c540000, 0x2b550000, 0x29570000, + 0x28580000, 0x265a0000, 0x245c0000, 0x235d0000, + 0x215f0000, 0x20600000, 0x1e620000, 0x1d620100, + 0x1b620300, 0x19630400, 0x17630600, 0x15640700, + 0x14640800, 0x12640a00, 0x11640b00, 0x0f650c00, + 0x0d660d00 +}; + +const u32 vpp_filter_coefs_2point_binilear[] = { + 2, + 33, + 0x80000000, 0x7e020000, 0x7c040000, 0x7a060000, + 0x78080000, 0x760a0000, 0x740c0000, 0x720e0000, + 0x70100000, 0x6e120000, 0x6c140000, 0x6a160000, + 0x68180000, 0x661a0000, 0x641c0000, 0x621e0000, + 0x60200000, 0x5e220000, 0x5c240000, 0x5a260000, + 0x58280000, 0x562a0000, 0x542c0000, 0x522e0000, + 0x50300000, 0x4e320000, 0x4c340000, 0x4a360000, + 0x48380000, 0x463a0000, 0x443c0000, 0x423e0000, + 0x40400000 +}; + +static const u32 *filter_table[] = { + vpp_filter_coefs_bicubic, + vpp_filter_coefs_3point_triangle, + vpp_filter_coefs_4point_triangle, + vpp_filter_coefs_bilinear, + vpp_filter_coefs_2point_binilear, + vpp_filter_coefs_bicubic_sharp, + vpp_filter_coefs_3point_triangle_sharp, + vpp_filter_coefs_3point_bspline, + vpp_filter_coefs_4point_bspline, + vpp_3d_filter_coefs_bilinear +}; + +static int chroma_filter_table[] = { + COEF_BICUBIC, /* bicubic */ + COEF_3POINT_TRIANGLE, + COEF_4POINT_TRIANGLE, + COEF_4POINT_TRIANGLE, /* bilinear */ + COEF_2POINT_BILINEAR, + COEF_3POINT_TRIANGLE, /* bicubic_sharp */ + COEF_3POINT_TRIANGLE, /* 3point_triangle_sharp */ + COEF_3POINT_TRIANGLE, /* 3point_bspline */ + COEF_4POINT_TRIANGLE, /* 4point_bspline */ + COEF_3D_FILTER /* can not change */ +}; + +static unsigned int vert_scaler_filter = 0xff; +module_param(vert_scaler_filter, uint, 0664); +MODULE_PARM_DESC(vert_scaler_filter, "vert_scaler_filter"); + +static unsigned int vert_chroma_scaler_filter = 0xff; +module_param(vert_chroma_scaler_filter, uint, 0664); +MODULE_PARM_DESC(vert_chroma_scaler_filter, "vert_chroma_scaler_filter"); + +static unsigned int horz_scaler_filter = 0xff; +module_param(horz_scaler_filter, uint, 0664); +MODULE_PARM_DESC(horz_scaler_filter, "horz_scaler_filter"); + +bool pre_scaler_en = true; +module_param(pre_scaler_en, bool, 0664); +MODULE_PARM_DESC(pre_scaler_en, "pre_scaler_en"); +#endif +/*bicubic*/ +static const unsigned int di_filt_coef0[] = { + 0x00800000, + 0x007f0100, + 0xff7f0200, + 0xfe7f0300, + 0xfd7e0500, + 0xfc7e0600, + 0xfb7d0800, + 0xfb7c0900, + 0xfa7b0b00, + 0xfa7a0dff, + 0xf9790fff, + 0xf97711ff, + 0xf87613ff, + 0xf87416fe, + 0xf87218fe, + 0xf8701afe, + 0xf76f1dfd, + 0xf76d1ffd, + 0xf76b21fd, + 0xf76824fd, + 0xf76627fc, + 0xf76429fc, + 0xf7612cfc, + 0xf75f2ffb, + 0xf75d31fb, + 0xf75a34fb, + 0xf75837fa, + 0xf7553afa, + 0xf8523cfa, + 0xf8503ff9, + 0xf84d42f9, + 0xf84a45f9, + 0xf84848f8 +}; + +/* 2 point bilinear */ +static const unsigned int di_filt_coef1[] = { + 0x00800000, + 0x007e0200, + 0x007c0400, + 0x007a0600, + 0x00780800, + 0x00760a00, + 0x00740c00, + 0x00720e00, + 0x00701000, + 0x006e1200, + 0x006c1400, + 0x006a1600, + 0x00681800, + 0x00661a00, + 0x00641c00, + 0x00621e00, + 0x00602000, + 0x005e2200, + 0x005c2400, + 0x005a2600, + 0x00582800, + 0x00562a00, + 0x00542c00, + 0x00522e00, + 0x00503000, + 0x004e3200, + 0x004c3400, + 0x004a3600, + 0x00483800, + 0x00463a00, + 0x00443c00, + 0x00423e00, + 0x00404000 +}; + +/* 2 point bilinear, bank_length == 2*/ +static const unsigned int di_filt_coef2[] = { + 0x80000000, + 0x7e020000, + 0x7c040000, + 0x7a060000, + 0x78080000, + 0x760a0000, + 0x740c0000, + 0x720e0000, + 0x70100000, + 0x6e120000, + 0x6c140000, + 0x6a160000, + 0x68180000, + 0x661a0000, + 0x641c0000, + 0x621e0000, + 0x60200000, + 0x5e220000, + 0x5c240000, + 0x5a260000, + 0x58280000, + 0x562a0000, + 0x542c0000, + 0x522e0000, + 0x50300000, + 0x4e320000, + 0x4c340000, + 0x4a360000, + 0x48380000, + 0x463a0000, + 0x443c0000, + 0x423e0000, + 0x40400000 +}; + +#define ZOOM_BITS 20 +#define PHASE_BITS 16 + +static enum f2v_vphase_type_e top_conv_type = F2V_P2P; +static enum f2v_vphase_type_e bot_conv_type = F2V_P2P; +static unsigned int prehsc_en; +static unsigned int prevsc_en; + +static const unsigned char f2v_420_in_pos_luma[F2V_TYPE_MAX] = { +0, 2, 0, 2, 0, 0, 0, 2, 0}; +#if 0 +static const unsigned char f2v_420_in_pos_chroma[F2V_TYPE_MAX] = { + 1, 5, 1, 5, 2, 2, 1, 5, 2}; +#endif +static const unsigned char f2v_420_out_pos[F2V_TYPE_MAX] = { +0, 2, 2, 0, 0, 2, 0, 0, 0}; + +static void f2v_get_vertical_phase(unsigned int zoom_ratio, + enum f2v_vphase_type_e type, + unsigned char bank_length, + struct pps_f2v_vphase_s *vphase) +{ + int offset_in, offset_out; + + /* luma */ + offset_in = f2v_420_in_pos_luma[type] << PHASE_BITS; + offset_out = (f2v_420_out_pos[type] * zoom_ratio) + >> (ZOOM_BITS - PHASE_BITS); + + vphase->rcv_num = bank_length; + if (bank_length == 4 || bank_length == 3) + vphase->rpt_num = 1; + else + vphase->rpt_num = 0; + + if (offset_in > offset_out) { + vphase->rpt_num = vphase->rpt_num + 1; + vphase->phase = + ((4 << PHASE_BITS) + offset_out - offset_in) >> 2; + } else { + while ((offset_in + (4 << PHASE_BITS)) <= offset_out) { + if (vphase->rpt_num == 1) + vphase->rpt_num = 0; + else + vphase->rcv_num++; + offset_in += 4 << PHASE_BITS; + } + vphase->phase = (offset_out - offset_in) >> 2; + } +} + +/* + * patch 1: inp scaler 0: di wr scaler + * support: TM2 + * not support: SM1 + */ +void dim_pps_config(unsigned char path, int src_w, int src_h, + int dst_w, int dst_h) +{ + struct pps_f2v_vphase_s vphase; + + int i; + int hsc_en = 0, vsc_en = 0; + int vsc_double_line_mode; + unsigned int p_src_w, p_src_h; + unsigned int vert_phase_step, horz_phase_step; + unsigned char top_rcv_num, bot_rcv_num; + unsigned char top_rpt_num, bot_rpt_num; + unsigned short top_vphase, bot_vphase; + unsigned char is_frame; + int vert_bank_length = 4; + + const unsigned int *filt_coef0 = di_filt_coef0; + /*unsigned int *filt_coef1 = di_filt_coef1;*/ + const unsigned int *filt_coef2 = di_filt_coef2; + + vsc_double_line_mode = 0; + + if (src_h != dst_h) + vsc_en = 1; + if (src_w != dst_w) + hsc_en = 1; + /* config hdr size */ + Wr_reg_bits(DI_HDR_IN_HSIZE, dst_w, 0, 13); + Wr_reg_bits(DI_HDR_IN_VSIZE, dst_h, 0, 13); + p_src_w = (prehsc_en ? ((src_w + 1) >> 1) : src_w); + p_src_h = prevsc_en ? ((src_h + 1) >> 1) : src_h; + + Wr(DI_SC_HOLD_LINE, 0x10); + + if (p_src_w > 2048) { + /*force vert bank length = 2*/ + vert_bank_length = 2; + vsc_double_line_mode = 1; + } + + /*write vert filter coefs*/ + Wr(DI_SC_COEF_IDX, 0x0000); + for (i = 0; i < 33; i++) { + if (vert_bank_length == 2) + Wr(DI_SC_COEF, filt_coef2[i]); /*bilinear*/ + else + Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/ + } + + /*write horz filter coefs*/ + Wr(DI_SC_COEF_IDX, 0x0100); + for (i = 0; i < 33; i++) + Wr(DI_SC_COEF, filt_coef0[i]); /*bicubic*/ + + if (p_src_h > 2048) + vert_phase_step = ((p_src_h << 18) / dst_h) << 2; + else + vert_phase_step = (p_src_h << 20) / dst_h; + if (p_src_w > 2048) + horz_phase_step = ((p_src_w << 18) / dst_w) << 2; + else + horz_phase_step = (p_src_w << 20) / dst_w; + + is_frame = ((top_conv_type == F2V_IT2P) || + (top_conv_type == F2V_IB2P) || + (top_conv_type == F2V_P2P)); + + if (is_frame) { + f2v_get_vertical_phase(vert_phase_step, top_conv_type, + vert_bank_length, &vphase); + top_rcv_num = vphase.rcv_num; + top_rpt_num = vphase.rpt_num; + top_vphase = vphase.phase; + + bot_rcv_num = 0; + bot_rpt_num = 0; + bot_vphase = 0; + } else { + f2v_get_vertical_phase(vert_phase_step, top_conv_type, + vert_bank_length, &vphase); + top_rcv_num = vphase.rcv_num; + top_rpt_num = vphase.rpt_num; + top_vphase = vphase.phase; + + f2v_get_vertical_phase(vert_phase_step, bot_conv_type, + vert_bank_length, &vphase); + bot_rcv_num = vphase.rcv_num; + bot_rpt_num = vphase.rpt_num; + bot_vphase = vphase.phase; + } + vert_phase_step = (vert_phase_step << 4); + horz_phase_step = (horz_phase_step << 4); + + Wr(DI_SC_LINE_IN_LENGTH, src_w); + Wr(DI_SC_PIC_IN_HEIGHT, src_h); + Wr(DI_VSC_REGION12_STARTP, 0); + Wr(DI_VSC_REGION34_STARTP, ((dst_h << 16) | dst_h)); + Wr(DI_VSC_REGION4_ENDP, (dst_h - 1)); + + Wr(DI_VSC_START_PHASE_STEP, vert_phase_step); + Wr(DI_VSC_REGION0_PHASE_SLOPE, 0); + Wr(DI_VSC_REGION1_PHASE_SLOPE, 0); + Wr(DI_VSC_REGION3_PHASE_SLOPE, 0); + Wr(DI_VSC_REGION4_PHASE_SLOPE, 0); + + Wr(DI_VSC_PHASE_CTRL, + ((vsc_double_line_mode << 17) | + (!is_frame) << 16) | + (0 << 15) | + (bot_rpt_num << 13) | + (bot_rcv_num << 8) | + (0 << 7) | + (top_rpt_num << 5) | + (top_rcv_num)); + Wr(DI_VSC_INI_PHASE, (bot_vphase << 16) | top_vphase); + Wr(DI_HSC_REGION12_STARTP, 0); + Wr(DI_HSC_REGION34_STARTP, (dst_w << 16) | dst_w); + Wr(DI_HSC_REGION4_ENDP, dst_w - 1); + + Wr(DI_HSC_START_PHASE_STEP, horz_phase_step); + Wr(DI_HSC_REGION0_PHASE_SLOPE, 0); + Wr(DI_HSC_REGION1_PHASE_SLOPE, 0); + Wr(DI_HSC_REGION3_PHASE_SLOPE, 0); + Wr(DI_HSC_REGION4_PHASE_SLOPE, 0); + + Wr(DI_HSC_PHASE_CTRL, (1 << 21) | (4 << 16) | 0); + Wr_reg_bits(DI_SC_TOP_CTRL, (path ? 3 : 0), 29, 2); + Wr(DI_SC_MISC, + (prevsc_en << 21) | + (prehsc_en << 20) | /* prehsc_en */ + (prevsc_en << 19) | /* prevsc_en */ + (vsc_en << 18) | /* vsc_en */ + (hsc_en << 17) | /* hsc_en */ + ((vsc_en | hsc_en) << 16) | /* sc_top_en */ + (1 << 15) | /* vd1 sc out enable */ + (0 << 12) | /* horz nonlinear 4region enable */ + (4 << 8) | /* horz scaler bank length */ + (0 << 5) | /* vert scaler phase field enable */ + (0 << 4) | /* vert nonlinear 4region enable */ + (vert_bank_length << 0) /* vert scaler bank length */ + ); + + pr_info("[pps] %s input %d %d output %d %d.\n", + path ? "pre" : "post", src_w, src_h, dst_w, dst_h); +} + +/* + * 0x374e ~ 0x376d, 20 regs + */ +void dim_dump_pps_reg(unsigned int base_addr) +{ + unsigned int i = 0x374e; + + pr_info("-----dump pps start-----\n"); + for (i = 0x374e; i < 0x376e; i++) { + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, dim_RDMA_RD(i)); + } + pr_info("-----dump pps end-----\n"); +} + +/* + * di pre h scaling down function + * only have h scaling down + * support: sm1 tm2 ... + * 0x37b0 ~ 0x37b5 + */ +void dim_inp_hsc_setting(u32 src_w, u32 dst_w) +{ + u32 i; + u32 hsc_en; + u32 horz_phase_step; + const int *filt_coef0 = di_filt_coef0; + /*int *filt_coef1 = di_filt_coef1;*/ + /*int *filt_coef2 = di_filt_coef2;*/ + + if (src_w == dst_w) { + hsc_en = 0; + } else { + hsc_en = 1; + /*write horz filter coefs*/ + dim_RDMA_WR(DI_VIU_HSC_COEF_IDX, 0x0100); + for (i = 0; i < 33; i++) /*bicubic*/ + dim_RDMA_WR(DI_VIU_HSC_COEF, filt_coef0[i]); + + horz_phase_step = (src_w << 20) / dst_w; + horz_phase_step = (horz_phase_step << 4); + dim_RDMA_WR(DI_VIU_HSC_WIDTHM1, + (src_w - 1) << 16 | (dst_w - 1)); + dim_RDMA_WR(DI_VIU_HSC_PHASE_STEP, horz_phase_step); + dim_RDMA_WR(DI_VIU_HSC_PHASE_CTRL, 0); + } + dim_RDMA_WR(DI_VIU_HSC_CTRL, + (4 << 20) | /* initial receive number*/ + (0 << 12) | /* initial pixel ptr*/ + (1 << 10) | /* repeat first pixel number*/ + (0 << 8) | /* sp422 mode*/ + (4 << 4) | /* horz scaler bank length*/ + (0 << 2) | /* phase0 always en*/ + (0 << 1) | /* nearest_en*/ + (hsc_en << 0)); /* hsc_en*/ +} + +/* + * 0x37b0 ~ 0x37b5 + */ +void dim_dump_hdownscler_reg(unsigned int base_addr) +{ + unsigned int i = 0x374e; + + pr_info("-----dump hdownscler start-----\n"); + for (i = 0x37b0; i < 0x37b5; i++) { + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, dim_RDMA_RD(i)); + } + pr_info("-----dump hdownscler end-----\n"); +} + +int dim_seq_file_module_para_pps(struct seq_file *seq) +{ + seq_puts(seq, "pps---------------\n"); + + return 0; +} + diff --git a/drivers/amlogic/media/di_multi/di_pps.h b/drivers/amlogic/media/di_multi/di_pps.h new file mode 100644 index 000000000000..334db9db8ff6 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_pps.h @@ -0,0 +1,112 @@ +/* + * drivers/amlogic/media/di_multi/di_pps.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef DI_PPS_H +#define DI_PPS_H +#include +#include +#if 0 +#define VPP_FLAG_WIDEMODE_MASK 0x0000000F +#define VPP_FLAG_INTERLACE_OUT 0x00000010 +#define VPP_FLAG_INTERLACE_IN 0x00000020 +#define VPP_FLAG_CBCR_SEPARATE 0x00000040 +#define VPP_FLAG_ZOOM_SHORTSIDE 0x00000080 +#define VPP_FLAG_AR_MASK 0x0003ff00 +#define VPP_FLAG_AR_BITS 8 +#define VPP_FLAG_PORTRAIT_MODE 0x00040000 +#define VPP_FLAG_VSCALE_DISABLE 0x00080000 + +#define IDX_H (2 << 8) +#define IDX_V_Y (1 << 13) +#define IDX_V_CBCR ((1 << 13) | (1 << 8)) + +#define ASPECT_4_3 ((3 << 8) / 4) +#define ASPECT_16_9 ((9 << 8) / 16) + +#define SPEED_CHECK_DONE 0 +#define SPEED_CHECK_HSKIP 1 +#define SPEED_CHECK_VSKIP 2 + +enum f2v_vphase_type_e { + F2V_IT2IT = 0, + F2V_IB2IB, + F2V_IT2IB, + F2V_IB2IT, + F2V_P2IT, + F2V_P2IB, + F2V_IT2P, + F2V_IB2P, + F2V_P2P, + F2V_TYPE_MAX +}; /* frame to video conversion type */ +#endif + +enum hdr2_scaler_e { + hdr2_scaler_postdi = 0, + hdr2_scaler_predi = 1, +}; + +struct pps_f2v_vphase_s { + unsigned char rcv_num; + unsigned char rpt_num; + unsigned short phase; +}; + +struct ppsfilter_mode_s { + u32 pps_hf_start_phase_step; + u32 pps_hf_start_phase_slope; + u32 pps_hf_end_phase_slope; + const u32 *pps_vert_coeff; + const u32 *pps_horz_coeff; + u32 pps_sc_misc_; + u32 pps_vsc_start_phase_step; + u32 pps_hsc_start_phase_step; + bool pps_pre_vsc_en; + bool pps_pre_hsc_en; + u32 pps_vert_filter; + u32 pps_horz_filter; + const u32 *pps_chroma_coeff; + u32 pps_chroma_filter_en; +}; + +struct pps_frame_par_s { + u32 pps_vsc_startp; + u32 pps_vsc_endp; + u32 pps_hsc_startp; + u32 pps_hsc_linear_startp; + u32 pps_hsc_linear_endp; + u32 pps_hsc_endp; + u32 VPP_hf_ini_phase_; + struct f2v_vphase_s VPP_vf_ini_phase_[9]; + u32 pps_pic_in_height_; + u32 pps_line_in_length_; + struct ppsfilter_mode_s pps_filter; + u32 pps_3d_mode; + u32 trans_fmt; + /* bit[1:0] 0: 1 pic,1:two pic one buf,2:tow pic two buf */ + /* bit[2]0:select pic0,1:select pic1 */ + /* bit[3]0:pic0 first,1:pic1 first */ + bool pps_3d_scale; +}; + +void dim_pps_config(unsigned char path, int src_w, int src_h, + int dst_w, int dst_h); +void dim_dump_pps_reg(unsigned int base_addr); +void dim_inp_hsc_setting(u32 src_w, u32 dst_w); +void dim_dump_hdownscler_reg(unsigned int base_addr); + +#endif diff --git a/drivers/amlogic/media/di_multi/di_prc.c b/drivers/amlogic/media/di_multi/di_prc.c new file mode 100644 index 000000000000..98fdf24f8906 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_prc.c @@ -0,0 +1,1969 @@ +/* + * drivers/amlogic/media/di_multi/di_prc.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include +#include "deinterlace.h" + +#include "di_data_l.h" +#include "di_data.h" +#include "di_dbg.h" +#include "di_vframe.h" +#include "di_que.h" +#include "di_task.h" + +#include "di_prc.h" +#include "di_pre.h" +#include "di_post.h" +#include "di_api.h" + +/************************************** + * + * cfg ctr top + * bool + **************************************/ + +const struct di_cfg_ctr_s di_cfg_top_ctr[K_DI_CFG_NUB] = { + /*same order with enum eDI_DBG_CFG*/ + /* cfg for top */ + [eDI_CFG_BEGIN] = {"cfg top begin ", eDI_CFG_BEGIN, 0}, + + [eDI_CFG_first_bypass] = {"first_bypass", + eDI_CFG_first_bypass, 1}, + [eDI_CFG_ref_2] = {"ref_2", + eDI_CFG_ref_2, 0}, + [eDI_CFG_END] = {"cfg top end ", eDI_CFG_END, 0}, + +}; + +char *di_cfg_top_get_name(enum eDI_CFG_TOP_IDX idx) +{ + return di_cfg_top_ctr[idx].name; +} + +void di_cfg_top_get_info(unsigned int idx, char **name) +{ + if (di_cfg_top_ctr[idx].id != idx) + PR_ERR("%s:err:idx not map [%d->%d]\n", __func__, + idx, di_cfg_top_ctr[idx].id); + + *name = di_cfg_top_ctr[idx].name; +} + +bool di_cfg_top_check(unsigned int idx) +{ + unsigned int tsize; + + tsize = ARRAY_SIZE(di_cfg_top_ctr); + if (idx >= tsize) { + PR_ERR("%s:err:overflow:%d->%d\n", + __func__, idx, tsize); + return false; + } + if (idx != di_cfg_top_ctr[idx].id) { + PR_ERR("%s:err:not map:%d->%d\n", + __func__, idx, di_cfg_top_ctr[idx].id); + return false; + } + pr_info("\t%-15s=%d\n", di_cfg_top_ctr[idx].name, + di_cfg_top_ctr[idx].default_val); + return true; +} + +void di_cfg_top_init_val(void) +{ + int i; + + pr_info("%s:\n", __func__); + for (i = eDI_CFG_BEGIN; i < eDI_CFG_END; i++) { + if (!di_cfg_top_check(i)) + continue; + di_cfg_top_set(i, di_cfg_top_ctr[i].default_val); + } + pr_info("%s:finish\n", __func__); +} + +bool di_cfg_top_get(enum eDI_CFG_TOP_IDX id) +{ + return get_datal()->cfg_en[id]; +} + +void di_cfg_top_set(enum eDI_CFG_TOP_IDX id, bool en) +{ + get_datal()->cfg_en[id] = en; +} + +/************************************** + * + * cfg ctr x + * bool + **************************************/ + +const struct di_cfgx_ctr_s di_cfgx_ctr[K_DI_CFGX_NUB] = { + /*same order with enum eDI_DBG_CFG*/ + + /* cfg channel x*/ + [eDI_CFGX_BEGIN] = {"cfg x begin ", eDI_CFGX_BEGIN, 0}, + /* bypass_all */ + [eDI_CFGX_BYPASS_ALL] = {"bypass_all", eDI_CFGX_BYPASS_ALL, 0}, + [eDI_CFGX_END] = {"cfg x end ", eDI_CFGX_END, 0}, + + /* debug cfg x */ + [eDI_DBG_CFGX_BEGIN] = {"cfg dbg begin ", eDI_DBG_CFGX_BEGIN, 0}, + [eDI_DBG_CFGX_IDX_VFM_IN] = {"vfm_in", eDI_DBG_CFGX_IDX_VFM_IN, 0}, + [eDI_DBG_CFGX_IDX_VFM_OT] = {"vfm_out", eDI_DBG_CFGX_IDX_VFM_OT, 1}, + [eDI_DBG_CFGX_END] = {"cfg dbg end", eDI_DBG_CFGX_END, 0}, +}; + +char *di_cfgx_get_name(enum eDI_CFGX_IDX idx) +{ + return di_cfgx_ctr[idx].name; +} + +void di_cfgx_get_info(enum eDI_CFGX_IDX idx, char **name) +{ + if (di_cfgx_ctr[idx].id != idx) + PR_ERR("%s:err:idx not map [%d->%d]\n", __func__, + idx, di_cfgx_ctr[idx].id); + + *name = di_cfgx_ctr[idx].name; +} + +bool di_cfgx_check(unsigned int idx) +{ + unsigned int tsize; + + tsize = ARRAY_SIZE(di_cfgx_ctr); + if (idx >= tsize) { + PR_ERR("%s:err:overflow:%d->%d\n", + __func__, idx, tsize); + return false; + } + if (idx != di_cfgx_ctr[idx].id) { + PR_ERR("%s:err:not map:%d->%d\n", + __func__, idx, di_cfgx_ctr[idx].id); + return false; + } + pr_info("\t%-15s=%d\n", di_cfgx_ctr[idx].name, + di_cfgx_ctr[idx].default_val); + return true; +} + +void di_cfgx_init_val(void) +{ + int i, ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + for (i = eDI_CFGX_BEGIN; i < eDI_DBG_CFGX_END; i++) + di_cfgx_set(ch, i, di_cfgx_ctr[i].default_val); + } +} + +bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx) +{ + return get_datal()->ch_data[ch].cfgx_en[idx]; +} + +void di_cfgx_set(unsigned int ch, enum eDI_CFGX_IDX idx, bool en) +{ + get_datal()->ch_data[ch].cfgx_en[idx] = en; +} + +/************************************** + * + * module para top + * int + **************************************/ + +const struct di_mp_uit_s di_mp_ui_top[] = { + /*same order with enum eDI_MP_UI*/ + /* for top */ + [eDI_MP_UI_T_BEGIN] = {"module para top begin ", + eDI_MP_UI_T_BEGIN, 0}, + /**************************************/ + [eDI_MP_SUB_DI_B] = {"di begin ", + eDI_MP_SUB_DI_B, 0}, + [eDI_MP_force_prog] = {"bool:force_prog:1", + eDI_MP_force_prog, 1}, + [edi_mp_combing_fix_en] = {"bool:combing_fix_en,def:1", + edi_mp_combing_fix_en, 1}, + [eDI_MP_cur_lev] = {"int cur_lev,def:2", + eDI_MP_cur_lev, 2}, + [eDI_MP_pps_dstw] = {"pps_dstw:int", + eDI_MP_pps_dstw, 0}, + [eDI_MP_pps_dsth] = {"pps_dsth:int", + eDI_MP_pps_dsth, 0}, + [eDI_MP_pps_en] = {"pps_en:bool", + eDI_MP_pps_en, 0}, + [eDI_MP_pps_position] = {"pps_position:uint:def:1", + eDI_MP_pps_position, 1}, + [eDI_MP_pre_enable_mask] = {"pre_enable_mask:bit0:ma;bit1:mc:def:3", + eDI_MP_pre_enable_mask, 3}, + [eDI_MP_post_refresh] = {"post_refresh:bool", + eDI_MP_post_refresh, 0}, + [eDI_MP_nrds_en] = {"nrds_en:bool", + eDI_MP_nrds_en, 0}, + [eDI_MP_bypass_3d] = {"bypass_3d:int:def:1", + eDI_MP_bypass_3d, 1}, + [eDI_MP_bypass_trick_mode] = {"bypass_trick_mode:int:def:1", + eDI_MP_bypass_trick_mode, 1}, + [eDI_MP_invert_top_bot] = {"invert_top_bot:int", + eDI_MP_invert_top_bot, 0}, + [eDI_MP_skip_top_bot] = {"skip_top_bot:int:", + /*1or2: may affect atv when bypass di*/ + eDI_MP_skip_top_bot, 0}, + [eDI_MP_force_width] = {"force_width:int", + eDI_MP_force_width, 0}, + [eDI_MP_force_height] = {"force_height:int", + eDI_MP_force_height, 0}, + [eDI_MP_prog_proc_config] = {"prog_proc_config:int:def:0x", +/* prog_proc_config, + * bit[2:1]: when two field buffers are used, + * 0 use vpp for blending , + * 1 use post_di module for blending + * 2 debug mode, bob with top field + * 3 debug mode, bot with bot field + * bit[0]: + * 0 "prog vdin" use two field buffers, + * 1 "prog vdin" use single frame buffer + * bit[4]: + * 0 "prog frame from decoder/vdin" use two field buffers, + * 1 use single frame buffer + * bit[5]: + * when two field buffers are used for decoder (bit[4] is 0): + * 1,handle prog frame as two interlace frames + * bit[6]:(bit[4] is 0,bit[5] is 0,use_2_interlace_buff is 0): 0, + * process progress frame as field,blend by post; + * 1, process progress frame as field,process by normal di + */ + eDI_MP_prog_proc_config, ((1 << 5) | (1 << 1) | 1)}, + [eDI_MP_start_frame_drop_count] = {"start_frame_drop_count:int:2", + eDI_MP_start_frame_drop_count, 2}, + [eDI_MP_same_field_top_count] = {"same_field_top_count:long?", + eDI_MP_same_field_top_count, 0}, + [eDI_MP_same_field_bot_count] = {"same_field_bot_count:long?", + eDI_MP_same_field_bot_count, 0}, + [eDI_MP_vpp_3d_mode] = {"vpp_3d_mode:int", + eDI_MP_vpp_3d_mode, 0}, + [eDI_MP_force_recovery_count] = {"force_recovery_count:uint", + eDI_MP_force_recovery_count, 0}, + [eDI_MP_pre_process_time] = {"pre_process_time:int", + eDI_MP_pre_process_time, 0}, + [eDI_MP_bypass_post] = {"bypass_post:int", + eDI_MP_bypass_post, 0}, + [eDI_MP_post_wr_en] = {"post_wr_en:bool:1", + eDI_MP_post_wr_en, 1}, + [eDI_MP_post_wr_support] = {"post_wr_support:uint", + eDI_MP_post_wr_support, 0}, + [eDI_MP_bypass_post_state] = {"bypass_post_state:int", +/* 0, use di_wr_buf still; + * 1, call dim_pre_de_done_buf_clear to clear di_wr_buf; + * 2, do nothing + */ + eDI_MP_bypass_post_state, 0}, + [eDI_MP_use_2_interlace_buff] = {"use_2_interlace_buff:int", + eDI_MP_use_2_interlace_buff, 0}, + [eDI_MP_debug_blend_mode] = {"debug_blend_mode:int:-1", + eDI_MP_debug_blend_mode, -1}, + [eDI_MP_nr10bit_support] = {"nr10bit_support:uint", + /* 0: not support nr10bit, 1: support nr10bit */ + eDI_MP_nr10bit_support, 0}, + [eDI_MP_di_stop_reg_flag] = {"di_stop_reg_flag:uint", + eDI_MP_di_stop_reg_flag, 0}, + [eDI_MP_mcpre_en] = {"mcpre_en:bool:true", + eDI_MP_mcpre_en, 1}, + [eDI_MP_check_start_drop_prog] = {"check_start_drop_prog:bool", + eDI_MP_check_start_drop_prog, 0}, + [eDI_MP_overturn] = {"overturn:bool:?", + eDI_MP_overturn, 0}, + [eDI_MP_full_422_pack] = {"full_422_pack:bool", + eDI_MP_full_422_pack, 0}, + [eDI_MP_cma_print] = {"cma_print:bool:1", + eDI_MP_cma_print, 0}, + [eDI_MP_pulldown_enable] = {"pulldown_enable:bool:1", + eDI_MP_pulldown_enable, 1}, + [eDI_MP_di_force_bit_mode] = {"di_force_bit_mode:uint:10", + eDI_MP_di_force_bit_mode, 10}, + [eDI_MP_calc_mcinfo_en] = {"calc_mcinfo_en:bool:1", + eDI_MP_calc_mcinfo_en, 1}, + [eDI_MP_colcfd_thr] = {"colcfd_thr:uint:128", + eDI_MP_colcfd_thr, 128}, + [eDI_MP_post_blend] = {"post_blend:uint", + eDI_MP_post_blend, 0}, + [eDI_MP_post_ei] = {"post_ei:uint", + eDI_MP_post_ei, 0}, + [eDI_MP_post_cnt] = {"post_cnt:uint", + eDI_MP_post_cnt, 0}, + [eDI_MP_di_log_flag] = {"di_log_flag:uint", + eDI_MP_di_log_flag, 0}, + [eDI_MP_di_debug_flag] = {"di_debug_flag:uint", + eDI_MP_di_debug_flag, 0}, + [eDI_MP_buf_state_log_threshold] = {"buf_state_log_threshold:unit:16", + eDI_MP_buf_state_log_threshold, 16}, + [eDI_MP_di_vscale_skip_enable] = {"di_vscale_skip_enable:int", +/* + * bit[2]: enable bypass all when skip + * bit[1:0]: enable bypass post when skip + */ + eDI_MP_di_vscale_skip_enable, 0}, + [eDI_MP_di_vscale_skip_count] = {"di_vscale_skip_count:int", + eDI_MP_di_vscale_skip_count, 0}, + [eDI_MP_di_vscale_skip_count_real] = {"di_vscale_skip_count_real:int", + eDI_MP_di_vscale_skip_count_real, 0}, + [eDI_MP_det3d_en] = {"det3d_en:bool", + eDI_MP_det3d_en, 0}, + [eDI_MP_post_hold_line] = {"post_hold_line:int:8", + eDI_MP_post_hold_line, 8}, + [eDI_MP_post_urgent] = {"post_urgent:int:1", + eDI_MP_post_urgent, 1}, + [eDI_MP_di_printk_flag] = {"di_printk_flag:uint", + eDI_MP_di_printk_flag, 0}, + [eDI_MP_force_recovery] = {"force_recovery:uint:1", + eDI_MP_force_recovery, 1}, +#if 0 + [eDI_MP_debug_blend_mode] = {"debug_blend_mode:int:-1", + eDI_MP_debug_blend_mode, -1}, +#endif + [eDI_MP_di_dbg_mask] = {"di_dbg_mask:uint:0x02", + eDI_MP_di_dbg_mask, 2}, + [eDI_MP_nr_done_check_cnt] = {"nr_done_check_cnt:uint:5", + eDI_MP_nr_done_check_cnt, 5}, + [eDI_MP_pre_hsc_down_en] = {"pre_hsc_down_en:bool:0", + eDI_MP_pre_hsc_down_en, 0}, + [eDI_MP_pre_hsc_down_width] = {"pre_hsc_down_width:int:480", + eDI_MP_pre_hsc_down_width, 480}, + [eDI_MP_show_nrwr] = {"show_nrwr:bool:0", + eDI_MP_show_nrwr, 0}, + + /******deinterlace_hw.c**********/ + [eDI_MP_pq_load_dbg] = {"pq_load_dbg:uint", + eDI_MP_pq_load_dbg, 0}, + [eDI_MP_lmv_lock_win_en] = {"lmv_lock_win_en:bool", + eDI_MP_lmv_lock_win_en, 0}, + [eDI_MP_lmv_dist] = {"lmv_dist:short:5", + eDI_MP_lmv_dist, 5}, + [eDI_MP_pr_mcinfo_cnt] = {"pr_mcinfo_cnt:ushort", + eDI_MP_pr_mcinfo_cnt, 0}, + [eDI_MP_offset_lmv] = {"offset_lmv:short:100", + eDI_MP_offset_lmv, 100}, + [eDI_MP_post_ctrl] = {"post_ctrl:uint", + eDI_MP_post_ctrl, 0}, + [eDI_MP_if2_disable] = {"if2_disable:bool", + eDI_MP_if2_disable, 0}, + [eDI_MP_pre_flag] = {"pre_flag:ushort:2", + eDI_MP_pre_flag, 2}, + [eDI_MP_pre_mif_gate] = {"pre_mif_gate:bool", + eDI_MP_pre_mif_gate, 0}, + [eDI_MP_pre_urgent] = {"pre_urgent:ushort", + eDI_MP_pre_urgent, 0}, + [eDI_MP_pre_hold_line] = {"pre_hold_line:ushort:10", + eDI_MP_pre_hold_line, 10}, + [eDI_MP_pre_ctrl] = {"pre_ctrl:uint", + eDI_MP_pre_ctrl, 0}, + [eDI_MP_line_num_post_frst] = {"line_num_post_frst:ushort:5", + eDI_MP_line_num_post_frst, 5}, + [eDI_MP_line_num_pre_frst] = {"line_num_pre_frst:ushort:5", + eDI_MP_line_num_pre_frst, 5}, + [eDI_MP_pd22_flg_calc_en] = {"pd22_flg_calc_en:bool:true", + eDI_MP_pd22_flg_calc_en, 1}, + [eDI_MP_mcen_mode] = {"mcen_mode:ushort:1", + eDI_MP_mcen_mode, 1}, + [eDI_MP_mcuv_en] = {"mcuv_en:ushort:1", + eDI_MP_mcuv_en, 1}, + [eDI_MP_mcdebug_mode] = {"mcdebug_mode:ushort", + eDI_MP_mcdebug_mode, 0}, + [eDI_MP_pldn_ctrl_rflsh] = {"pldn_ctrl_rflsh:uint:1", + eDI_MP_pldn_ctrl_rflsh, 1}, + + [eDI_MP_SUB_DI_E] = {"di end-------", + eDI_MP_SUB_DI_E, 0}, + /**************************************/ + [eDI_MP_SUB_NR_B] = {"nr begin", + eDI_MP_SUB_NR_B, 0}, + [eDI_MP_dnr_en] = {"dnr_en:bool:true", + eDI_MP_dnr_en, 1}, + [eDI_MP_nr2_en] = {"nr2_en:uint:1", + eDI_MP_nr2_en, 1}, + [eDI_MP_cue_en] = {"cue_en:bool:true", + eDI_MP_cue_en, 1}, + [eDI_MP_invert_cue_phase] = {"invert_cue_phase:bool", + eDI_MP_invert_cue_phase, 0}, + [eDI_MP_cue_pr_cnt] = {"cue_pr_cnt:uint", + eDI_MP_cue_pr_cnt, 0}, + [eDI_MP_cue_glb_mot_check_en] = {"cue_glb_mot_check_en:bool:true", + eDI_MP_cue_glb_mot_check_en, 1}, + [eDI_MP_glb_fieldck_en] = {"glb_fieldck_en:bool:true", + eDI_MP_glb_fieldck_en, 1}, + [eDI_MP_dnr_pr] = {"dnr_pr:bool", + eDI_MP_dnr_pr, 0}, + [eDI_MP_dnr_dm_en] = {"dnr_dm_en:bool", + eDI_MP_dnr_dm_en, 0}, + [eDI_MP_SUB_NR_E] = {"nr end-------", + eDI_MP_SUB_NR_E, 0}, + /**************************************/ + [eDI_MP_SUB_PD_B] = {"pd begin", + eDI_MP_SUB_PD_B, 0}, + [eDI_MP_flm22_ratio] = {"flm22_ratio:uint:200", + eDI_MP_flm22_ratio, 200}, + [eDI_MP_pldn_cmb0] = {"pldn_cmb0:uint:1", + eDI_MP_pldn_cmb0, 1}, + [eDI_MP_pldn_cmb1] = {"pldn_cmb1:uint", + eDI_MP_pldn_cmb1, 0}, + [eDI_MP_flm22_sure_num] = {"flm22_sure_num:uint:100", + eDI_MP_flm22_sure_num, 100}, + [eDI_MP_flm22_glbpxlnum_rat] = {"flm22_glbpxlnum_rat:uint:4", + eDI_MP_flm22_glbpxlnum_rat, 4}, + [eDI_MP_flag_di_weave] = {"flag_di_weave:int:1", + eDI_MP_flag_di_weave, 1}, + [eDI_MP_flm22_glbpxl_maxrow] = {"flm22_glbpxl_maxrow:uint:16", + eDI_MP_flm22_glbpxl_maxrow, 16}, + [eDI_MP_flm22_glbpxl_minrow] = {"flm22_glbpxl_minrow:uint:3", + eDI_MP_flm22_glbpxl_minrow, 3}, + [eDI_MP_cmb_3point_rnum] = {"cmb_3point_rnum:uint", + eDI_MP_cmb_3point_rnum, 0}, + [eDI_MP_cmb_3point_rrat] = {"cmb_3point_rrat:unit:32", + eDI_MP_cmb_3point_rrat, 32}, + /********************************/ + [eDI_MP_pr_pd] = {"pr_pd:uint", + eDI_MP_pr_pd, 0}, + [eDI_MP_prt_flg] = {"prt_flg:bool", + eDI_MP_prt_flg, 0}, + [eDI_MP_flmxx_maybe_num] = {"flmxx_maybe_num:uint:15", + /* if flmxx level > flmxx_maybe_num */ + /* mabye flmxx: when 2-2 3-2 not detected */ + eDI_MP_flmxx_maybe_num, 15}, + [eDI_MP_flm32_mim_frms] = {"flm32_mim_frms:int:6", + eDI_MP_flm32_mim_frms, 6}, + [eDI_MP_flm22_dif01a_flag] = {"flm22_dif01a_flag:int:1", + eDI_MP_flm22_dif01a_flag, 1}, + [eDI_MP_flm22_mim_frms] = {"flm22_mim_frms:int:60", + eDI_MP_flm22_mim_frms, 60}, + [eDI_MP_flm22_mim_smfrms] = {"flm22_mim_smfrms:int:40", + eDI_MP_flm22_mim_smfrms, 40}, + [eDI_MP_flm32_f2fdif_min0] = {"flm32_f2fdif_min0:int:11", + eDI_MP_flm32_f2fdif_min0, 11}, + [eDI_MP_flm32_f2fdif_min1] = {"flm32_f2fdif_min1:int:11", + eDI_MP_flm32_f2fdif_min1, 11}, + [eDI_MP_flm32_chk1_rtn] = {"flm32_chk1_rtn:int:25", + eDI_MP_flm32_chk1_rtn, 25}, + [eDI_MP_flm32_ck13_rtn] = {"flm32_ck13_rtn:int:8", + eDI_MP_flm32_ck13_rtn, 8}, + [eDI_MP_flm32_chk2_rtn] = {"flm32_chk2_rtn:int:16", + eDI_MP_flm32_chk2_rtn, 16}, + [eDI_MP_flm32_chk3_rtn] = {"flm32_chk3_rtn:int:16", + eDI_MP_flm32_chk3_rtn, 16}, + [eDI_MP_flm32_dif02_ratio] = {"flm32_dif02_ratio:int:8", + eDI_MP_flm32_dif02_ratio, 8}, + [eDI_MP_flm22_chk20_sml] = {"flm22_chk20_sml:int:6", + eDI_MP_flm22_chk20_sml, 6}, + [eDI_MP_flm22_chk21_sml] = {"flm22_chk21_sml:int:6", + eDI_MP_flm22_chk21_sml, 6}, + [eDI_MP_flm22_chk21_sm2] = {"flm22_chk21_sm2:int:10", + eDI_MP_flm22_chk21_sm2, 10}, + [eDI_MP_flm22_lavg_sft] = {"flm22_lavg_sft:int:4", + eDI_MP_flm22_lavg_sft, 4}, + [eDI_MP_flm22_lavg_lg] = {"flm22_lavg_lg:int:24", + eDI_MP_flm22_lavg_lg, 24}, + [eDI_MP_flm22_stl_sft] = {"flm22_stl_sft:int:7", + eDI_MP_flm22_stl_sft, 7}, + [eDI_MP_flm22_chk5_avg] = {"flm22_chk5_avg:int:50", + eDI_MP_flm22_chk5_avg, 50}, + [eDI_MP_flm22_chk6_max] = {"flm22_chk6_max:int:20", + eDI_MP_flm22_chk6_max, 20}, + [eDI_MP_flm22_anti_chk1] = {"flm22_anti_chk1:int:61", + eDI_MP_flm22_anti_chk1, 61}, + [eDI_MP_flm22_anti_chk3] = {"flm22_anti_chk3:int:140", + eDI_MP_flm22_anti_chk3, 140}, + [eDI_MP_flm22_anti_chk4] = {"flm22_anti_chk4:int:128", + eDI_MP_flm22_anti_chk4, 128}, + [eDI_MP_flm22_anti_ck140] = {"flm22_anti_ck140:int:32", + eDI_MP_flm22_anti_ck140, 32}, + [eDI_MP_flm22_anti_ck141] = {"flm22_anti_ck141:int:80", + eDI_MP_flm22_anti_ck141, 80}, + [eDI_MP_flm22_frmdif_max] = {"flm22_frmdif_max:int:50", + eDI_MP_flm22_frmdif_max, 50}, + [eDI_MP_flm22_flddif_max] = {"flm22_flddif_max:int:100", + eDI_MP_flm22_flddif_max, 100}, + [eDI_MP_flm22_minus_cntmax] = {"flm22_minus_cntmax:int:2", + eDI_MP_flm22_minus_cntmax, 2}, + [eDI_MP_flagdif01chk] = {"flagdif01chk:int:1", + eDI_MP_flagdif01chk, 1}, + [eDI_MP_dif01_ratio] = {"dif01_ratio:int:10", + eDI_MP_dif01_ratio, 10}, + /*************vof_soft_top**************/ + [eDI_MP_cmb32_blw_wnd] = {"cmb32_blw_wnd:int:180", + eDI_MP_cmb32_blw_wnd, 180}, + [eDI_MP_cmb32_wnd_ext] = {"cmb32_wnd_ext:int:11", + eDI_MP_cmb32_wnd_ext, 11}, + [eDI_MP_cmb32_wnd_tol] = {"cmb32_wnd_tol:int:4", + eDI_MP_cmb32_wnd_tol, 4}, + [eDI_MP_cmb32_frm_nocmb] = {"cmb32_frm_nocmb:int:40", + eDI_MP_cmb32_frm_nocmb, 40}, + [eDI_MP_cmb32_min02_sft] = {"cmb32_min02_sft:int:7", + eDI_MP_cmb32_min02_sft, 7}, + [eDI_MP_cmb32_cmb_tol] = {"cmb32_cmb_tol:int:10", + eDI_MP_cmb32_cmb_tol, 10}, + [eDI_MP_cmb32_avg_dff] = {"cmb32_avg_dff:int:48", + eDI_MP_cmb32_avg_dff, 48}, + [eDI_MP_cmb32_smfrm_num] = {"cmb32_smfrm_num:int:4", + eDI_MP_cmb32_smfrm_num, 4}, + [eDI_MP_cmb32_nocmb_num] = {"cmb32_nocmb_num:int:20", + eDI_MP_cmb32_nocmb_num, 20}, + [eDI_MP_cmb22_gcmb_rnum] = {"cmb22_gcmb_rnum:int:8", + eDI_MP_cmb22_gcmb_rnum, 8}, + [eDI_MP_flmxx_cal_lcmb] = {"flmxx_cal_lcmb:int:1", + eDI_MP_flmxx_cal_lcmb, 1}, + [eDI_MP_flm2224_stl_sft] = {"flm2224_stl_sft:int:7", + eDI_MP_flm2224_stl_sft, 7}, + [eDI_MP_SUB_PD_E] = {"pd end------", + eDI_MP_SUB_PD_E, 0}, + /**************************************/ + [eDI_MP_SUB_MTN_B] = {"mtn begin", + eDI_MP_SUB_MTN_B, 0}, + [eDI_MP_force_lev] = {"force_lev:int:0xff", + eDI_MP_force_lev, 0xff}, + [eDI_MP_dejaggy_flag] = {"dejaggy_flag:int:-1", + eDI_MP_dejaggy_flag, -1}, + [eDI_MP_dejaggy_enable] = {"dejaggy_enable:int:1", + eDI_MP_dejaggy_enable, 1}, + [eDI_MP_cmb_adpset_cnt] = {"cmb_adpset_cnt:int", + eDI_MP_cmb_adpset_cnt, 0}, + [eDI_MP_cmb_num_rat_ctl4] = {"cmb_num_rat_ctl4:int:64:0~255", + eDI_MP_cmb_num_rat_ctl4, 64}, + [eDI_MP_cmb_rat_ctl4_minthd] = {"cmb_rat_ctl4_minthd:int:64", + eDI_MP_cmb_rat_ctl4_minthd, 64}, + [eDI_MP_small_local_mtn] = {"small_local_mtn:uint:70", + eDI_MP_small_local_mtn, 70}, + [eDI_MP_di_debug_readreg] = {"di_debug_readreg:int", + eDI_MP_di_debug_readreg, 0}, + [eDI_MP_SUB_MTN_E] = {"mtn end----", + eDI_MP_SUB_MTN_E, 0}, + /**************************************/ + [eDI_MP_SUB_3D_B] = {"3d begin", + eDI_MP_SUB_3D_B, 0}, + [eDI_MP_chessbd_vrate] = {"chessbd_vrate:int:29", + eDI_MP_chessbd_vrate, 29}, + [eDI_MP_det3d_debug] = {"det3d_debug:bool:0", + eDI_MP_det3d_debug, 0}, + [eDI_MP_SUB_3D_E] = {"3d begin", + eDI_MP_SUB_3D_E, 0}, + + /**************************************/ + [eDI_MP_UI_T_END] = {"module para top end ", eDI_MP_UI_T_END, 0}, +}; + +bool di_mp_uit_check(unsigned int idx) +{ + unsigned int tsize; + + tsize = ARRAY_SIZE(di_mp_ui_top); + if (idx >= tsize) { + PR_ERR("%s:err:overflow:%d->%d\n", + __func__, idx, tsize); + return false; + } + if (idx != di_mp_ui_top[idx].id) { + PR_ERR("%s:err:not map:%d->%d\n", + __func__, idx, di_mp_ui_top[idx].id); + return false; + } + dbg_init("\t%-15s=%d\n", di_mp_ui_top[idx].name, + di_mp_ui_top[idx].default_val); + return true; +} + +char *di_mp_uit_get_name(enum eDI_MP_UI_T idx) +{ + return di_mp_ui_top[idx].name; +} + +void di_mp_uit_init_val(void) +{ + int i; + + for (i = eDI_MP_UI_T_BEGIN; i < eDI_MP_UI_T_END; i++) { + if (!di_mp_uit_check(i)) + continue; + di_mp_uit_set(i, di_mp_ui_top[i].default_val); + } +} + +int di_mp_uit_get(enum eDI_MP_UI_T idx) +{ + return get_datal()->mp_uit[idx]; +} + +void di_mp_uit_set(enum eDI_MP_UI_T idx, int val) +{ + get_datal()->mp_uit[idx] = val; +} + +/************************************** + * + * module para x + * unsigned int + **************************************/ + +const struct di_mp_uix_s di_mpx[] = { + /*same order with enum eDI_MP_UI*/ + + /* module para for channel x*/ + [eDI_MP_UIX_BEGIN] = {"module para x begin ", eDI_MP_UIX_BEGIN, 0}, + /*debug: run_flag*/ + [eDI_MP_UIX_RUN_FLG] = {"run_flag(0:run;1:pause;2:step)", + eDI_MP_UIX_RUN_FLG, DI_RUN_FLAG_RUN}, + [eDI_MP_UIX_END] = {"module para x end ", eDI_MP_UIX_END, 0}, + +}; + +bool di_mp_uix_check(unsigned int idx) +{ + unsigned int tsize; + + tsize = ARRAY_SIZE(di_mpx); + if (idx >= tsize) { + PR_ERR("%s:err:overflow:%d->%d\n", + __func__, idx, tsize); + return false; + } + if (idx != di_mpx[idx].id) { + PR_ERR("%s:err:not map:%d->%d\n", + __func__, idx, di_mpx[idx].id); + return false; + } + dbg_init("\t%-15s=%d\n", di_mpx[idx].name, di_mpx[idx].default_val); + + return true; +} + +char *di_mp_uix_get_name(enum eDI_MP_UIX_T idx) +{ + return di_mpx[idx].name; +} + +void di_mp_uix_init_val(void) +{ + int i, ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + dbg_init("%s:ch[%d]\n", __func__, ch); + for (i = eDI_MP_UIX_BEGIN; i < eDI_MP_UIX_END; i++) { + if (ch == 0) { + if (!di_mp_uix_check(i)) + continue; + } + di_mp_uix_set(ch, i, di_mpx[i].default_val); + } + } +} + +unsigned int di_mp_uix_get(unsigned int ch, enum eDI_MP_UIX_T idx) +{ + return get_datal()->ch_data[ch].mp_uix[idx]; +} + +void di_mp_uix_set(unsigned int ch, enum eDI_MP_UIX_T idx, unsigned int val) +{ + get_datal()->ch_data[ch].mp_uix[idx] = val; +} + +bool di_is_pause(unsigned int ch) +{ + unsigned int run_flag; + + run_flag = di_mp_uix_get(ch, eDI_MP_UIX_RUN_FLG); + + if (run_flag == DI_RUN_FLAG_PAUSE || + run_flag == DI_RUN_FLAG_STEP_DONE) + return true; + + return false; +} + +void di_pause_step_done(unsigned int ch) +{ + unsigned int run_flag; + + run_flag = di_mp_uix_get(ch, eDI_MP_UIX_RUN_FLG); + if (run_flag == DI_RUN_FLAG_STEP) { + di_mp_uix_set(ch, eDI_MP_UIX_RUN_FLG, + DI_RUN_FLAG_STEP_DONE); + } +} + +void di_pause(unsigned int ch, bool on) +{ + pr_info("%s:%d\n", __func__, on); + if (on) + di_mp_uix_set(ch, eDI_MP_UIX_RUN_FLG, + DI_RUN_FLAG_PAUSE); + else + di_mp_uix_set(ch, eDI_MP_UIX_RUN_FLG, + DI_RUN_FLAG_RUN); +} + +/************************************** + * + * summmary variable + * + **************************************/ +const struct di_sum_s di_sum_tab[] = { + /*video_peek_cnt*/ + [eDI_SUM_O_PEEK_CNT] = {"o_peek_cnt", eDI_SUM_O_PEEK_CNT, 0}, + /*di_reg_unreg_cnt*/ + [eDI_SUM_REG_UNREG_CNT] = { + "di_reg_unreg_cnt", eDI_SUM_REG_UNREG_CNT, 100}, + + [eDI_SUM_NUB] = {"end", eDI_SUM_NUB, 0}, +}; + +unsigned int di_sum_get_tab_size(void) +{ + return ARRAY_SIZE(di_sum_tab); +} + +bool di_sum_check(unsigned int ch, enum eDI_SUM id) +{ + unsigned int tsize; + + tsize = ARRAY_SIZE(di_sum_tab); + + if (id >= tsize) { + PR_ERR("%s:err:overflow:tsize[%d],id[%d]\n", + __func__, tsize, id); + return false; + } + if (di_sum_tab[id].index != id) { + PR_ERR("%s:err:table:id[%d],tab_id[%d]\n", + __func__, id, di_sum_tab[id].index); + return false; + } + return true; +} + +void di_sum_reg_init(unsigned int ch) +{ + unsigned int tsize; + int i; + + tsize = ARRAY_SIZE(di_sum_tab); + + dbg_init("%s:ch[%d]\n", __func__, ch); + for (i = 0; i < tsize; i++) { + if (!di_sum_check(ch, i)) + continue; + dbg_init("\t:%d:name:%s,%d\n", i, di_sum_tab[i].name, + di_sum_tab[i].default_val); + di_sum_set_l(ch, i, di_sum_tab[i].default_val); + } +} + +void di_sum_get_info(unsigned int ch, enum eDI_SUM id, char **name, + unsigned int *pval) +{ + *name = di_sum_tab[id].name; + *pval = di_sum_get(ch, id); +} + +void di_sum_set(unsigned int ch, enum eDI_SUM id, unsigned int val) +{ + if (!di_sum_check(ch, id)) + return; + + di_sum_set_l(ch, id, val); +} + +unsigned int di_sum_inc(unsigned int ch, enum eDI_SUM id) +{ + if (!di_sum_check(ch, id)) + return 0; + return di_sum_inc_l(ch, id); +} + +unsigned int di_sum_get(unsigned int ch, enum eDI_SUM id) +{ + if (!di_sum_check(ch, id)) + return 0; + return di_sum_get_l(ch, id); +} + +/****************************/ +/*call by event*/ +/****************************/ +void dip_even_reg_init_val(unsigned int ch) +{ +} + +void dip_even_unreg_val(unsigned int ch) +{ +} + +/****************************/ +static void dip_cma_init_val(void) +{ + unsigned int ch; + struct di_mng_s *pbm = get_bufmng(); + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + /* CMA state */ + atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_IDL); + + /* CMA reg/unreg cmd */ + pbm->cma_reg_cmd[ch] = 0; + } +} + +void dip_cma_close(void) +{ + unsigned int ch; + struct di_mng_s *pbm = get_bufmng(); + + if (dip_cma_st_is_idl_all()) + return; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + if (!dip_cma_st_is_idle(ch)) { + dim_cma_top_release(ch); + pr_info("%s:force release ch[%d]", __func__, ch); + atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_IDL); + + pbm->cma_reg_cmd[ch] = 0; + } + } +} + +static void dip_wq_cma_handler(struct work_struct *work) +{ + unsigned int ch; + struct di_mng_s *pbm = get_bufmng(); + enum eDI_CMA_ST cma_st; + bool do_flg; + + pr_info("%s:start\n", __func__); + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + do_flg = false; + cma_st = dip_cma_get_st(ch); + switch (cma_st) { + case eDI_CMA_ST_IDL: + if (pbm->cma_reg_cmd[ch]) { + do_flg = true; + /*set:alloc:*/ + atomic_set(&pbm->cma_mem_state[ch], + eDI_CMA_ST_ALLOC); + if (dim_cma_top_alloc(ch)) { + atomic_set(&pbm->cma_mem_state[ch], + eDI_CMA_ST_READY); + } + } + break; + case eDI_CMA_ST_READY: + if (!pbm->cma_reg_cmd[ch]) { + do_flg = true; + atomic_set(&pbm->cma_mem_state[ch], + eDI_CMA_ST_RELEASE); + dim_cma_top_release(ch); + atomic_set(&pbm->cma_mem_state[ch], + eDI_CMA_ST_IDL); + } + break; + case eDI_CMA_ST_ALLOC: /*do*/ + case eDI_CMA_ST_RELEASE:/*do*/ + default: + break; + } + if (!do_flg) + pr_info("\tch[%d],do nothing[%d]\n", ch, cma_st); + else + task_send_ready(); + } + pr_info("%s:end\n", __func__); +} + +static void dip_wq_prob(void) +{ + struct di_mng_s *pbm = get_bufmng(); + + pbm->wq_cma = create_singlethread_workqueue("deinterlace"); + INIT_WORK(&pbm->wq_work, dip_wq_cma_handler); +} + +static void dip_wq_ext(void) +{ + struct di_mng_s *pbm = get_bufmng(); + + cancel_work_sync(&pbm->wq_work); + destroy_workqueue(pbm->wq_cma); + pr_info("%s:finish\n", __func__); +} + +void dip_wq_cma_run(unsigned char ch, bool reg_cmd) +{ + struct di_mng_s *pbm = get_bufmng(); + + if (reg_cmd) + pbm->cma_reg_cmd[ch] = 1; + else + pbm->cma_reg_cmd[ch] = 0; + + queue_work(pbm->wq_cma, &pbm->wq_work); +} + +bool dip_cma_st_is_ready(unsigned int ch) +{ + struct di_mng_s *pbm = get_bufmng(); + bool ret = false; + + if (atomic_read(&pbm->cma_mem_state[ch]) == eDI_CMA_ST_READY) + ret = true; + + return ret; +} + +bool dip_cma_st_is_idle(unsigned int ch) +{ + struct di_mng_s *pbm = get_bufmng(); + bool ret = false; + + if (atomic_read(&pbm->cma_mem_state[ch]) == eDI_CMA_ST_IDL) + ret = true; + + return ret; +} + +bool dip_cma_st_is_idl_all(void) +{ + unsigned int ch; + struct di_mng_s *pbm = get_bufmng(); + bool ret = true; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + if (atomic_read(&pbm->cma_mem_state[ch]) != eDI_CMA_ST_IDL) { + ret = true; + break; + } + } + return ret; +} + +enum eDI_CMA_ST dip_cma_get_st(unsigned int ch) +{ + struct di_mng_s *pbm = get_bufmng(); + + return atomic_read(&pbm->cma_mem_state[ch]); +} + +const char * const di_cma_state_name[] = { + "IDLE", + "do_alloc", + "READY", + "do_release", +}; + +const char *di_cma_dbg_get_st_name(unsigned int ch) +{ + enum eDI_CMA_ST st = dip_cma_get_st(ch); + const char *p = ""; + + if (st <= eDI_CMA_ST_RELEASE) + p = di_cma_state_name[st]; + return p; +} + +void dip_cma_st_set_ready_all(void) +{ + unsigned int ch; + struct di_mng_s *pbm = get_bufmng(); + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) + atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_READY); +} + +/****************************/ +/*channel STATE*/ +/****************************/ +void dip_chst_set(unsigned int ch, enum eDI_TOP_STATE chSt) +{ + struct di_mng_s *pbm = get_bufmng(); + + atomic_set(&pbm->ch_state[ch], chSt); +} + +enum eDI_TOP_STATE dip_chst_get(unsigned int ch) +{ + struct di_mng_s *pbm = get_bufmng(); + + return atomic_read(&pbm->ch_state[ch]); +} + +void dip_chst_init(void) +{ + unsigned int ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) + dip_chst_set(ch, eDI_TOP_STATE_IDLE); +} + +bool dip_event_reg_chst(unsigned int ch) +{ + enum eDI_TOP_STATE chst; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + bool err_flg = false; + bool ret = true; + + dbg_dbg("%s:ch[%d]\n", __func__, ch); + + chst = dip_chst_get(ch); +#if 0 /*move*/ + if (chst > eDI_TOP_STATE_NOPROB) + set_flag_trig_unreg(ch, false); +#endif + switch (chst) { + case eDI_TOP_STATE_IDLE: + + queue_init2(ch); + di_que_init(ch); + di_vframe_reg(ch); + + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP1); + task_send_cmd(LCMD1(eCMD_REG, ch)); + dbg_dbg("reg ok\n"); + break; + case eDI_TOP_STATE_REG_STEP1: + case eDI_TOP_STATE_REG_STEP1_P1: + case eDI_TOP_STATE_REG_STEP2: + case eDI_TOP_STATE_READY: + case eDI_TOP_STATE_BYPASS: + PR_WARN("have reg\n"); + ret = false; + break; + case eDI_TOP_STATE_UNREG_STEP1: + case eDI_TOP_STATE_UNREG_STEP2: + /*wait*/ + ppre->reg_req_flag_cnt = 0; + while (dip_chst_get(ch) != eDI_TOP_STATE_IDLE) { + usleep_range(10000, 10001); + if (ppre->reg_req_flag_cnt++ > + dim_get_reg_unreg_cnt()) { + dim_reg_timeout_inc(); + PR_ERR("%s,ch[%d] reg timeout!!!\n", + __func__, ch); + err_flg = true; + ret = false; + break; + } + } + if (!err_flg) { + /*same as IDLE*/ + queue_init2(ch); + di_que_init(ch); + di_vframe_reg(ch); + + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP1); + task_send_cmd(LCMD1(eCMD_REG, ch)); + dbg_dbg("reg retry ok\n"); + } + break; + case eDI_TOP_STATE_NOPROB: + default: + ret = false; + PR_ERR("err: not prob[%d]\n", chst); + + break; + } + + return ret; +} + +bool dip_event_unreg_chst(unsigned int ch) +{ + enum eDI_TOP_STATE chst, chst2; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + bool ret = false; + bool err_flg = false; + unsigned int cnt; + + chst = dip_chst_get(ch); + dbg_reg("%s:ch[%d]:%s\n", __func__, ch, dip_chst_get_name(chst)); + #if 0 + if (chst > eDI_TOP_STATE_IDLE) + set_reg_flag(ch, false);/*set_flag_trig_unreg(ch, true);*/ + #endif + if (chst > eDI_TOP_STATE_NOPROB) + set_flag_trig_unreg(ch, true); + + switch (chst) { + case eDI_TOP_STATE_READY: + + di_vframe_unreg(ch); + /*trig unreg*/ + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP1); + task_send_cmd(LCMD1(eCMD_UNREG, ch)); + /*debug only di_dbg = di_dbg|DBG_M_TSK;*/ + + /*wait*/ + ppre->unreg_req_flag_cnt = 0; + chst2 = dip_chst_get(ch); + + while (chst2 != eDI_TOP_STATE_IDLE) { + task_send_ready(); + usleep_range(10000, 10001); + /*msleep(5);*/ + if (ppre->unreg_req_flag_cnt++ + > dim_get_reg_unreg_cnt()) { + dim_reg_timeout_inc(); + PR_ERR("%s:ch[%d] unreg timeout!!!\n", + __func__, ch); + /*dim_unreg_process();*/ + err_flg = true; + break; + } + #if 0 /*debug only*/ + dbg_reg("\tch[%d]:s[%s],ecnt[%d]\n", + ch, + dip_chst_get_name(chst2), + ppre->unreg_req_flag_cnt); + #endif + chst2 = dip_chst_get(ch); + } + + /*debug only di_dbg = di_dbg & (~DBG_M_TSK);*/ + dbg_reg("%s:ch[%d] ready end\n", __func__, ch); + #if 0 + if (!err_flg) + set_reg_flag(ch, false); + #endif + break; + case eDI_TOP_STATE_BYPASS: + /*from bypass complet to unreg*/ + di_vframe_unreg(ch); + di_unreg_variable(ch); + + set_reg_flag(ch, false); + if (!get_reg_flag_all()) { + di_unreg_setting(); + dpre_init(); + dpost_init(); + } + dip_chst_set(ch, eDI_TOP_STATE_IDLE); + ret = true; + + break; + case eDI_TOP_STATE_IDLE: + PR_WARN("have unreg\n"); + break; + case eDI_TOP_STATE_REG_STEP1: + dbg_dbg("%s:in reg step1\n", __func__); + di_vframe_unreg(ch); + set_reg_flag(ch, false); + dip_chst_set(ch, eDI_TOP_STATE_IDLE); + + ret = true; + break; + case eDI_TOP_STATE_REG_STEP1_P1: + /*wait:*/ + cnt = 0; + chst2 = dip_chst_get(ch); + while (chst2 == eDI_TOP_STATE_REG_STEP1_P1 || cnt < 5) { + task_send_ready(); + usleep_range(3000, 3001); + cnt++; + } + if (cnt >= 5) + PR_ERR("%s:ch[%d] in p1 timeout\n", __func__, ch); + + set_reg_flag(ch, false); + + di_vframe_unreg(ch); + /*trig unreg*/ + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP1); + task_send_cmd(LCMD1(eCMD_UNREG, ch)); + /*debug only di_dbg = di_dbg|DBG_M_TSK;*/ + + /*wait*/ + ppre->unreg_req_flag_cnt = 0; + chst2 = dip_chst_get(ch); + + while (chst2 != eDI_TOP_STATE_IDLE) { + task_send_ready(); + usleep_range(10000, 10001); + /*msleep(5);*/ + if (ppre->unreg_req_flag_cnt++ + > dim_get_reg_unreg_cnt()) { + dim_reg_timeout_inc(); + PR_ERR("%s:ch[%d] unreg timeout!!!\n", + __func__, + ch); + /*di_unreg_process();*/ + err_flg = true; + break; + } + + chst2 = dip_chst_get(ch); + } + + /*debug only di_dbg = di_dbg & (~DBG_M_TSK);*/ + dbg_reg("%s:ch[%d] ready end\n", __func__, ch); + ret = true; + + break; + case eDI_TOP_STATE_REG_STEP2: + di_vframe_unreg(ch); + di_unreg_variable(ch); + set_reg_flag(ch, false); + if (!get_reg_flag_all()) { + di_unreg_setting(); + dpre_init(); + dpost_init(); + } + + dip_chst_set(ch, eDI_TOP_STATE_IDLE); + + ret = true; + break; + case eDI_TOP_STATE_UNREG_STEP1: + case eDI_TOP_STATE_UNREG_STEP2: + task_send_cmd(LCMD1(eCMD_UNREG, ch)); + + /*wait*/ + ppre->unreg_req_flag_cnt = 0; + while (dip_chst_get(ch) != eDI_TOP_STATE_IDLE) { + usleep_range(10000, 10001); + if (ppre->unreg_req_flag_cnt++ > + dim_get_reg_unreg_cnt()) { + dim_reg_timeout_inc(); + PR_ERR("%s:unreg_reg_flag timeout!!!\n", + __func__); + di_vframe_unreg(ch); + err_flg = true; + break; + } + } + break; + case eDI_TOP_STATE_NOPROB: + default: + PR_ERR("err: not prob[%d]\n", chst); + break; + } + if (err_flg) + ret = false; + + return ret; +} + +/*process for reg and unreg cmd*/ +void dip_chst_process_reg(unsigned int ch) +{ + enum eDI_TOP_STATE chst; + struct vframe_s *vframe; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + bool reflesh = true; + + while (reflesh) { + reflesh = false; + + chst = dip_chst_get(ch); + + /*dbg_reg("%s:ch[%d]%s\n", __func__, ch, dip_chst_get_name(chst));*/ + + switch (chst) { + case eDI_TOP_STATE_NOPROB: + case eDI_TOP_STATE_IDLE: + break; + case eDI_TOP_STATE_REG_STEP1:/*wait peek*/ + vframe = pw_vf_peek(ch); + + if (vframe) { + dim_tr_ops.pre_get(vframe->omx_index); + set_flag_trig_unreg(ch, false); + #if 0 + di_reg_variable(ch); + + /*?how about bypass ?*/ + if (ppre->bypass_flag) { + /* complete bypass */ + set_bypass2_complete(ch, true); + if (!get_reg_flag_all()) { + /*first channel reg*/ + dpre_init(); + dpost_init(); + di_reg_setting(ch, vframe); + } + dip_chst_set(ch, eDI_TOP_STATE_BYPASS); + set_reg_flag(ch, true); + } else { + set_bypass2_complete(ch, false); + if (!get_reg_flag_all()) { + /*first channel reg*/ + dpre_init(); + dpost_init(); + di_reg_setting(ch, vframe); + } + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP2); + } + #else + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP1_P1); + #endif + + reflesh = true; + } + break; + case eDI_TOP_STATE_REG_STEP1_P1: + vframe = pw_vf_peek(ch); + if (!vframe) { + PR_ERR("%s:p1 vfm nop\n", __func__); + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP1); + + break; + } + di_reg_variable(ch, vframe); + /*di_reg_process_irq(ch);*/ /*check if bypass*/ + + /*?how about bypass ?*/ + if (ppre->bypass_flag) { + /* complete bypass */ + set_bypass2_complete(ch, true); + if (!get_reg_flag_all()) { + /*first channel reg*/ + dpre_init(); + dpost_init(); + di_reg_setting(ch, vframe); + } + dip_chst_set(ch, eDI_TOP_STATE_BYPASS); + set_reg_flag(ch, true); + } else { + set_bypass2_complete(ch, false); + if (!get_reg_flag_all()) { + /*first channel reg*/ + dpre_init(); + dpost_init(); + di_reg_setting(ch, vframe); + } + /*this will cause first local buf not alloc*/ + /*dim_bypass_first_frame(ch);*/ + dip_chst_set(ch, eDI_TOP_STATE_REG_STEP2); + /*set_reg_flag(ch, true);*/ + } + + reflesh = true; + break; + case eDI_TOP_STATE_REG_STEP2:/*now no change to do*/ + if (dip_cma_get_st(ch) == eDI_CMA_ST_READY) { + if (di_cfg_top_get(eDI_CFG_first_bypass)) { + if (get_sum_g(ch) == 0) + dim_bypass_first_frame(ch); + else + PR_INF("ch[%d],g[%d]\n", + ch, get_sum_g(ch)); + } + dip_chst_set(ch, eDI_TOP_STATE_READY); + set_reg_flag(ch, true); + /*move to step1 dim_bypass_first_frame(ch);*/ + } + break; + case eDI_TOP_STATE_READY: + + break; + case eDI_TOP_STATE_BYPASS: + /*do nothing;*/ + break; + case eDI_TOP_STATE_UNREG_STEP1: + +#if 0 + if (!get_reg_flag(ch)) { /*need wait pre/post done*/ + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP2); + reflesh = true; + } +#else + /*debug only dbg_reg("%s:UNREG_STEP1\n", __func__);*/ + + if (dpre_can_exit(ch) && dpst_can_exit(ch)) { + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP2); + set_reg_flag(ch, false); + reflesh = true; + } +#endif + break; + case eDI_TOP_STATE_UNREG_STEP2: + /*debug only dbg_reg("%s:ch[%d]:UNREG_STEP2\n",__func__, ch);*/ + di_unreg_variable(ch); + if (!get_reg_flag_all()) { + di_unreg_setting(); + dpre_init(); + dpost_init(); + } + + dip_chst_set(ch, eDI_TOP_STATE_IDLE); + /*debug only dbg_reg("ch[%d]UNREG_STEP2 end\n",ch);*/ + break; + } + } +} + +void dip_chst_process_ch(void) +{ + unsigned int ch; + unsigned int chst; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + chst = dip_chst_get(ch); + switch (chst) { + case eDI_TOP_STATE_REG_STEP2: + if (dip_cma_get_st(ch) == eDI_CMA_ST_READY) { + if (di_cfg_top_get(eDI_CFG_first_bypass)) { + if (get_sum_g(ch) == 0) + dim_bypass_first_frame(ch); + else + PR_INF("ch[%d],g[%d]\n", + ch, get_sum_g(ch)); + } + dip_chst_set(ch, eDI_TOP_STATE_READY); + set_reg_flag(ch, true); + } + break; +#if 1 + case eDI_TOP_STATE_UNREG_STEP1: + if (dpre_can_exit(ch) && dpst_can_exit(ch)) { + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP2); + set_reg_flag(ch, false); + } + + break; +#endif + case eDI_TOP_STATE_UNREG_STEP2: + dbg_reg("%s:ch[%d]:at UNREG_STEP2\n", __func__, ch); + di_unreg_variable(ch); + if (!get_reg_flag_all()) { + di_unreg_setting(); + dpre_init(); + dpost_init(); + } + + dip_chst_set(ch, eDI_TOP_STATE_IDLE); + dbg_reg("ch[%d]STEP2 end\n", ch); + break; + } + } +} + +bool dip_chst_change_2unreg(void) +{ + unsigned int ch; + unsigned int chst; + bool ret = false; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + chst = dip_chst_get(ch); + dbg_poll("[%d]%d\n", ch, chst); + if (chst == eDI_TOP_STATE_UNREG_STEP1) { + dbg_reg("%s:ch[%d]to UNREG_STEP2\n", __func__, ch); + set_reg_flag(ch, false); + dip_chst_set(ch, eDI_TOP_STATE_UNREG_STEP2); + ret = true; + } + } + return ret; +} + +#if 0 +void di_reg_flg_check(void) +{ + int ch; + unsigned int chst; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) + chst = dip_chst_get(ch); +} +#endif + +void dip_hw_process(void) +{ + di_dbg_task_flg = 5; + dpre_process(); + di_dbg_task_flg = 6; + pre_mode_setting(); + di_dbg_task_flg = 7; + dpst_process(); + di_dbg_task_flg = 8; +} + +const char * const di_top_state_name[] = { + "NOPROB", + "IDLE", + "REG_STEP1", + "REG_P1", + "REG_STEP2", + "READY", + "BYPASS", + "UNREG_STEP1", + "UNREG_STEP2", +}; + +const char *dip_chst_get_name_curr(unsigned int ch) +{ + const char *p = ""; + enum eDI_TOP_STATE chst; + + chst = dip_chst_get(ch); + + if (chst < ARRAY_SIZE(di_top_state_name)) + p = di_top_state_name[chst]; + + return p; +} + +const char *dip_chst_get_name(enum eDI_TOP_STATE chst) +{ + const char *p = ""; + + if (chst < ARRAY_SIZE(di_top_state_name)) + p = di_top_state_name[chst]; + + return p; +} + +/**********************************/ +/* TIME OUT CHEKC api*/ +/**********************************/ + +void di_tout_int(struct di_time_out_s *tout, unsigned int thd) +{ + tout->en = false; + tout->timer_start = 0; + tout->timer_thd = thd; +} + +bool di_tout_contr(enum eDI_TOUT_CONTR cmd, struct di_time_out_s *tout) +{ + unsigned long ctimer; + unsigned long diff; + bool ret = false; + + ctimer = cur_to_msecs(); + + switch (cmd) { + case eDI_TOUT_CONTR_EN: + tout->en = true; + tout->timer_start = ctimer; + break; + case eDI_TOUT_CONTR_FINISH: + if (tout->en) { + diff = ctimer - tout->timer_start; + + if (diff > tout->timer_thd) { + tout->over_flow_cnt++; + + if (tout->over_flow_cnt > 0xfffffff0) { + tout->over_flow_cnt = 0; + tout->flg_over = 1; + } + #if 0 + if (tout->do_func) + tout->do_func(); + + #endif + ret = true; + } + tout->en = false; + } + break; + + case eDI_TOUT_CONTR_CHECK: /*if time is overflow, disable timer*/ + if (tout->en) { + diff = ctimer - tout->timer_start; + + if (diff > tout->timer_thd) { + tout->over_flow_cnt++; + + if (tout->over_flow_cnt > 0xfffffff0) { + tout->over_flow_cnt = 0; + tout->flg_over = 1; + } + #if 0 + if (tout->do_func) + tout->do_func(); + + #endif + ret = true; + tout->en = false; + } + } + break; + case eDI_TOUT_CONTR_CLEAR: + tout->en = false; + tout->timer_start = ctimer; + break; + case eDI_TOUT_CONTR_RESET: + tout->en = true; + tout->timer_start = ctimer; + break; + } + + return ret; +} + +const unsigned int di_ch2mask_table[DI_CHANNEL_MAX] = { + DI_BIT0, + DI_BIT1, + DI_BIT2, + DI_BIT3, +}; + +/****************************************/ +/* do_table */ +/****************************************/ + +/*for do_table_working*/ +#define K_DO_TABLE_LOOP_MAX 15 + +const struct do_table_s do_table_def = { + .ptab = NULL, + .data = NULL, + .size = 0, + .op_lst = K_DO_TABLE_ID_STOP, + .op_crr = K_DO_TABLE_ID_STOP, + .do_stop = 0, + .flg_stop = 0, + .do_pause = 0, + .do_step = 0, + .flg_repeat = 0, + +}; + +void do_table_init(struct do_table_s *pdo, + const struct do_table_ops_s *ptable, + unsigned int size_tab) +{ + memcpy(pdo, &do_table_def, sizeof(struct do_table_s)); + + if (ptable) { + pdo->ptab = ptable; + pdo->size = size_tab; + } +} + +/*if change to async?*/ +/* now only call in same thread */ +void do_talbe_cmd(struct do_table_s *pdo, enum eDO_TABLE_CMD cmd) +{ + switch (cmd) { + case eDO_TABLE_CMD_NONE: + pr_info("test:%s\n", __func__); + break; + case eDO_TABLE_CMD_STOP: + pdo->do_stop = true; + break; + case eDO_TABLE_CMD_START: + if (pdo->op_crr == K_DO_TABLE_ID_STOP) { + pdo->op_lst = pdo->op_crr; + pdo->op_crr = K_DO_TABLE_ID_START; + pdo->do_stop = false; + pdo->flg_stop = false; + } else if (pdo->op_crr == K_DO_TABLE_ID_PAUSE) { + pdo->op_crr = pdo->op_lst; + pdo->op_lst = K_DO_TABLE_ID_PAUSE; + pdo->do_pause = false; + } else { + pr_info("crr is [%d], not start\n", pdo->op_crr); + } + break; + case eDO_TABLE_CMD_PAUSE: + if (pdo->op_crr <= K_DO_TABLE_ID_STOP) { + /*do nothing*/ + } else { + pdo->op_lst = pdo->op_crr; + pdo->op_crr = K_DO_TABLE_ID_PAUSE; + pdo->do_pause = true; + } + break; + case eDO_TABLE_CMD_STEP: + pdo->do_step = true; + break; + case eDO_TABLE_CMD_STEP_BACK: + pdo->do_step = false; + break; + default: + break; + } +} + +bool do_table_is_crr(struct do_table_s *pdo, unsigned int state) +{ + if (pdo->op_crr == state) + return true; + return false; +} + +void do_table_working(struct do_table_s *pdo) +{ + const struct do_table_ops_s *pcrr; + unsigned int ret = 0; + unsigned int next; + bool flash = false; + unsigned int cnt = 0; /*proction*/ + unsigned int lst_id; /*dbg only*/ + char *name = ""; /*dbg only*/ + bool need_pr = false; /*dbg only*/ + + if (!pdo) + return; + + if (!pdo->ptab || + pdo->op_crr >= pdo->size) { + PR_ERR("di:err:%s:ovflow:0x%p,0x%p,crr=%d,size=%d\n", + __func__, + pdo, pdo->ptab, + pdo->op_crr, + pdo->size); + return; + } + + pcrr = pdo->ptab + pdo->op_crr; + + if (pdo->name) + name = pdo->name; + /*stop ?*/ + if (pdo->do_stop && + (pcrr->mark & K_DO_TABLE_CAN_STOP)) { + dbg_dt("%s:do stop\n", name); + + /*do stop*/ + if (pcrr->do_stop_op) + pcrr->do_stop_op(pdo->data); + /*set status*/ + pdo->op_lst = pdo->op_crr; + pdo->op_crr = K_DO_TABLE_ID_STOP; + pdo->flg_stop = true; + pdo->do_stop = false; + + return; + } + + /*pause?*/ + if (pdo->op_crr == K_DO_TABLE_ID_STOP || + pdo->op_crr == K_DO_TABLE_ID_PAUSE) + return; + + do { + flash = false; + cnt++; + if (cnt > K_DO_TABLE_LOOP_MAX) { + PR_ERR("di:err:%s:loop more %d\n", name, cnt); + break; + } + + /*stop again? */ + if (pdo->do_stop && + (pcrr->mark & K_DO_TABLE_CAN_STOP)) { + /*do stop*/ + dbg_dt("%s: do stop in loop\n", name); + if (pcrr->do_stop_op) + pcrr->do_stop_op(pdo->data); + /*set status*/ + pdo->op_lst = pdo->op_crr; + pdo->op_crr = K_DO_TABLE_ID_STOP; + pdo->flg_stop = true; + pdo->do_stop = false; + + break; + } + + /*debug:*/ + lst_id = pdo->op_crr; + need_pr = true; + + if (pcrr->con) { + if (pcrr->con(pdo->data)) + ret = pcrr->do_op(pdo->data); + else + break; + + } else { + ret = pcrr->do_op(pdo->data); + dbg_dt("do_table:do:%d:ret=0x%x\n", pcrr->id, ret); + } + + /*not finish, keep current status*/ + if ((ret & K_DO_TABLE_R_B_FINISH) == 0) { + dbg_dt("%s:not finish,wait\n", __func__); + break; + } + + /*fix to next */ + if (ret & K_DO_TABLE_R_B_NEXT) { + pdo->op_lst = pdo->op_crr; + pdo->op_crr++; + if (pdo->op_crr >= pdo->size) { + pdo->op_crr = pdo->flg_repeat ? + K_DO_TABLE_ID_START + : K_DO_TABLE_ID_STOP; + dbg_dt("%s:to end,%d\n", __func__, + pdo->op_crr); + break; + } + /*return;*/ + flash = true; + } else { + next = ((ret & K_DO_TABLE_R_B_OTHER) >> + K_DO_TABLE_R_B_OTHER_SHIFT); + if (next < pdo->size) { + pdo->op_lst = pdo->op_crr; + pdo->op_crr = next; + if (next > K_DO_TABLE_ID_STOP) + flash = true; + else + flash = false; + } else { + PR_ERR("%s: next[%d] err:\n", + __func__, next); + } + } + /*debug 1:*/ + need_pr = false; + if (lst_id != pdo->op_crr) { + dbg_dt("do_table:%s:%s->%s\n", pdo->name, + pdo->ptab[lst_id].name, + pdo->ptab[pdo->op_crr].name); + } + + pcrr = pdo->ptab + pdo->op_crr; + } while (flash && !pdo->do_step); + + /*debug 2:*/ + if (need_pr) { + if (lst_id != pdo->op_crr) { + dbg_dt("do_table2:%s:%s->%s\n", pdo->name, + pdo->ptab[lst_id].name, + pdo->ptab[pdo->op_crr].name); + } + } +} + +/**********************************/ + +/****************************/ +void dip_init_value_reg(unsigned int ch) +{ + struct di_post_stru_s *ppost; + struct di_buf_s *keep_post_buf; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + + pr_info("%s:\n", __func__); + + /*post*/ + ppost = get_post_stru(ch); + /*keep buf:*/ + keep_post_buf = ppost->keep_buf_post; + + memset(ppost, 0, sizeof(struct di_post_stru_s)); + ppost->next_canvas_id = 1; + ppost->keep_buf_post = keep_post_buf; + + /*pre*/ + memset(ppre, 0, sizeof(struct di_pre_stru_s)); +} + +static bool dip_init_value(void) +{ + unsigned int ch; + struct di_post_stru_s *ppost; + struct di_mm_s *mm = dim_mm_get(); + bool ret = false; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + ppost = get_post_stru(ch); + memset(ppost, 0, sizeof(struct di_post_stru_s)); + ppost->next_canvas_id = 1; + + /*que*/ + ret = di_que_alloc(ch); + } + set_current_channel(0); + + /*mm cfg*/ + mm->cfg.di_h = 1080; + mm->cfg.di_w = 1920; + mm->cfg.num_local = MAX_LOCAL_BUF_NUM; + mm->cfg.num_post = MAX_POST_BUF_NUM; + /*mm sts*/ + mm->sts.mem_start = 0; + mm->sts.mem_size = 0; + mm->sts.total_pages = NULL; + mm->sts.flag_cma = 0; + + return ret; +} + +/****************************************** + * pq ops + *****************************************/ +void dip_init_pq_ops(void) +{ + di_attach_ops_pulldown(&get_datal()->ops_pd); + di_attach_ops_3d(&get_datal()->ops_3d); + di_attach_ops_nr(&get_datal()->ops_nr); + di_attach_ops_mtn(&get_datal()->ops_mtn); + + dim_attach_to_local(); +} + +/**********************************/ +void dip_clean_value(void) +{ + unsigned int ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + /*que*/ + di_que_release(ch); + } +} + +bool dip_prob(void) +{ + bool ret = true; + + ret = dip_init_value(); + + di_cfgx_init_val(); + di_cfg_top_init_val(); + di_mp_uit_init_val(); + di_mp_uix_init_val(); + + dev_vframe_init(); + didbg_fs_init(); + dip_wq_prob(); + dip_cma_init_val(); + dip_chst_init(); + + dpre_init(); + dpost_init(); + + dip_init_pq_ops(); + + return ret; +} + +void dip_exit(void) +{ + dip_wq_ext(); + dev_vframe_exit(); + dip_clean_value(); + didbg_fs_exit(); +} + diff --git a/drivers/amlogic/media/di_multi/di_prc.h b/drivers/amlogic/media/di_multi/di_prc.h new file mode 100644 index 000000000000..8083bc469c04 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_prc.h @@ -0,0 +1,131 @@ +/* + * drivers/amlogic/media/di_multi/di_prc.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_PRC_H__ +#define __DI_PRC_H__ + +bool dip_prob(void); +void dip_exit(void); + +void dip_even_reg_init_val(unsigned int ch); +void dip_even_unreg_val(unsigned int ch); + +/************************/ +/* CMA */ +/************************/ +void dip_wq_cma_run(unsigned char ch, bool reg_cmd); +bool dip_cma_st_is_ready(unsigned int ch); +bool dip_cma_st_is_idle(unsigned int ch); +bool dip_cma_st_is_idl_all(void); +enum eDI_CMA_ST dip_cma_get_st(unsigned int ch); +void dip_cma_st_set_ready_all(void); +void dip_cma_close(void); +const char *di_cma_dbg_get_st_name(unsigned int ch); + +/*************************/ +/* STATE*/ +/*************************/ +bool dip_event_reg_chst(unsigned int ch); +bool dip_event_unreg_chst(unsigned int ch); +void dip_chst_process_reg(unsigned int ch); + +void dip_hw_process(void); + +void dip_chst_process_ch(void); +bool dip_chst_change_2unreg(void); + +enum eDI_TOP_STATE dip_chst_get(unsigned int ch); +const char *dip_chst_get_name_curr(unsigned int ch); +const char *dip_chst_get_name(enum eDI_TOP_STATE chst); + +/************************************** + * + * summmary variable + * + **************************************/ +void di_sum_reg_init(unsigned int ch); +void di_sum_set(unsigned int ch, enum eDI_SUM id, unsigned int val); +unsigned int di_sum_inc(unsigned int ch, enum eDI_SUM id); +unsigned int di_sum_get(unsigned int ch, enum eDI_SUM id); +void di_sum_get_info(unsigned int ch, enum eDI_SUM id, char **name, + unsigned int *pval); +unsigned int di_sum_get_tab_size(void); +bool di_sum_check(unsigned int ch, enum eDI_SUM id); + +/************************************** + * + * cfg ctr top + * bool + **************************************/ +char *di_cfg_top_get_name(enum eDI_CFG_TOP_IDX idx); +void di_cfg_top_get_info(unsigned int idx, char **name); +void di_cfg_top_init_val(void); +bool di_cfg_top_get(enum eDI_CFG_TOP_IDX id); +void di_cfg_top_set(enum eDI_CFG_TOP_IDX id, bool en); + +/************************************** + * + * cfg ctr x + * bool + **************************************/ +char *di_cfgx_get_name(enum eDI_CFGX_IDX idx); +void di_cfgx_get_info(enum eDI_CFGX_IDX idx, char **name); +void di_cfgx_init_val(void); +bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx); +void di_cfgx_set(unsigned int ch, enum eDI_CFGX_IDX idx, bool en); + +/************************************** + * + * module para top + * int + **************************************/ +char *di_mp_uit_get_name(enum eDI_MP_UI_T idx); +void di_mp_uit_init_val(void); +int di_mp_uit_get(enum eDI_MP_UI_T idx); +void di_mp_uit_set(enum eDI_MP_UI_T idx, int val); + +/************************************** + * + * module para x + * unsigned int + **************************************/ +char *di_mp_uix_get_name(enum eDI_MP_UIX_T idx); +void di_mp_uix_init_val(void); +unsigned int di_mp_uix_get(unsigned int ch, enum eDI_MP_UIX_T idx); +void di_mp_uix_set(unsigned int ch, enum eDI_MP_UIX_T idx, + unsigned int val); + +/****************************************/ +/* do_table */ +/****************************************/ +void do_table_init(struct do_table_s *pdo, + const struct do_table_ops_s *ptable, + unsigned int size_tab); +/* now only call in same thread */ +void do_talbe_cmd(struct do_table_s *pdo, enum eDO_TABLE_CMD cmd); +void do_table_working(struct do_table_s *pdo); +bool do_table_is_crr(struct do_table_s *pdo, unsigned int state); + +enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel); + +void dip_init_value_reg(unsigned int ch); + +bool di_is_pause(unsigned int ch); +void di_pause_step_done(unsigned int ch); +void di_pause(unsigned int ch, bool on); + +#endif /*__DI_PRC_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_pre.c b/drivers/amlogic/media/di_multi/di_pre.c new file mode 100644 index 000000000000..2c4739499a39 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_pre.c @@ -0,0 +1,985 @@ +/* + * drivers/amlogic/media/di_multi/di_pre.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include +#include "deinterlace.h" +#include "deinterlace_dbg.h" + +#include "di_data_l.h" +#include "di_data.h" +#include "di_dbg.h" +#include "di_vframe.h" +#include "di_que.h" +#include "di_task.h" + +#include "di_prc.h" +#include "di_pre.h" + +#include "nr_downscale.h" +#include "register.h" + +/**************************************** + * 1. copy curr to last + * 2. set curr + ****************************************/ +void pre_vinfo_set(unsigned int ch, + struct vframe_s *ori_vframe) +{ + struct di_hpre_s *pre = get_hw_pre(); + + struct di_vinfo_s *vc = &pre->vinf_curr; + struct di_vinfo_s *vl = &pre->vinf_lst; + + memcpy(vl, vc, sizeof(struct di_vinfo_s)); + + vc->ch = ch; + vc->vtype = ori_vframe->type; + vc->src_type = ori_vframe->source_type; + vc->trans_fmt = ori_vframe->trans_fmt; + + if (COM_ME(ori_vframe->type, VIDTYPE_COMPRESS)) { + vc->h = ori_vframe->compWidth; + vc->v = ori_vframe->compHeight; + } else { + vc->h = ori_vframe->width; + vc->v = ori_vframe->height; + } +} + +/**************************************** + * compare current vframe info with last + * return + * 0. no change + * 1. video format channge + * 2. scan mode channge? + ****************************************/ +unsigned int is_vinfo_change(unsigned int ch) +{ + struct di_hpre_s *pre = get_hw_pre(); + + struct di_vinfo_s *vc = &pre->vinf_curr; + struct di_vinfo_s *vl = &pre->vinf_lst; + struct di_pre_stru_s *ppre = get_pre_stru(ch); + unsigned int ret = 0; + + if (vc->src_type != vl->src_type || + !COM_M(DI_VFM_T_MASK_CHANGE, vc->vtype, vl->vtype) || + vc->v != vl->v || + vc->h != vl->h || + vc->trans_fmt != vl->trans_fmt) { + /* video format changed */ + ret = 1; + } else if (!COM_M(VIDTYPE_VIU_FIELD, vc->vtype, vl->vtype)) + /* just scan mode changed */ + ret = 2; + + if (ret) { + dim_print( + "%s:ch[%d]: %dth source change 2: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n", + __func__, + ch, + /*jiffies_to_msecs(jiffies_64),*/ + ppre->in_seq, + vl->vtype, + vl->h, + vl->v, + vl->src_type, + vc->vtype, + vc->h, + vc->v, + vc->src_type); + } + + return ret; +} + +bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm) +{ + bool ret = false; + + if (!vfm) + return ret; + pre_vinfo_set(ch, vfm); + if (is_vinfo_change(ch)) { + if (!is_bypass2(vfm, ch)) { + set_bypass2_complete(ch, false); + PR_INF("%s:\n", __func__); + /*task_send_ready();*/ + task_send_cmd(LCMD1(eCMD_CHG, ch)); + ret = true; + } + } + return ret; +} + +unsigned int di_get_other_ch(unsigned int curr) +{ + return curr ? 0 : 1; +} + +bool is_bypass_i_p(void) +{ + bool ret = false; + struct di_hpre_s *pre = get_hw_pre(); + struct di_vinfo_s *vc = &pre->vinf_curr; + #if 0 + struct di_vinfo_s *vl = &pre->vinf_lst; + + if (vl->ch != vc->ch && + vf_type_is_interlace(vl->vtype) && + vf_type_is_prog(vc->vtype)) { + ret = true; + } + #else + unsigned int ch_c, ch_l; + + struct di_pre_stru_s *ppre_c, *ppre_l; + + if (!get_reg_flag(0) || + !get_reg_flag(1)) + return ret; + + ch_c = vc->ch; + ch_l = (ch_c ? 0 : 1); + ppre_c = get_pre_stru(ch_c); + ppre_l = get_pre_stru(ch_l); + if (vf_type_is_interlace(ppre_l->cur_inp_type) && + vf_type_is_prog(ppre_c->cur_inp_type)) { + ret = true; + dim_print("ch[%d]:bypass p\n", ch_c); + } + #endif + + return ret; +} + +void dpre_clear(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + + memset(pre, 0, sizeof(struct di_hpre_s)); +} + +void dpre_init(void) +{/*reg:*/ + struct di_hpre_s *pre = get_hw_pre(); + + pre->pre_st = eDI_PRE_ST_IDLE; + + /*timer out*/ + di_tout_int(&pre->tout, 40); /*ms*/ +} + +void pw_use_hw_pre(enum eDI_SUB_ID channel, bool on) +{ + struct di_hpre_s *pre = get_hw_pre(); + + pre->hw_flg_busy_pre = on; + if (on) + pre->curr_ch = channel; +} + +enum eDI_SUB_ID pw_ch_next_count(enum eDI_SUB_ID channel) +{ + int i; + unsigned int lch, nch; + + nch = channel; + for (i = 0; i < DI_CHANNEL_NUB; i++) { + lch = channel + i + 1; + if (lch >= DI_CHANNEL_NUB) + lch -= DI_CHANNEL_NUB; + #if 0 + if (pbm->sub_act_flg[lch]) { + nch = lch; + break; + } + #else + if (get_reg_flag(lch) && + !get_flag_trig_unreg(lch) && + !is_bypss2_complete(lch)) { + nch = lch; + break; + } + #endif + } + return nch; +} + +/****************************************/ +static bool pw_try_sw_ch_next_pre(enum eDI_SUB_ID channel) +{ + bool ret = false; + struct di_hpre_s *pre = get_hw_pre(); + enum eDI_SUB_ID lst_ch, nch; + + lst_ch = channel; + + nch = pw_ch_next_count(lst_ch); + if (!get_reg_flag(nch) || + get_flag_trig_unreg(nch) || + is_bypss2_complete(nch)) + return false; + + pre->curr_ch = nch; + pre->hw_flg_busy_pre = true; + ret = true; + + /*dim_print("%s:%d->%d:%d\n", __func__, lst_ch, nch, ret);*/ + return ret; +} + +/*****************************/ +/* debug */ +/*****************************/ + +unsigned int di_dbg_pre_cnt; + +void dbg_cnt_begin(void) +{ + di_dbg_pre_cnt = 0x10; +} + +void dbg_cnt_print(void) +{ + if (di_dbg_pre_cnt < 0xf) + return; + + if (di_dbg_pre_cnt > 0x10) { + di_dbg_pre_cnt++; + pr_info("di:[%d]\n", di_dbg_pre_cnt); + } + + if (di_dbg_pre_cnt > 0x15) + di_dbg_pre_cnt = 0; +} + +/*****************************/ +/* STEP */ +/*****************************/ +void dpre_recyc(unsigned int ch) +{ + struct di_hpre_s *pre = get_hw_pre(); + + pre->check_recycle_buf_cnt = 0; + while (dim_check_recycle_buf(ch) & 1) { + if (pre->check_recycle_buf_cnt++ > MAX_IN_BUF_NUM) { + di_pr_info("%s: dim_check_recycle_buf time out!!\n", + __func__); + break; + } + } +} + +void dpre_vdoing(unsigned int ch) +{ + struct di_post_stru_s *ppost = get_post_stru(ch); + + ppost->di_post_process_cnt = 0; + while (dim_process_post_vframe(ch)) { + if (ppost->di_post_process_cnt++ > + MAX_POST_BUF_NUM) { + di_pr_info("%s: dim_process_post_vframe time out!!\n", + __func__); + break; + } + } +} + +bool dpre_can_exit(unsigned int ch) +{ + struct di_hpre_s *pre = get_hw_pre(); + bool ret = false; + + if (ch != pre->curr_ch) { + ret = true; + } else { + if (pre->pre_st <= eDI_PRE_ST4_IDLE) + ret = true; + } + pr_info("%s:ch[%d]:curr[%d]:stat[%s] ret[%d]\n", + __func__, + ch, pre->curr_ch, + dpre_state4_name_get(pre->pre_st), + ret); + return ret; +} + +void dpre_dbg_f_trig(unsigned int cmd) +{ + struct di_task *tsk = get_task(); + + struct di_hpre_s *pre = get_hw_pre(); + + if (down_interruptible(&tsk->sem)) { + PR_ERR("%s:can't get sem\n", __func__); + return; + } + + /*set on/off and trig*/ + if (cmd & 0x10) { + pre->dbg_f_en = 1; + pre->dbg_f_cnt = cmd & 0xf; + pre->dbg_f_lstate = pre->pre_st; + } else { + pre->dbg_f_en = 0; + } + + up(&tsk->sem); +} + +void dpre_process(void) +{ + bool reflesh; + struct di_hpre_s *pre = get_hw_pre(); + + if (pre->dbg_f_en) { + if (pre->dbg_f_cnt) { + dpre_process_step4(); + pre->dbg_f_cnt--; + } + if (pre->dbg_f_lstate != pre->pre_st) { + pr_info("ch[%d]:state:%s->%s\n", + pre->curr_ch, + dpre_state4_name_get(pre->dbg_f_lstate), + dpre_state4_name_get(pre->pre_st)); + + pre->dbg_f_lstate = pre->pre_st; + } + return; + } + + reflesh = true; + + while (reflesh) { + reflesh = dpre_process_step4(); + #if 0 /*debug only*/ + dbg_tsk("ch[%d]:st[%s]r[%d]\n", pre->curr_ch, + dpre_state4_name_get(pre->pre_st), reflesh); + #endif + } +} + +enum eDI_PRE_MT { + eDI_PRE_MT_CHECK = K_DO_TABLE_ID_START, + eDI_PRE_MT_SET, + eDI_PRE_MT_WAIT_INT, + eDI_PRE_MT_TIME_OUT, +}; + +/*use do_table:*/ +unsigned int dpre_mtotal_check(void *data) +{ + struct di_hpre_s *pre = get_hw_pre(); + unsigned int ret = K_DO_R_NOT_FINISH; + + if ((pre_run_flag == DI_RUN_FLAG_RUN) || + (pre_run_flag == DI_RUN_FLAG_STEP)) { + if (pre_run_flag == DI_RUN_FLAG_STEP) + pre_run_flag = DI_RUN_FLAG_STEP_DONE; + /*dim_print("%s:\n", __func__);*/ + if (dim_pre_de_buf_config(pre->curr_ch)) + ret = K_DO_R_FINISH; + else + ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); + + dim_dbg_pre_cnt(pre->curr_ch, "x"); + } + + return ret; +} + +unsigned int dpre_mtotal_set(void *data) +{ + struct di_hpre_s *pre = get_hw_pre(); + ulong flags = 0; + + /*dim_print("%s:\n", __func__);*/ + spin_lock_irqsave(&plist_lock, flags); + dim_pre_de_process(pre->curr_ch); + spin_unlock_irqrestore(&plist_lock, flags); + /*begin to count timer*/ + di_tout_contr(eDI_TOUT_CONTR_EN, &pre->tout); + + return K_DO_R_FINISH; +} + +enum eDI_WAIT_INT { + eDI_WAIT_INT_NEED_WAIT, + eDI_WAIT_INT_HAVE_INT, + eDI_WAIT_INT_TIME_OUT, +}; + +/* + *return: enum eDI_WAIT_INT + * + */ +enum eDI_WAIT_INT di_pre_wait_int(void *data) +{ + struct di_hpre_s *pre = get_hw_pre(); + ulong flags = 0; + struct di_pre_stru_s *ppre; + + enum eDI_WAIT_INT ret = eDI_WAIT_INT_NEED_WAIT; + + if (pre->flg_int_done) { + /*have INT done flg*/ + /*DI_INTR_CTRL[bit 0], NRWR_done, set by + * hardware when NRWR is done,clear by write 1 + * by code;[bit 1] + * MTNWR_done, set by hardware when MTNWR + * is done, clear by write 1 by code;these two + * bits have nothing to do with + * DI_INTR_CTRL[16](NRW irq mask, 0 to enable + * irq) and DI_INTR_CTRL[17] + * (MTN irq mask, 0 to enable irq).two + * interrupts are raised if both + * DI_INTR_CTRL[16] and DI_INTR_CTRL[17] are 0 + */ +#if 0 + data32 = Rd(DI_INTR_CTRL); + if (((data32 & 0x1) && + ((ppre->enable_mtnwr == 0) || (data32 & 0x2))) || + (ppre->pre_de_clear_flag == 2)) { + dim_RDMA_WR(DI_INTR_CTRL, data32); + } +#endif + di_pre_wait_irq_set(false); + /*finish to count timer*/ + di_tout_contr(eDI_TOUT_CONTR_FINISH, &pre->tout); + spin_lock_irqsave(&plist_lock, flags); + + dim_pre_de_done_buf_config(pre->curr_ch, false); + + pre->flg_int_done = 0; + + dpre_recyc(pre->curr_ch); + dpre_vdoing(pre->curr_ch); + + spin_unlock_irqrestore(&plist_lock, flags); + + ppre = get_pre_stru(pre->curr_ch); +#if 0 + if (ppre->field_count_for_cont == 1) { + usleep_range(2000, 2001); + pr_info("delay 1ms\n"); + } +#endif + + ret = eDI_WAIT_INT_HAVE_INT; + + } else { + /*check if timeout:*/ + if (di_tout_contr(eDI_TOUT_CONTR_CHECK, &pre->tout)) { + di_pre_wait_irq_set(false); + /*return K_DO_R_FINISH;*/ + ret = eDI_WAIT_INT_TIME_OUT; + } + } + /*debug:*/ + if (dbg_first_cnt_pre) + dbg_first_frame("ch[%d],w_int[%d]\n", pre->curr_ch, ret); + + return ret; +} + +unsigned int dpre_mtotal_wait_int(void *data) +{ + enum eDI_WAIT_INT wret; + unsigned int ret = K_DO_R_NOT_FINISH; + + wret = di_pre_wait_int(NULL); + switch (wret) { + case eDI_WAIT_INT_NEED_WAIT: + ret = K_DO_R_NOT_FINISH; + break; + case eDI_WAIT_INT_HAVE_INT: + ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); + break; + case eDI_WAIT_INT_TIME_OUT: + ret = K_DO_R_FINISH; + break; + } + return ret; +} + +void dpre_mtotal_timeout_contr(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + + /*move from di_pre_trigger_work*/ + if (dimp_get(eDI_MP_di_dbg_mask) & 4) + dim_dump_mif_size_state(pre->pres, pre->psts); + + dimh_enable_di_pre_mif(false, dimp_get(eDI_MP_mcpre_en)); + if (di_get_dts_nrds_en()) + dim_nr_ds_hw_ctrl(false); + pre->pres->pre_de_irq_timeout_count++; + + pre->pres->pre_de_busy = 0; + pre->pres->pre_de_clear_flag = 2; + if ((dimp_get(eDI_MP_di_dbg_mask) & 0x2)) { + pr_info("DI:ch[%d]*****wait %d timeout 0x%x(%d ms)*****\n", + pre->curr_ch, + pre->pres->field_count_for_cont, + Rd(DI_INTR_CTRL), + (unsigned int)(cur_to_msecs() - + pre->pres->irq_time[1])); + } + /*******************************/ + dim_pre_de_done_buf_config(pre->curr_ch, true); + + dpre_recyc(pre->curr_ch); + dpre_vdoing(pre->curr_ch); + /*******************************/ + /*dpre_recyc(pre->curr_ch);*/ +} + +unsigned int dpre_mtotal_timeout(void *data) +{ + ulong flags = 0; + + spin_lock_irqsave(&plist_lock, flags); + dpre_mtotal_timeout_contr(); + spin_unlock_irqrestore(&plist_lock, flags); + + return K_DO_R_JUMP(K_DO_TABLE_ID_STOP); +} + +const struct do_table_ops_s pr_mode_total[] = { + /*fix*/ + [K_DO_TABLE_ID_PAUSE] = { + .id = K_DO_TABLE_ID_PAUSE, + .mark = 0, + .con = NULL, + .do_op = NULL, + .do_stop_op = NULL, + .name = "pause", + }, + [K_DO_TABLE_ID_STOP] = { + .id = K_DO_TABLE_ID_STOP, + .mark = 0, + .con = NULL, + .do_op = NULL, + .do_stop_op = NULL, + .name = "stop", + }, + /******************/ + [K_DO_TABLE_ID_START] = { /*eDI_PRE_MT_CHECK*/ + .id = K_DO_TABLE_ID_START, + .mark = 0, + .con = NULL, + .do_op = dpre_mtotal_check, + .do_stop_op = NULL, + .name = "start-check", + }, + [eDI_PRE_MT_SET] = { + .id = eDI_PRE_MT_SET, + .mark = 0, + .con = NULL, + .do_op = dpre_mtotal_set, + .do_stop_op = NULL, + .name = "set", + }, + [eDI_PRE_MT_WAIT_INT] = { + .id = eDI_PRE_MT_WAIT_INT, + .mark = 0, + .con = NULL, + .do_op = dpre_mtotal_wait_int, + .do_stop_op = NULL, + .name = "wait_int", + }, + [eDI_PRE_MT_TIME_OUT] = { + .id = eDI_PRE_MT_TIME_OUT, + .mark = 0, + .con = NULL, + .do_op = dpre_mtotal_timeout, + .do_stop_op = NULL, + .name = "timeout", + }, +}; + +/**************************** + * + * mode for p + * + ****************************/ +enum eDI_PRE_MP { + eDI_PRE_MP_CHECK = K_DO_TABLE_ID_START, + eDI_PRE_MP_SET, + eDI_PRE_MP_WAIT_INT, + eDI_PRE_MP_TIME_OUT, + eDI_PRE_MP_CHECK2, + eDI_PRE_MP_SET2, + eDI_PRE_MP_WAIT_INT2, + eDI_PRE_MP_TIME_OUT2, +}; + +unsigned int dpre_mp_check(void *data) +{ + struct di_hpre_s *pre = get_hw_pre(); + unsigned int ret = K_DO_R_NOT_FINISH; + + if ((pre_run_flag == DI_RUN_FLAG_RUN) || + (pre_run_flag == DI_RUN_FLAG_STEP)) { + if (pre_run_flag == DI_RUN_FLAG_STEP) + pre_run_flag = DI_RUN_FLAG_STEP_DONE; + /*dim_print("%s:\n", __func__);*/ + if (dim_pre_de_buf_config(pre->curr_ch)) { + /*pre->flg_wait_int = false;*/ + /*pre_p_asi_set_next(pre->curr_ch);*/ + ret = K_DO_R_FINISH; + } else { + /*pre->flg_wait_int = false;*/ + ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); + } + dim_dbg_pre_cnt(pre->curr_ch, "x"); + } + + return ret; +} + +unsigned int dpre_mp_check2(void *data) +{ + struct di_hpre_s *pre = get_hw_pre(); + unsigned int ret = K_DO_R_NOT_FINISH; + + if (dim_pre_de_buf_config(pre->curr_ch)) { + /*pre->flg_wait_int = false;*/ + ret = K_DO_R_FINISH; + } + #if 0 + else { + PR_ERR("%s:not second?ch[%d]\n", __func__, pre->curr_ch); + ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); + } + #endif + + return ret; +} + +unsigned int dpre_mp_wait_int(void *data) +{ + enum eDI_WAIT_INT wret; + unsigned int ret = K_DO_R_NOT_FINISH; + + wret = di_pre_wait_int(NULL); + switch (wret) { + case eDI_WAIT_INT_NEED_WAIT: + ret = K_DO_R_NOT_FINISH; + break; + case eDI_WAIT_INT_HAVE_INT: + ret = K_DO_R_JUMP(eDI_PRE_MP_CHECK2); + break; + case eDI_WAIT_INT_TIME_OUT: + ret = K_DO_R_FINISH; + break; + } + return ret; +} + +unsigned int dpre_mp_wait_int2(void *data) +{ + enum eDI_WAIT_INT wret; + unsigned int ret = K_DO_R_NOT_FINISH; + + wret = di_pre_wait_int(NULL); + switch (wret) { + case eDI_WAIT_INT_NEED_WAIT: + ret = K_DO_R_NOT_FINISH; + break; + case eDI_WAIT_INT_HAVE_INT: + ret = K_DO_R_JUMP(K_DO_TABLE_ID_STOP); + break; + case eDI_WAIT_INT_TIME_OUT: + ret = K_DO_R_FINISH; + break; + } + return ret; +} + +unsigned int dpre_mp_timeout(void *data) +{ + dpre_mtotal_timeout_contr(); + + return K_DO_R_FINISH; +} + +unsigned int dpre_mp_timeout2(void *data) +{ + dpre_mtotal_timeout_contr(); + + return K_DO_R_JUMP(K_DO_TABLE_ID_STOP); +} + +const struct do_table_ops_s pre_mode_proc[] = { + /*fix*/ + [K_DO_TABLE_ID_PAUSE] = { + .id = K_DO_TABLE_ID_PAUSE, + .mark = 0, + .con = NULL, + .do_op = NULL, + .do_stop_op = NULL, + .name = "pause", + }, + [K_DO_TABLE_ID_STOP] = { + .id = K_DO_TABLE_ID_STOP, + .mark = 0, /*stop / pause*/ + .con = NULL, + .do_op = NULL, + .do_stop_op = NULL, + .name = "stop", + }, + /******************/ + [K_DO_TABLE_ID_START] = { /*eDI_PRE_MP_CHECK*/ + .id = K_DO_TABLE_ID_START, + .mark = 0, /*stop / pause*/ + .con = NULL, + .do_op = dpre_mp_check, + .do_stop_op = NULL, + .name = "start-check", + }, + [eDI_PRE_MP_SET] = { + .id = eDI_PRE_MP_SET, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mtotal_set, + .do_stop_op = NULL, + .name = "pset", + }, + [eDI_PRE_MP_WAIT_INT] = { + .id = eDI_PRE_MP_WAIT_INT, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mp_wait_int, + .do_stop_op = NULL, + .name = "pwait_int", + }, + [eDI_PRE_MP_TIME_OUT] = { + .id = eDI_PRE_MP_TIME_OUT, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mp_timeout, + .do_stop_op = NULL, + .name = "ptimeout", + }, + /******/ + [eDI_PRE_MP_CHECK2] = { /*eDI_PRE_MP_CHECK2*/ + .id = eDI_PRE_MP_CHECK2, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mp_check2, + .do_stop_op = NULL, + .name = "start-check", + }, + [eDI_PRE_MP_SET2] = { + .id = eDI_PRE_MP_SET2, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mtotal_set, + .do_stop_op = NULL, + .name = "psetp2", + }, + [eDI_PRE_MP_WAIT_INT2] = { + .id = eDI_PRE_MP_WAIT_INT2, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mp_wait_int2, + .do_stop_op = NULL, + .name = "pwait_int2", + }, + [eDI_PRE_MP_TIME_OUT2] = { + .id = eDI_PRE_MP_TIME_OUT2, + .mark = 0, /*stop / pause*/ + .con = NULL, /*condition*/ + .do_op = dpre_mp_timeout2, + .do_stop_op = NULL, + .name = "ptimeout2", + }, + +}; + +void pre_mode_setting(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + + if (pre->pre_st != eDI_PRE_ST4_DO_TABLE) + return; + + do_table_working(&pre->sdt_mode); +} + +/*--------------------------*/ +enum eDI_WORK_MODE pre_cfg_count_mode(unsigned int ch, struct vframe_s *vframe) +{ + enum eDI_WORK_MODE pmode; + + if (is_bypass2(vframe, ch)) { + pmode = eDI_WORK_MODE_bypass_all; + return pmode; + } + + if (COM_ME(vframe->type, VIDTYPE_INTERLACE)) { + /*interlace:*/ + pmode = eDI_WORK_MODE_i; + return pmode; + } + + if (dimp_get(eDI_MP_prog_proc_config) & 0x10) + pmode = eDI_WORK_MODE_p_as_p; + else if (is_from_vdin(vframe)) + pmode = eDI_WORK_MODE_p_use_ibuf; + else + pmode = eDI_WORK_MODE_p_as_i; + + return pmode; +} + +unsigned int dpre_check_mode(unsigned int ch) +{ + struct vframe_s *vframe; + unsigned int mode; + + vframe = pw_vf_peek(ch); + + if (!vframe) + return eDI_WORK_MODE_NONE; + mode = pre_cfg_count_mode(ch, vframe);/*eDI_WORK_MODE_all;*/ + + return mode; +} + +/*--------------------------*/ +bool dpre_step4_idle(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + bool reflesh = false; + unsigned int ch; + + ch = pre->curr_ch; + if (!pw_try_sw_ch_next_pre(ch)) + return false; + + if (pre->idle_cnt >= DI_CHANNEL_NUB) { + pre->idle_cnt = 0; + return false; + } + pre->pres = get_pre_stru(pre->curr_ch); + pre->psts = get_post_stru(pre->curr_ch); + + /*state*/ + pre->pre_st++;/*tmp*/ + reflesh = true; + + return reflesh; +} + +bool dpre_step4_check(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + bool reflesh = false; + unsigned int mode; + + /*get vframe and select mode + * now: fix use total table + */ + + mode = dpre_check_mode(pre->curr_ch); + + if (mode == eDI_WORK_MODE_NONE) { + pre->pre_st--; + pre->idle_cnt++; + return true; + } + pre->idle_cnt = 0; + if (mode == eDI_WORK_MODE_p_as_i) { + do_table_init(&pre->sdt_mode, + &pre_mode_proc[0], + ARRAY_SIZE(pre_mode_proc)); + + } else { + do_table_init(&pre->sdt_mode, + &pr_mode_total[0], + ARRAY_SIZE(pr_mode_total)); + } + do_talbe_cmd(&pre->sdt_mode, eDO_TABLE_CMD_START); + + /*state*/ + pre->pre_st++; + reflesh = true; + + return reflesh; +} + +bool dpre_step4_do_table(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + bool reflesh = false; + + if (do_table_is_crr(&pre->sdt_mode, K_DO_TABLE_ID_STOP)) { + pre->pre_st = eDI_PRE_ST4_IDLE; + reflesh = true; + } + return reflesh; +} + +const struct di_func_tab_s di_pre_func_tab4[] = { + {eDI_PRE_ST4_EXIT, NULL}, + {eDI_PRE_ST4_IDLE, dpre_step4_idle}, + {eDI_PRE_ST4_CHECK, dpre_step4_check}, + {eDI_PRE_ST4_DO_TABLE, dpre_step4_do_table}, +}; + +const char * const dpre_state_name4[] = { + "EXIT", + "IDLE", /*swith to next channel?*/ + "CHECK", + "DO_TABLE", +}; + +const char *dpre_state4_name_get(enum eDI_PRE_ST4 state) +{ + if (state > eDI_PRE_ST4_DO_TABLE) + return "nothing"; + + return dpre_state_name4[state]; +} + +bool dpre_process_step4(void) +{ + struct di_hpre_s *pre = get_hw_pre(); + enum eDI_PRE_ST4 pre_st = pre->pre_st; + ulong flags = 0; + + if (pre_st > eDI_PRE_ST4_EXIT) { + spin_lock_irqsave(&plist_lock, flags); + dim_recycle_post_back(pre->curr_ch); + dpre_recyc(pre->curr_ch); + dpre_vdoing(pre->curr_ch); + spin_unlock_irqrestore(&plist_lock, flags); + } + if ((pre_st <= eDI_PRE_ST4_DO_TABLE) && + di_pre_func_tab4[pre_st].func) { + return di_pre_func_tab4[pre_st].func(); + } + + return false; +} diff --git a/drivers/amlogic/media/di_multi/di_pre.h b/drivers/amlogic/media/di_multi/di_pre.h new file mode 100644 index 000000000000..2f46b12df8c8 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_pre.h @@ -0,0 +1,38 @@ +/* + * drivers/amlogic/media/di_multi/di_pre.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_PRE_H__ +#define __DI_PRE_H__ + +void dpre_process(void); + +void dpre_init(void); + +const char *dpre_state_name_get(enum eDI_PRE_ST state); +void dpre_dbg_f_trig(unsigned int cmd); +void pre_vinfo_set(unsigned int ch, + struct vframe_s *ori_vframe); +unsigned int is_vinfo_change(unsigned int ch); +bool dpre_can_exit(unsigned int ch); +bool is_bypass_i_p(void); +bool dim_bypass_detect(unsigned int ch, struct vframe_s *vfm); + +void pre_mode_setting(void); +bool dpre_process_step4(void); +const char *dpre_state4_name_get(enum eDI_PRE_ST4 state); + +#endif /*__DI_PRE_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_que.c b/drivers/amlogic/media/di_multi/di_que.c new file mode 100644 index 000000000000..c1c05e1c192b --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_que.c @@ -0,0 +1,995 @@ +/* + * drivers/amlogic/media/di_multi/di_que.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include + +#include +#include "deinterlace.h" + +#include "di_data_l.h" +#include "di_que.h" +#include "di_vframe.h" + +#include "di_prc.h" + +const char * const di_name_new_que[QUE_NUB] = { + "QUE_IN_FREE", /*0*/ + "QUE_PRE_READY", /*1*/ + "QUE_POST_FREE", /*2*/ + "QUE_POST_READY", /*3*/ + "QUE_POST_BACK", /*4*/ + "QUE_DBG", +/* "QUE_NUB",*/ + +}; + +#define que_dbg dim_print + +static void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype) +{ + struct di_ch_s *pch = get_chdata(ch); + +#if 0 + if (qtype >= QUE_NUB) + return; +#endif + kfifo_reset(&pch->fifo[qtype]); +} + +bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype, unsigned int buf_index) +{ + struct di_ch_s *pch = get_chdata(ch); + +#if 0 + if (qtype >= QUE_NUB) + return false; +#endif + if (kfifo_in(&pch->fifo[qtype], &buf_index, sizeof(unsigned int)) + != sizeof(unsigned int)) + return false; +#if 0 + + /*below for debug: save in que*/ + if (qtype <= QUE_POST_RECYC) { + if (buf_index >= MAX_POST_BUF_NUM) { + pr_err("%s:err:overflow?[%d]\n", __func__, buf_index); + } else { + ppw = &pch->lpost_buf[buf_index]; + ppw->in_qtype = qtype; + } + } +#endif + return true; +} + +bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype, + unsigned int *buf_index) +{ + struct di_ch_s *pch = get_chdata(ch); + unsigned int index; + +#if 0 + if (qtype >= QUE_NUB) + return false; +#endif + if (kfifo_out(&pch->fifo[qtype], &index, sizeof(unsigned int)) + != sizeof(unsigned int)) + return false; + + *buf_index = index; + + return true; +} + +static bool pw_queue_peek(unsigned int ch, enum QUE_TYPE qtype, + unsigned int *buf_index) +{ + struct di_ch_s *pch = get_chdata(ch); + unsigned int index; + +#if 0 + if (qtype >= QUE_NUB) + return false; +#endif + + if (kfifo_out_peek(&pch->fifo[qtype], &index, sizeof(unsigned int)) + != sizeof(unsigned int)) + return false; + + *buf_index = index; + + return true; +} + +bool pw_queue_move(unsigned int ch, enum QUE_TYPE qtypef, enum QUE_TYPE qtypet, + unsigned int *oindex) +{ + struct di_ch_s *pch = get_chdata(ch); + unsigned int index; + + /*struct di_post_buf_s *ppw;*/ /*debug only*/ + +#if 0 + if (qtypef >= QUE_NUB || qtypet >= QUE_NUB) + return false; +#endif + if (kfifo_out(&pch->fifo[qtypef], &index, sizeof(unsigned int)) + != sizeof(unsigned int)) { + PR_ERR("qtypef[%d] is empty\n", qtypef); + return false; + } + if (kfifo_in(&pch->fifo[qtypet], &index, sizeof(unsigned int)) + != sizeof(unsigned int)) { + PR_ERR("qtypet[%d] is full\n", qtypet); + return false; + } + + *oindex = index; +#if 0 + if (qtypet <= QUE_POST_RECYC) { + /*below for debug: save in que*/ + if (index >= MAX_POST_BUF_NUM) { + pr_err("%s:err:overflow?[%d]\n", __func__, index); + } else { + ppw = &pch->lpost_buf[index]; + ppw->in_qtype = qtypet; + } + } +#endif + return true; +} + +bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype) +{ + struct di_ch_s *pch = get_chdata(ch); + + if (kfifo_is_empty(&pch->fifo[qtype])) + return true; + + return false; +} + +int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype) +{ + struct di_ch_s *pch = get_chdata(ch); + unsigned int length; + +#if 0 + if (qtype >= QUE_NUB) + return -1; +#endif + length = kfifo_len(&pch->fifo[qtype]); + length = length / sizeof(unsigned int); + + return length; +} + +/***************************************/ +/*outbuf : array size MAX_FIFO_SIZE*/ +/***************************************/ +bool di_que_list(unsigned int ch, enum QUE_TYPE qtype, unsigned int *outbuf, + unsigned int *rsize) +{ + struct di_ch_s *pch = get_chdata(ch); +/* unsigned int tmp[MAX_FIFO_SIZE + 1];*/ + int i; + unsigned int index; + bool ret = false; + + /*que_dbg("%s:begin\n", __func__);*/ + for (i = 0; i < MAX_FIFO_SIZE; i++) + outbuf[i] = 0xff; + + if (kfifo_is_empty(&pch->fifo[qtype])) { + que_dbg("\t%d:empty\n", qtype); + *rsize = 0; + return true; + } + + ret = true; + memcpy(&pch->fifo[QUE_DBG], &pch->fifo[qtype], + sizeof(pch->fifo[qtype])); + +#if 0 + if (kfifo_is_empty(&pbm->fifo[QUE_DBG])) + pr_err("%s:err, kfifo can not copy?\n", __func__); + +#endif + i = 0; + *rsize = 0; + + while (kfifo_out(&pch->fifo[QUE_DBG], &index, sizeof(unsigned int)) + == sizeof(unsigned int)) { + outbuf[i] = index; + /*pr_info("%d->%d\n",i,index);*/ + i++; + } + *rsize = di_que_list_count(ch, qtype); + #if 0 /*debug only*/ + que_dbg("%s: size[%d]\n", di_name_new_que[qtype], *rsize); + for (i = 0; i < *rsize; i++) + que_dbg("%d,", outbuf[i]); + + que_dbg("\n"); + #endif + /*que_dbg("finish\n");*/ + + return ret; +} + +int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype) +{ + struct di_ch_s *pch = get_chdata(ch); + +#if 0 + if (qtype >= QUE_NUB) + return -1; +#endif + return kfifo_is_empty(&pch->fifo[qtype]); +} + +void di_que_init(unsigned int ch) +{ + int i; + + for (i = 0; i < QUE_NUB; i++) + pw_queue_clear(ch, i); +} + +bool di_que_alloc(unsigned int ch) +{ + int i; + int ret; + bool flg_err; + struct di_ch_s *pch = get_chdata(ch); + + /*kfifo----------------------------*/ + flg_err = 0; + for (i = 0; i < QUE_NUB; i++) { + ret = kfifo_alloc(&pch->fifo[i], + sizeof(unsigned int) * MAX_FIFO_SIZE, + GFP_KERNEL); + if (ret < 0) { + flg_err = 1; + PR_ERR("%s:%d:can't get kfifo\n", __func__, i); + break; + } + pch->flg_fifo[i] = 1; + } +#if 0 + /*canvas-----------------------------*/ + canvas_alloc(); +#endif +/* pdp_clear();*/ + + if (!flg_err) { + /*pbm->flg_fifo = 1;*/ + pr_info("%s:ok\n", __func__); + ret = true; + } else { + di_que_release(ch); + ret = false; + } + + return ret; +} + +void di_que_release(unsigned int ch) +{ + struct di_ch_s *pch = get_chdata(ch); + int i; + +/* canvas_release();*/ + for (i = 0; i < QUE_NUB; i++) { + if (pch->flg_fifo[i]) { + kfifo_free(&pch->fifo[i]); + pch->flg_fifo[i] = 0; + } + } + + pr_info("%s:ok\n", __func__); +} + +/******************************************** + *get di_buf from index that same in que + * (di_buf->type << 8) | (di_buf->index) + ********************************************/ +struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex) +{ + union uDI_QBUF_INDEX index; + struct di_buf_s *di_buf; + struct di_buf_pool_s *pbuf_pool = get_buf_pool(ch); + + index.d32 = qindex; + di_buf = &pbuf_pool[index.b.type - 1].di_buf_ptr[index.b.index]; + + return di_buf; +} + +/********************************************/ +/*get di_buf from index that same in que*/ +/*(di_buf->type << 8) | (di_buf->index)*/ +/********************************************/ +static unsigned int pw_buf_2_qindex(unsigned int ch, struct di_buf_s *pdi_buf) +{ + union uDI_QBUF_INDEX index; + + index.b.index = pdi_buf->index; + index.b.type = pdi_buf->type; + return index.d32; +} + +/*di_buf is out*/ +struct di_buf_s *di_que_out_to_di_buf(unsigned int ch, enum QUE_TYPE qtype) +{ + unsigned int q_index; + struct di_buf_s *pdi_buf = NULL; + + if (!pw_queue_peek(ch, qtype, &q_index)) + return pdi_buf; + + pdi_buf = pw_qindex_2_buf(ch, q_index); + if (!pdi_buf) { + PR_ERR("di:err:%s:buf is null[%d]\n", __func__, q_index); + return NULL; + } + + pw_queue_out(ch, qtype, &q_index); + pdi_buf->queue_index = -1; + + return pdi_buf; +} + +/*di_buf is input*/ +bool di_que_out(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf) +{ + unsigned int q_index; + unsigned int q_index2; + + if (!pw_queue_peek(ch, qtype, &q_index)) + return false; + + q_index2 = pw_buf_2_qindex(ch, di_buf); + if (q_index2 != q_index) { + PR_ERR("di:%s:not map[%d,%d]\n", __func__, q_index2, q_index); + return false; + } + + pw_queue_out(ch, qtype, &q_index); + di_buf->queue_index = -1; + return true; +} + +bool di_que_in(unsigned int ch, enum QUE_TYPE qtype, struct di_buf_s *di_buf) +{ + unsigned int q_index; + + if (!di_buf) { + PR_ERR("di:%s:err:di_buf is NULL,ch[%d],qtype[%d]\n", + __func__, ch, qtype); + return false; + } + if (di_buf->queue_index != -1) { + PR_ERR("di:%s:buf in some que,ch[%d],qt[%d],qi[%d],bi[%d]\n", + __func__, + ch, qtype, di_buf->queue_index, di_buf->index); + return false; + } + + q_index = pw_buf_2_qindex(ch, di_buf); + + if (!pw_queue_in(ch, qtype, q_index)) { + PR_ERR("di:%s:err:can't que in,ch[%d],qtype[%d],q_index[%d]\n", + __func__, + ch, qtype, q_index); + return false; + } + di_buf->queue_index = qtype + QUEUE_NUM; + + if (qtype == QUE_PRE_READY) + dim_print("di:pre_ready in %d\n", di_buf->index); + + return true; +} + +bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype, + struct di_buf_s *di_buf) +{ + unsigned int q_index; + unsigned int arr[MAX_FIFO_SIZE + 1]; + unsigned int asize = 0; + bool ret = false; + unsigned int i; + + if (!di_buf) + return false; + + q_index = pw_buf_2_qindex(ch, di_buf); + + di_que_list(ch, qtype, &arr[0], &asize); + + if (asize == 0) + return ret; + + for (i = 0; i < asize; i++) { + if (arr[i] == q_index) { + ret = true; + break; + } + } + return ret; +} + +/*same as get_di_buf_head*/ +struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype) +{ + struct di_buf_s *di_buf = NULL; + unsigned int q_index; + + if (!pw_queue_peek(ch, qtype, &q_index)) + return di_buf; + di_buf = pw_qindex_2_buf(ch, q_index); + + return di_buf; +} + +bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype) +{ + if (!F_IN(q_type, QUEUE_NEW_THD_MIN, QUEUE_NEW_THD_MAX)) + return false; + *nqtype = (enum QUE_TYPE)(q_type - QUEUE_NUM); + + return true; +} + +/**********************************************************/ +/**********************************************************/ +/*ary add this function for reg ini value, no need wait peek*/ +void queue_init2(unsigned int channel) +{ + int i, j; + struct queue_s *pqueue = get_queue(channel); + + for (i = 0; i < QUEUE_NUM; i++) { + queue_t *q = &pqueue[i]; + + for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++) + q->pool[j] = 0; + + q->in_idx = 0; + q->out_idx = 0; + q->num = 0; + q->type = 0; + if ((i == QUEUE_RECYCLE) || + (i == QUEUE_DISPLAY) || + (i == QUEUE_TMP) || + (i == QUEUE_POST_DOING)) + q->type = 1; + +#if 0 + if ((i == QUEUE_LOCAL_FREE) && dim_get_use_2_int_buf()) + q->type = 2; +#endif + } +} + +void queue_init(unsigned int channel, int local_buffer_num) +{ + int i, j; + struct di_buf_s *pbuf_local = get_buf_local(channel); + struct di_buf_s *pbuf_in = get_buf_in(channel); + struct di_buf_s *pbuf_post = get_buf_post(channel); + struct queue_s *pqueue = get_queue(channel); + struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel); + + for (i = 0; i < QUEUE_NUM; i++) { + queue_t *q = &pqueue[i]; + + for (j = 0; j < MAX_QUEUE_POOL_SIZE; j++) + q->pool[j] = 0; + + q->in_idx = 0; + q->out_idx = 0; + q->num = 0; + q->type = 0; + if ((i == QUEUE_RECYCLE) || + (i == QUEUE_DISPLAY) || + (i == QUEUE_TMP) + /*||(i == QUEUE_POST_DOING)*/ + ) + q->type = 1; + + if ((i == QUEUE_LOCAL_FREE) && + dimp_get(eDI_MP_use_2_interlace_buff)) + q->type = 2; + } + if (local_buffer_num > 0) { + pbuf_pool[VFRAME_TYPE_IN - 1].di_buf_ptr = &pbuf_in[0]; + pbuf_pool[VFRAME_TYPE_IN - 1].size = MAX_IN_BUF_NUM; + + pbuf_pool[VFRAME_TYPE_LOCAL - 1].di_buf_ptr = &pbuf_local[0]; + pbuf_pool[VFRAME_TYPE_LOCAL - 1].size = local_buffer_num; + + pbuf_pool[VFRAME_TYPE_POST - 1].di_buf_ptr = &pbuf_post[0]; + pbuf_pool[VFRAME_TYPE_POST - 1].size = MAX_POST_BUF_NUM; + } +} + +struct di_buf_s *get_di_buf_head(unsigned int channel, int queue_idx) +{ + struct queue_s *pqueue = get_queue(channel); + queue_t *q = &pqueue[queue_idx]; + int idx; + unsigned int pool_idx, di_buf_idx; + struct di_buf_s *di_buf = NULL; + struct di_buf_pool_s *pbuf_pool = get_buf_pool(channel); + enum QUE_TYPE nqtype;/*new que*/ + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s:<%d:%d,%d,%d>\n", __func__, queue_idx, + q->num, q->in_idx, q->out_idx); + /* ****new que***** */ + if (di_que_type_2_new(queue_idx, &nqtype)) + return di_que_peek(channel, nqtype); + + /* **************** */ + + if (q->num > 0) { + if (q->type == 0) { + idx = q->out_idx; + } else { + for (idx = 0; idx < MAX_QUEUE_POOL_SIZE; idx++) + if (q->pool[idx] != 0) + break; + } + if (idx < MAX_QUEUE_POOL_SIZE) { + pool_idx = ((q->pool[idx] >> 8) & 0xff) - 1; + di_buf_idx = q->pool[idx] & 0xff; + + if (pool_idx < VFRAME_TYPE_NUM) { + if (di_buf_idx < pbuf_pool[pool_idx].size) + di_buf = &pbuf_pool[pool_idx].di_buf_ptr[di_buf_idx]; + } + } + } + + if ((di_buf) && ((((pool_idx + 1) << 8) | di_buf_idx) != + ((di_buf->type << 8) | (di_buf->index)))) { + pr_dbg("%s: Error (%x,%x)\n", __func__, + (((pool_idx + 1) << 8) | di_buf_idx), + ((di_buf->type << 8) | (di_buf->index))); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(2); + dim_vcry_set_log_q_idx(queue_idx); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + di_buf = NULL; + } + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) { + if (di_buf) + dim_print("%s: 0x%p(%d,%d)\n", __func__, di_buf, + pool_idx, di_buf_idx); + else + dim_print("%s: 0x%p\n", __func__, di_buf); + } + + return di_buf; +} + +/*ary: note:*/ +/*a. di_buf->queue_index = -1*/ +/*b. */ +void queue_out(unsigned int channel, struct di_buf_s *di_buf) +{ + int i; + queue_t *q; + struct queue_s *pqueue = get_queue(channel); + enum QUE_TYPE nqtype;/*new que*/ + + if (!di_buf) { + PR_ERR("%s:Error\n", __func__); + + if (dim_vcry_get_flg() == 0) + dim_vcry_set_log_reason(3); + + dim_vcry_flg_inc(); + return; + } + /* ****new que***** */ + if (di_que_type_2_new(di_buf->queue_index, &nqtype)) { + di_que_out(channel, nqtype, di_buf); /*?*/ + return; + } + /* **************** */ + + if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) { + q = &pqueue[di_buf->queue_index]; + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, + di_buf->queue_index, q->num, q->in_idx, + q->out_idx, di_buf); + + if (q->num > 0) { + if (q->type == 0) { + if (q->pool[q->out_idx] == + ((di_buf->type << 8) | (di_buf->index))) { + q->num--; + q->pool[q->out_idx] = 0; + q->out_idx++; + if (q->out_idx >= MAX_QUEUE_POOL_SIZE) + q->out_idx = 0; + di_buf->queue_index = -1; + } else { + PR_ERR( + "%s: Error (%d, %x,%x)\n", + __func__, + di_buf->queue_index, + q->pool[q->out_idx], + ((di_buf->type << 8) | + (di_buf->index))); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(4); + dim_vcry_set_log_q_idx(di_buf->queue_index); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + } else if (q->type == 1) { + int pool_val = + (di_buf->type << 8) | (di_buf->index); + for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) { + if (q->pool[i] == pool_val) { + q->num--; + q->pool[i] = 0; + di_buf->queue_index = -1; + break; + } + } + if (i == MAX_QUEUE_POOL_SIZE) { + PR_ERR("%s: Error\n", __func__); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(5); + dim_vcry_set_log_q_idx(di_buf->queue_index); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + } else if (q->type == 2) { + int pool_val = + (di_buf->type << 8) | (di_buf->index); + if ((di_buf->index < MAX_QUEUE_POOL_SIZE) && + (q->pool[di_buf->index] == pool_val)) { + q->num--; + q->pool[di_buf->index] = 0; + di_buf->queue_index = -1; + } else { + PR_ERR("%s: Error\n", __func__); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(5); + dim_vcry_set_log_q_idx(di_buf->queue_index); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + } + } + } else { + PR_ERR("%s: Error, queue_index %d is not right\n", + __func__, di_buf->queue_index); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(6); + dim_vcry_set_log_q_idx(0); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s done\n", __func__); +} + +void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf) +{ + int i; + queue_t *q; + struct queue_s *pqueue = get_queue(channel); + enum QUE_TYPE nqtype;/*new que*/ + + if (!di_buf) { + PR_ERR("%s:Error\n", __func__); + + if (dim_vcry_get_flg() == 0) + dim_vcry_set_log_reason(3); + + dim_vcry_flg_inc(); + return; + } + /* ****new que***** */ + if (di_que_type_2_new(di_buf->queue_index, &nqtype)) { + di_que_out(channel, nqtype, di_buf); /*?*/ + pr_info("dbg1:nqtype=%d\n", nqtype); + return; + } + /* **************** */ + + if (di_buf->queue_index >= 0 && di_buf->queue_index < QUEUE_NUM) { + q = &pqueue[di_buf->queue_index]; + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, + di_buf->queue_index, q->num, q->in_idx, + q->out_idx, di_buf); + + if (q->num > 0) { + if (q->type == 0) { + pr_info("dbg3\n"); + if (q->pool[q->out_idx] == + ((di_buf->type << 8) | (di_buf->index))) { + q->num--; + q->pool[q->out_idx] = 0; + q->out_idx++; + if (q->out_idx >= MAX_QUEUE_POOL_SIZE) + q->out_idx = 0; + di_buf->queue_index = -1; + } else { + PR_ERR( + "%s: Error (%d, %x,%x)\n", + __func__, + di_buf->queue_index, + q->pool[q->out_idx], + ((di_buf->type << 8) | + (di_buf->index))); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(4); + dim_vcry_set_log_q_idx(di_buf->queue_index); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + } else if (q->type == 1) { + int pool_val = + (di_buf->type << 8) | (di_buf->index); + for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) { + if (q->pool[i] == pool_val) { + q->num--; + q->pool[i] = 0; + di_buf->queue_index = -1; + break; + } + } + pr_info("dbg2:i=%d,qindex=%d\n", i, + di_buf->queue_index); + if (i == MAX_QUEUE_POOL_SIZE) { + PR_ERR("%s: Error\n", __func__); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(5); + dim_vcry_set_log_q_idx(di_buf->queue_index); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + } else if (q->type == 2) { + int pool_val = + (di_buf->type << 8) | (di_buf->index); + + pr_info("dbg4\n"); + if ((di_buf->index < MAX_QUEUE_POOL_SIZE) && + (q->pool[di_buf->index] == pool_val)) { + q->num--; + q->pool[di_buf->index] = 0; + di_buf->queue_index = -1; + } else { + PR_ERR("%s: Error\n", __func__); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set(5, + di_buf->queue_index, + di_buf); + } + dim_vcry_flg_inc(); + } + } + } + } else { + PR_ERR("%s: Error, queue_index %d is not right\n", + __func__, di_buf->queue_index); + + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(6); + dim_vcry_set_log_q_idx(0); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + } + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s done\n", __func__); +} + +/***************************************/ +/* set di_buf->queue_index*/ +/***************************************/ +void queue_in(unsigned int channel, struct di_buf_s *di_buf, int queue_idx) +{ + queue_t *q = NULL; + struct queue_s *pqueue = get_queue(channel); + enum QUE_TYPE nqtype;/*new que*/ + + if (!di_buf) { + PR_ERR("%s:Error\n", __func__); + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(7); + dim_vcry_set_log_q_idx(queue_idx); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + return; + } + /* ****new que***** */ + if (di_que_type_2_new(queue_idx, &nqtype)) { + di_que_in(channel, nqtype, di_buf); + return; + } + /* **************** */ + if (di_buf->queue_index != -1) { + PR_ERR("%s:%s[%d] queue_index(%d) is not -1, to que[%d]\n", + __func__, dim_get_vfm_type_name(di_buf->type), + di_buf->index, di_buf->queue_index, queue_idx); + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(8); + dim_vcry_set_log_q_idx(queue_idx); + dim_vcry_set_log_di_buf(di_buf); + } + dim_vcry_flg_inc(); + return; + } + q = &pqueue[queue_idx]; + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s:<%d:%d,%d,%d> 0x%p\n", __func__, queue_idx, + q->num, q->in_idx, q->out_idx, di_buf); + + if (q->type == 0) { + q->pool[q->in_idx] = (di_buf->type << 8) | (di_buf->index); + di_buf->queue_index = queue_idx; + q->in_idx++; + if (q->in_idx >= MAX_QUEUE_POOL_SIZE) + q->in_idx = 0; + + q->num++; + } else if (q->type == 1) { + int i; + + for (i = 0; i < MAX_QUEUE_POOL_SIZE; i++) { + if (q->pool[i] == 0) { + q->pool[i] = + (di_buf->type << 8) | (di_buf->index); + di_buf->queue_index = queue_idx; + q->num++; + break; + } + } + if (i == MAX_QUEUE_POOL_SIZE) { + pr_dbg("%s: Error\n", __func__); + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(9); + dim_vcry_set_log_q_idx(queue_idx); + } + dim_vcry_flg_inc(); + } + } else if (q->type == 2) { + if ((di_buf->index < MAX_QUEUE_POOL_SIZE) && + (q->pool[di_buf->index] == 0)) { + q->pool[di_buf->index] = + (di_buf->type << 8) | (di_buf->index); + di_buf->queue_index = queue_idx; + q->num++; + } else { + pr_dbg("%s: Error\n", __func__); + if (dim_vcry_get_flg() == 0) { + dim_vcry_set_log_reason(9); + dim_vcry_set_log_q_idx(queue_idx); + } + dim_vcry_flg_inc(); + } + } + + if (dimp_get(eDI_MP_di_log_flag) & DI_LOG_QUEUE) + dim_print("%s done\n", __func__); +} + +int list_count(unsigned int channel, int queue_idx) +{ + struct queue_s *pqueue; + enum QUE_TYPE nqtype;/*new que*/ + + /* ****new que***** */ + if (di_que_type_2_new(queue_idx, &nqtype)) { + PR_ERR("%s:err: over flow\n", __func__); + return di_que_list_count(channel, nqtype); + } + /* **************** */ + + pqueue = get_queue(channel); + return pqueue[queue_idx].num; +} + +bool queue_empty(unsigned int channel, int queue_idx) +{ + struct queue_s *pqueue; + bool ret; + enum QUE_TYPE nqtype;/*new que*/ + + /* ****new que***** */ + if (di_que_type_2_new(queue_idx, &nqtype)) { + PR_ERR("%s:err: over flow\n", __func__); + return di_que_is_empty(channel, nqtype); + } + /* **************** */ + + pqueue = get_queue(channel); + ret = (pqueue[queue_idx].num == 0); + + return ret; +} + +bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf, int queue_idx) +{ + bool ret = 0; + struct di_buf_s *p = NULL; + int itmp; + unsigned int overflow_cnt; + enum QUE_TYPE nqtype;/*new que*/ + + /* ****new que***** */ + if (di_que_type_2_new(queue_idx, &nqtype)) + return di_que_is_in_que(channel, nqtype, di_buf); + + /* **************** */ + + overflow_cnt = 0; + if (!di_buf || (queue_idx < 0) || (queue_idx >= QUEUE_NUM)) { + ret = 0; + dim_print("%s: not in queue:%d!!!\n", __func__, queue_idx); + return ret; + } + queue_for_each_entry(p, channel, queue_idx, list) { + if (p == di_buf) { + ret = 1; + break; + } + if (overflow_cnt++ > MAX_QUEUE_POOL_SIZE) { + ret = 0; + dim_print("%s: overflow_cnt!!!\n", __func__); + break; + } + } + return ret; +} + diff --git a/drivers/amlogic/media/di_multi/di_que.h b/drivers/amlogic/media/di_multi/di_que.h new file mode 100644 index 000000000000..f2f35ab0332d --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_que.h @@ -0,0 +1,76 @@ +/* + * drivers/amlogic/media/di_multi/di_que.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_QUE_H__ +#define __DI_QUE_H__ + +void queue_init(unsigned int channel, int local_buffer_num); +void queue_out(unsigned int channel, struct di_buf_s *di_buf); +void queue_in(unsigned int channel, struct di_buf_s *di_buf, + int queue_idx); +int list_count(unsigned int channel, int queue_idx); +bool queue_empty(unsigned int channel, int queue_idx); +bool is_in_queue(unsigned int channel, struct di_buf_s *di_buf, + int queue_idx); +struct di_buf_s *get_di_buf_head(unsigned int channel, + int queue_idx); + +void queue_init2(unsigned int channel); + +/*new buf:*/ +bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype, + unsigned int buf_index); +bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype, + unsigned int *buf_index); +bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype); + +/******************************************/ +/*new api*/ +/******************************************/ +union uDI_QBUF_INDEX { + unsigned int d32; + struct { + unsigned int index:8, /*low*/ + type:8, + reserved0:16; + } b; +}; + +void di_que_init(unsigned int ch); +bool di_que_alloc(unsigned int ch); +void di_que_release(unsigned int ch); + +int di_que_is_empty(unsigned int ch, enum QUE_TYPE qtype); +bool di_que_out(unsigned int ch, enum QUE_TYPE qtype, + struct di_buf_s *di_buf); + +struct di_buf_s *di_que_out_to_di_buf(unsigned int ch, + enum QUE_TYPE qtype); +bool di_que_in(unsigned int ch, enum QUE_TYPE qtype, + struct di_buf_s *di_buf); +bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype, + struct di_buf_s *di_buf); +struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype); +bool di_que_type_2_new(unsigned int q_type, enum QUE_TYPE *nqtype); +int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype); +bool di_que_list(unsigned int ch, enum QUE_TYPE qtype, + unsigned int *outbuf, unsigned int *rsize); + +struct di_buf_s *pw_qindex_2_buf(unsigned int ch, unsigned int qindex); + +void queue_out_dbg(unsigned int channel, struct di_buf_s *di_buf); +#endif /*__DI_QUE_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_reg_tab.c b/drivers/amlogic/media/di_multi/di_reg_tab.c new file mode 100644 index 000000000000..750f10662edd --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_reg_tab.c @@ -0,0 +1,249 @@ +/* + * drivers/amlogic/media/di_multi/di_reg_tab.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include + +#include "deinterlace.h" +#include "di_data_l.h" +#include "register.h" + +static const struct reg_t rtab_contr[] = { + /*--------------------------*/ + {VD1_AFBCD0_MISC_CTRL, 20, 2, 0, "VD1_AFBCD0_MISC_CTRL", + "vd1_go_field_sel", + "0: gofile;1: post;2: pre"}, + {VD1_AFBCD0_MISC_CTRL, 9, 1, 0, "", + "afbc0_mux_vpp_mad", + "afbc0 to 0:vpp; 1:di"}, + {VD1_AFBCD0_MISC_CTRL, 8, 1, 0, "", + "di_mif0_en", + ":mif to 0-vpp;1-di"}, + /*--------------------------*/ + {DI_POST_CTRL, 12, 1, 0, "DI_POST_CTRL", + "di_post_viu_link", + ""}, + {DI_POST_CTRL, 8, 1, 0, "", + "di_vpp_out_en", + ""}, + /*--------------------------*/ + {VIU_MISC_CTRL0, 20, 1, 0, "VIU_MISC_CTRL0", + "?", + "?"}, + {VIU_MISC_CTRL0, 18, 1, 0, "", + "Vdin0_wr_out_ctrl", + "0: nr_inp to vdin; 1: vdin wr dout"}, + {VIU_MISC_CTRL0, 17, 1, 0, "", + "Afbc_inp_sel", + "0: mif to INP; 1: afbc to INP"}, + {VIU_MISC_CTRL0, 16, 1, 0, "", + "di_mif0_en", + " vd1(afbc) to di post(if0) enable"}, + /*--------------------------*/ + {DI_IF1_GEN_REG, 0, 1, 0, "DI_IF1_GEN_REG", + "enable", + ""}, + + /*--------------------------*/ + {DI_IF1_GEN_REG3, 8, 2, 0, "DI_IF1_GEN_REG3", + "cntl_bits_mode", + "0:8bit;1:10bit 422;2:10bit 444"}, + + /*--------------------------*/ + {DI_IF2_GEN_REG3, 8, 2, 0, "DI_IF2_GEN_REG3", + "cntl_bits_mode", + "0:8bit;1:10bit 422;2:10bit 444"}, + + /*--------------------------*/ + {DI_IF0_GEN_REG3, 8, 2, 0, "DI_IF0_GEN_REG3", + "cntl_bits_mode", + "0:8bit;1:10bit 422;2:10bit 444"}, + + /*--------------------------*/ + {DI_POST_GL_CTRL, 31, 1, 0, "DI_POST_GL_CTRL", + "post count enable", + ""}, + {DI_POST_GL_CTRL, 30, 1, 0, "", + "post count reset", + ""}, + {DI_POST_GL_CTRL, 16, 14, 0, "", + "total line number for post count", + ""}, + {DI_POST_GL_CTRL, 0, 14, 0, "", + "the line number of post frame reset", + ""}, + + {TABLE_FLG_END, 0, 0, 0, "end", "end", ""}, + +}; + +/**********************/ +/* debug register */ +/**********************/ +static unsigned int get_reg_bits(unsigned int val, unsigned int bstart, + unsigned int bw) +{ + return((val & + (((1L << bw) - 1) << bstart)) >> (bstart)); +} + +static void dbg_reg_tab(struct seq_file *s, const struct reg_t *pRegTab) +{ + struct reg_t creg; + int i; + unsigned int l_add; + unsigned int val32 = 1, val; + char *bname; + char *info; + + i = 0; + l_add = 0; + creg = pRegTab[i]; + + do { + if (creg.add != l_add) { + val32 = Rd(creg.add); /*RD*/ + seq_printf(s, "add:0x%x = 0x%08x, %s\n", + creg.add, val32, creg.name); + l_add = creg.add; + } + val = get_reg_bits(val32, creg.bit, creg.wid); /*RD_B*/ + + if (creg.bname) + bname = creg.bname; + else + bname = ""; + if (creg.info) + info = creg.info; + else + info = ""; + + seq_printf(s, "\tbit[%d,%d]:\t0x%x[%d]:\t%s:\t%s\n", + creg.bit, creg.wid, val, val, bname, info); + + i++; + creg = pRegTab[i]; + if (i > TABLE_LEN_MAX) { + pr_info("warn: too long, stop\n"); + break; + } + } while (creg.add != TABLE_FLG_END); +} + +int reg_con_show(struct seq_file *seq, void *v) +{ + dbg_reg_tab(seq, &rtab_contr[0]); + return 0; +} + +static const struct reg_t rtab_cue_int[] = { + /*--------------------------*/ + {NR2_CUE_CON_DIF0, 0, 32, 0x1400, "NR2_CUE_CON_DIF0", + NULL, + NULL}, + {NR2_CUE_CON_DIF1, 0, 32, 0x80064, "NR2_CUE_CON_DIF1", + NULL, + NULL}, + {NR2_CUE_CON_DIF2, 0, 32, 0x80064, "NR2_CUE_CON_DIF2", + NULL, + NULL}, + {NR2_CUE_CON_DIF3, 0, 32, 0x80a0a, "NR2_CUE_CON_DIF3", + NULL, + NULL}, + {NR2_CUE_PRG_DIF, 0, 32, 0x80a0a, "NR2_CUE_PRG_DIF", + NULL, + NULL}, + {TABLE_FLG_END, 0, 0, 0, "end", "end", ""}, + /*--------------------------*/ +}; + +/************************************************ + * register table + ************************************************/ +static bool di_g_rtab_cue(const struct reg_t **tab, unsigned int *tabsize) +{ + *tab = &rtab_cue_int[0]; + *tabsize = ARRAY_SIZE(rtab_cue_int); + + return true; +} + +static unsigned int dim_reg_read(unsigned int addr) +{ + return aml_read_vcbus(addr); +} + +static const struct reg_acc di_pre_regset = { + .wr = dim_DI_Wr, + .rd = dim_reg_read, + .bwr = dim_RDMA_WR_BITS, + .brd = dim_RDMA_RD_BITS, +}; + +static bool di_wr_tab(const struct reg_acc *ops, + const struct reg_t *ptab, unsigned int tabsize) +{ + int i; + const struct reg_t *pl; + + pl = ptab; + + if (!ops || + !tabsize || + !ptab) + return false; + + for (i = 0; i < tabsize; i++) { + if (pl->add == TABLE_FLG_END || + i > TABLE_LEN_MAX) { + break; + } + + if (pl->wid == 32) + ops->wr(pl->add, pl->df_val); + else + ops->bwr(pl->add, pl->df_val, pl->bit, pl->wid); + + pl++; + } + + return true; +} + +bool dim_wr_cue_int(void) +{ + const struct reg_t *ptab; + unsigned int tabsize; + + di_g_rtab_cue(&ptab, &tabsize); + di_wr_tab(&di_pre_regset, + ptab, + tabsize); + PR_INF("%s:finish\n", __func__); + + return true; +} + +int dim_reg_cue_int_show(struct seq_file *seq, void *v) +{ + dbg_reg_tab(seq, &rtab_cue_int[0]); + return 0; +} + diff --git a/drivers/amlogic/media/di_multi/di_reg_tab.h b/drivers/amlogic/media/di_multi/di_reg_tab.h new file mode 100644 index 000000000000..215d378a6e50 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_reg_tab.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/media/di_multi/di_reg_tab.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_REG_TABL_H__ +#define __DI_REG_TABL_H__ + +int reg_con_show(struct seq_file *seq, void *v); + +bool dim_wr_cue_int(void); +int dim_reg_cue_int_show(struct seq_file *seq, void *v); + +#endif /*__DI_REG_TABL_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_sys.c b/drivers/amlogic/media/di_multi/di_sys.c new file mode 100644 index 000000000000..64be0556e67c --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_sys.c @@ -0,0 +1,754 @@ +/* + * drivers/amlogic/media/di_multi/di_sys.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/*dma_get_cma_size_int_byte*/ +#include + +#include "deinterlace_dbg.h" +#include "deinterlace.h" +#include "di_data_l.h" +#include "di_data.h" +#include "di_dbg.h" +#include "di_vframe.h" +#include "di_task.h" +#include "di_prc.h" +#include "di_sys.h" +#include "di_api.h" + +#include "register.h" +#include "nr_downscale.h" + +static di_dev_t *di_pdev; + +struct di_dev_s *get_dim_de_devp(void) +{ + return di_pdev; +} + +unsigned int di_get_dts_nrds_en(void) +{ + return get_dim_de_devp()->nrds_enable; +} + +/******************************************** + * mem + *******************************************/ + +/********************************************/ +static ssize_t +show_config(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + + return pos; +} + +static ssize_t show_tvp_region(struct device *dev, + struct device_attribute *attr, char *buff) +{ + ssize_t len = 0; + struct di_dev_s *de_devp = get_dim_de_devp(); + + len = sprintf(buff, "segment DI:%lx - %lx (size:0x%x)\n", + de_devp->mem_start, + de_devp->mem_start + de_devp->mem_size - 1, + de_devp->mem_size); + return len; +} + +static +ssize_t +show_log(struct device *dev, struct device_attribute *attr, char *buf) +{ + return dim_read_log(buf); +} + +static ssize_t +show_frame_format(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned int channel = get_current_channel(); /*debug only*/ + struct di_pre_stru_s *ppre = get_pre_stru(channel); + + if (get_init_flag(channel)) + ret += sprintf(buf + ret, "%s\n", + ppre->cur_prog_flag + ? "progressive" : "interlace"); + + else + ret += sprintf(buf + ret, "%s\n", "null"); + + return ret; +} + +static DEVICE_ATTR(frame_format, 0444, show_frame_format, NULL); +static DEVICE_ATTR(config, 0640, show_config, store_config); +static DEVICE_ATTR(debug, 0200, NULL, store_dbg); +static DEVICE_ATTR(dump_pic, 0200, NULL, store_dump_mem); +static DEVICE_ATTR(log, 0640, show_log, store_log); +static DEVICE_ATTR(provider_vframe_status, 0444, show_vframe_status, NULL); +static DEVICE_ATTR(tvp_region, 0444, show_tvp_region, NULL); + +/********************************************/ +static int di_open(struct inode *node, struct file *file) +{ + di_dev_t *di_in_devp; + +/* Get the per-device structure that contains this cdev */ + di_in_devp = container_of(node->i_cdev, di_dev_t, cdev); + file->private_data = di_in_devp; + + return 0; +} + +static int di_release(struct inode *node, struct file *file) +{ +/* di_dev_t *di_in_devp = file->private_data; */ + +/* Reset file pointer */ + +/* Release some other fields */ + file->private_data = NULL; + return 0; +} + +static long di_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + + if (_IOC_TYPE(cmd) != _DI_) { + PR_ERR("%s invalid command: %u\n", __func__, cmd); + return -EFAULT; + } + +#if 0 + dbg_reg("no pq\n"); + return 0; +#endif + switch (cmd) { + case AMDI_IOC_SET_PQ_PARM: + ret = dim_pq_load_io(arg); + + break; + default: + break; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long di_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long ret; + + arg = (unsigned long)compat_ptr(arg); + ret = di_ioctl(file, cmd, arg); + return ret; +} +#endif + +static const struct file_operations di_fops = { + .owner = THIS_MODULE, + .open = di_open, + .release = di_release, + .unlocked_ioctl = di_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = di_compat_ioctl, +#endif +}; + +static int dim_rev_mem(struct di_dev_s *di_devp) +{ + unsigned int ch; + unsigned int o_size; + unsigned long rmstart; + unsigned int rmsize; + unsigned int flg_map; + + if (di_devp && !di_devp->flag_cma) { + dil_get_rev_mem(&rmstart, &rmsize); + dil_get_flg(&flg_map); + if (!rmstart) { + PR_ERR("%s:reserved mem start add is 0\n", __func__); + return -1; + } + di_devp->mem_start = rmstart; + di_devp->mem_size = rmsize; + + if (!flg_map) + di_devp->flags |= DI_MAP_FLAG; + + o_size = rmsize / DI_CHANNEL_NUB; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + di_set_mem_info(ch, + di_devp->mem_start + (o_size * ch), + o_size); + PR_INF("rmem:ch[%d]:start:0x%lx, size:%uB\n", + ch, + (di_devp->mem_start + (o_size * ch)), + o_size); + } + PR_INF("rmem:0x%lx, size %uMB.\n", + di_devp->mem_start, (di_devp->mem_size >> 20)); + + di_devp->mem_flg = true; + return 0; + } + PR_INF("%s:no dev or no rev mem\n", __func__); + return -1; +} + +bool dim_rev_mem_check(void)/*tmp*/ +{ + di_dev_t *di_devp = get_dim_de_devp(); + + if (di_devp && !di_devp->flag_cma && di_devp->mem_flg) + return true; + + if (!di_devp) { + PR_ERR("%s:no dev\n", __func__); + return false; + } + PR_INF("%s\n", __func__); + dim_rev_mem(di_devp); + + return true; +} + +#define ARY_MATCH (1) +#ifdef ARY_MATCH + +static const struct di_meson_data data_g12a = { + .name = "dim_g12a", +}; + +static const struct di_meson_data data_sm1 = { + .name = "dim_sm1", +}; + +/* #ifdef CONFIG_USE_OF */ +static const struct of_device_id amlogic_deinterlace_dt_match[] = { + /*{ .compatible = "amlogic, deinterlace", },*/ + { .compatible = "amlogic, dim-g12a", + .data = &data_g12a, + }, { .compatible = "amlogic, dim-g12b", + .data = &data_sm1, + }, { .compatible = "amlogic, dim-sm1", + .data = &data_sm1, + }, {} +}; +#endif +static int dim_probe(struct platform_device *pdev) +{ + int ret = 0; + struct di_dev_s *di_devp = NULL; + int i; +#ifdef ARY_MATCH + const struct of_device_id *match; + struct di_data_l_s *pdata; +#endif + PR_INF("%s:\n", __func__); + +#if 1 /*move from init to here*/ + + di_pdev = kzalloc(sizeof(*di_pdev), GFP_KERNEL); + if (!di_pdev) { + PR_ERR("%s fail to allocate memory.\n", __func__); + goto fail_kmalloc_dev; + } + + /******************/ + ret = alloc_chrdev_region(&di_pdev->devno, 0, DI_COUNT, DEVICE_NAME); + if (ret < 0) { + PR_ERR("%s: failed to allocate major number\n", __func__); + goto fail_alloc_cdev_region; + } + PR_INF("%s: major %d\n", __func__, MAJOR(di_pdev->devno)); + di_pdev->pclss = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(di_pdev->pclss)) { + ret = PTR_ERR(di_pdev->pclss); + PR_ERR("%s: failed to create class\n", __func__); + goto fail_class_create; + } +#endif + + di_devp = di_pdev; + /* *********new********* */ + di_pdev->data_l = NULL; + di_pdev->data_l = kzalloc(sizeof(struct di_data_l_s), GFP_KERNEL); + if (!di_pdev->data_l) { + PR_ERR("%s fail to allocate data l.\n", __func__); + goto fail_kmalloc_datal; + } + /*memset(di_pdev->data_l, 0, sizeof(struct di_data_l_s));*/ + /*pr_info("\tdata size: %ld\n", sizeof(struct di_data_l_s));*/ + /************************/ + if (!dip_prob()) + goto fail_cdev_add; + + di_devp->flags |= DI_SUSPEND_FLAG; + cdev_init(&di_devp->cdev, &di_fops); + di_devp->cdev.owner = THIS_MODULE; + ret = cdev_add(&di_devp->cdev, di_devp->devno, DI_COUNT); + if (ret) + goto fail_cdev_add; + + di_devp->devt = MKDEV(MAJOR(di_devp->devno), 0); + di_devp->dev = device_create(di_devp->pclss, &pdev->dev, + di_devp->devt, di_devp, "di%d", 0); + + if (!di_devp->dev) { + pr_error("device_create create error\n"); + goto fail_cdev_add; + } + dev_set_drvdata(di_devp->dev, di_devp); + platform_set_drvdata(pdev, di_devp); + +#ifdef ARY_MATCH + /************************/ + match = of_match_device(amlogic_deinterlace_dt_match, + &pdev->dev); + if (!match) { + PR_ERR("%s,no matched table\n", __func__); + goto fail_cdev_add; + } + pdata = (struct di_data_l_s *)di_pdev->data_l; + pdata->mdata = match->data; + PR_INF("match name: %s\n", pdata->mdata->name); +#endif + + ret = of_reserved_mem_device_init(&pdev->dev); + if (ret != 0) + PR_INF("no reserved mem.\n"); + + ret = of_property_read_u32(pdev->dev.of_node, + "flag_cma", &di_devp->flag_cma); + if (ret) + PR_ERR("DI-%s: get flag_cma error.\n", __func__); + else + PR_INF("flag_cma=%d\n", di_devp->flag_cma); + + dim_rev_mem(di_devp); + + ret = of_property_read_u32(pdev->dev.of_node, + "nrds-enable", &di_devp->nrds_enable); + ret = of_property_read_u32(pdev->dev.of_node, + "pps-enable", &di_devp->pps_enable); + + /*di pre h scaling down :sm1 tm2*/ + /*pre_hsc_down_en;*/ + di_devp->h_sc_down_en = di_mp_uit_get(eDI_MP_pre_hsc_down_en); + + if (di_devp->flag_cma >= 1) { +#ifdef CONFIG_CMA + di_devp->pdev = pdev; + di_devp->flags |= DI_MAP_FLAG; + #if 0 + di_devp->mem_size = dma_get_cma_size_int_byte(&pdev->dev); + #else + if (di_devp->flag_cma == 1 || + di_devp->flag_cma == 2) { + di_devp->mem_size + = dma_get_cma_size_int_byte(&pdev->dev); + PR_INF("mem size from dts:0x%x\n", di_devp->mem_size); + } + + if (di_devp->mem_size <= 0x800000) {/*need check??*/ + di_devp->mem_size = 0x2800000; + /*(flag_cma ? 3) reserved in*/ + /*codec mm : cma in codec mm*/ + if (di_devp->flag_cma != 3) { + /*no di cma, try use*/ + /*cma from codec mm*/ + di_devp->flag_cma = 4; + } + } + #endif + pr_info("DI: CMA size 0x%x.\n", di_devp->mem_size); + if (di_devp->flag_cma == 2) { + if (dim_cma_alloc_total(di_devp)) + dip_cma_st_set_ready_all(); + } +#endif + } else { + dip_cma_st_set_ready_all(); + } + /* mutex_init(&di_devp->cma_mutex); */ + INIT_LIST_HEAD(&di_devp->pq_table_list); + + atomic_set(&di_devp->pq_flag, 0); + + di_devp->pre_irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + pr_info("pre_irq:%d\n", + di_devp->pre_irq); + di_devp->post_irq = irq_of_parse_and_map(pdev->dev.of_node, 1); + pr_info("post_irq:%d\n", + di_devp->post_irq); + + di_pr_info("%s allocate rdma channel %d.\n", __func__, + di_devp->rdma_handle); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + dim_get_vpu_clkb(&pdev->dev, di_devp); + #ifdef CLK_TREE_SUPPORT + clk_prepare_enable(di_devp->vpu_clkb); + pr_info("DI:enable vpu clkb.\n"); + #else + aml_write_hiubus(HHI_VPU_CLKB_CNTL, 0x1000100); + #endif + } + di_devp->flags &= (~DI_SUSPEND_FLAG); + ret = of_property_read_u32(pdev->dev.of_node, + "buffer-size", &di_devp->buffer_size); + if (ret) + PR_ERR("DI-%s: get buffer size error.\n", __func__); + + /* set flag to indicate that post_wr is supportted */ + ret = of_property_read_u32(pdev->dev.of_node, + "post-wr-support", + &di_devp->post_wr_support); + if (ret) + dimp_set(eDI_MP_post_wr_support, 0);/*post_wr_support = 0;*/ + else /*post_wr_support = di_devp->post_wr_support;*/ + dimp_set(eDI_MP_post_wr_support, di_devp->post_wr_support); + + ret = of_property_read_u32(pdev->dev.of_node, + "nr10bit-support", + &di_devp->nr10bit_support); + if (ret) + dimp_set(eDI_MP_nr10bit_support, 0);/*nr10bit_support = 0;*/ + else /*nr10bit_support = di_devp->nr10bit_support;*/ + dimp_set(eDI_MP_nr10bit_support, di_devp->nr10bit_support); + +#ifdef DI_USE_FIXED_CANVAS_IDX + if (dim_get_canvas()) { + pr_dbg("DI get canvas error.\n"); + ret = -EEXIST; + return ret; + } +#endif + + device_create_file(di_devp->dev, &dev_attr_config); + device_create_file(di_devp->dev, &dev_attr_debug); + device_create_file(di_devp->dev, &dev_attr_dump_pic); + device_create_file(di_devp->dev, &dev_attr_log); + device_create_file(di_devp->dev, &dev_attr_provider_vframe_status); + device_create_file(di_devp->dev, &dev_attr_frame_format); + device_create_file(di_devp->dev, &dev_attr_tvp_region); + + /*pd_device_files_add*/ + get_ops_pd()->prob(di_devp->dev); + + get_ops_nr()->nr_drv_init(di_devp->dev); + + for (i = 0; i < DI_CHANNEL_NUB; i++) { + set_init_flag(i, false); + set_reg_flag(i, false); + } + + set_or_act_flag(true); + /*PR_INF("\t 11\n");*/ + ret = devm_request_irq(&pdev->dev, di_devp->pre_irq, &dim_irq, + IRQF_SHARED, + "pre_di", (void *)"pre_di"); + if (di_devp->post_wr_support) { + ret = devm_request_irq(&pdev->dev, di_devp->post_irq, + &dim_post_irq, + IRQF_SHARED, "post_di", + (void *)"post_di"); + } + + di_devp->sema_flg = 1; /*di_sema_init_flag = 1;*/ + dimh_hw_init(dimp_get(eDI_MP_pulldown_enable), + dimp_get(eDI_MP_mcpre_en)); + + dim_set_di_flag(); + + task_start(); + + post_mif_sw(false); + + dim_debugfs_init(); /*2018-07-18 add debugfs*/ + + dimh_patch_post_update_mc_sw(DI_MC_SW_IC, true); + + pr_info("%s:ok\n", __func__); + return ret; + +fail_cdev_add: + pr_info("%s:fail_cdev_add\n", __func__); + kfree(di_devp->data_l); + +fail_kmalloc_datal: + pr_info("%s:fail_kmalloc datal\n", __func__); + +#if 1 /*move from init*/ +/*fail_pdrv_register:*/ + class_destroy(di_pdev->pclss); +fail_class_create: + unregister_chrdev_region(di_pdev->devno, DI_COUNT); +fail_alloc_cdev_region: + kfree(di_pdev); +fail_kmalloc_dev: + + return ret; +#endif + return ret; +} + +static int dim_remove(struct platform_device *pdev) +{ + struct di_dev_s *di_devp = NULL; + + PR_INF("%s:\n", __func__); + di_devp = platform_get_drvdata(pdev); + + dimh_hw_uninit(); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) + clk_disable_unprepare(di_devp->vpu_clkb); + + di_devp->di_event = 0xff; + + dim_uninit_buf(1, 0);/*channel 0*/ + di_set_flg_hw_int(false); + + task_stop(); + + dim_rdma_exit(); + +/* Remove the cdev */ + device_remove_file(di_devp->dev, &dev_attr_config); + device_remove_file(di_devp->dev, &dev_attr_debug); + device_remove_file(di_devp->dev, &dev_attr_log); + device_remove_file(di_devp->dev, &dev_attr_dump_pic); + device_remove_file(di_devp->dev, &dev_attr_provider_vframe_status); + device_remove_file(di_devp->dev, &dev_attr_frame_format); + device_remove_file(di_devp->dev, &dev_attr_tvp_region); + /*pd_device_files_del*/ + get_ops_pd()->remove(di_devp->dev); + get_ops_nr()->nr_drv_uninit(di_devp->dev); + cdev_del(&di_devp->cdev); + + if (di_devp->flag_cma == 2) { + if (dma_release_from_contiguous(&pdev->dev, + di_devp->total_pages, + di_devp->mem_size >> PAGE_SHIFT)) { + di_devp->total_pages = NULL; + di_devp->mem_start = 0; + pr_dbg("DI CMA total release ok.\n"); + } else { + pr_dbg("DI CMA total release fail.\n"); + } + if (di_pdev->nrds_enable) { + dim_nr_ds_buf_uninit(di_pdev->flag_cma, + &pdev->dev); + } + } + device_destroy(di_devp->pclss, di_devp->devno); + +/* free drvdata */ + + dev_set_drvdata(&pdev->dev, NULL); + platform_set_drvdata(pdev, NULL); + +#if 1 /*move to remove*/ + class_destroy(di_pdev->pclss); + + dim_debugfs_exit(); + + dip_exit(); + unregister_chrdev_region(di_pdev->devno, DI_COUNT); +#endif + + kfree(di_devp->data_l); + kfree(di_pdev); + + PR_INF("%s:finish\n", __func__); + return 0; +} + +static void dim_shutdown(struct platform_device *pdev) +{ + struct di_dev_s *di_devp = NULL; + int i; + + di_devp = platform_get_drvdata(pdev); + + for (i = 0; i < DI_CHANNEL_NUB; i++) + set_init_flag(i, false); + + if (is_meson_txlx_cpu()) + dim_top_gate_control(true, true); + else + dim_DI_Wr(DI_CLKG_CTRL, 0x2); + + if (!is_meson_txlx_cpu()) + diext_clk_b_sw(false); + + PR_INF("%s.\n", __func__); +} + +#ifdef CONFIG_PM + +static void di_clear_for_suspend(struct di_dev_s *di_devp) +{ + unsigned int channel = get_current_channel(); /*tmp*/ + + pr_info("%s\n", __func__); + + di_vframe_unreg(channel);/*have flag*/ + + if (dip_chst_get(channel) != eDI_TOP_STATE_IDLE) + dim_unreg_process_irq(channel); + + dip_cma_close(); + pr_info("%s end\n", __func__); +} + +/* must called after lcd */ +static int di_suspend(struct device *dev) +{ + struct di_dev_s *di_devp = NULL; + + di_devp = dev_get_drvdata(dev); + di_devp->flags |= DI_SUSPEND_FLAG; + + di_clear_for_suspend(di_devp); + + if (!is_meson_txlx_cpu()) + diext_clk_b_sw(false); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + clk_disable_unprepare(di_devp->vpu_clkb); + PR_INF("%s\n", __func__); + return 0; +} + +/* must called before lcd */ +static int di_resume(struct device *dev) +{ + struct di_dev_s *di_devp = NULL; + + PR_INF("%s\n", __func__); + di_devp = dev_get_drvdata(dev); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + clk_prepare_enable(di_devp->vpu_clkb); + + di_devp->flags &= ~DI_SUSPEND_FLAG; + + /************/ + PR_INF("%s finish\n", __func__); + return 0; +} + +static const struct dev_pm_ops di_pm_ops = { + .suspend_late = di_suspend, + .resume_early = di_resume, +}; +#endif +#ifndef ARY_MATCH +/* #ifdef CONFIG_USE_OF */ +static const struct of_device_id amlogic_deinterlace_dt_match[] = { + /*{ .compatible = "amlogic, deinterlace", },*/ + { .compatible = "amlogic, dim-g12a", }, + {} +}; +#endif +/* #else */ +/* #define amlogic_deinterlace_dt_match NULL */ +/* #endif */ + +static struct platform_driver di_driver = { + .probe = dim_probe, + .remove = dim_remove, + .shutdown = dim_shutdown, + .driver = { + .name = DEVICE_NAME, + .owner = THIS_MODULE, + .of_match_table = amlogic_deinterlace_dt_match, +#ifdef CONFIG_PM + .pm = &di_pm_ops, +#endif + } +}; + +static int __init dim_module_init(void) +{ + int ret = 0; + + PR_INF("%s\n", __func__); + + ret = platform_driver_register(&di_driver); + if (ret != 0) { + PR_ERR("%s: failed to register driver\n", __func__); + /*goto fail_pdrv_register;*/ + return -ENODEV; + } + PR_INF("%s finish\n", __func__); + return 0; +} + +static void __exit dim_module_exit(void) +{ + platform_driver_unregister(&di_driver); + PR_INF("%s: ok.\n", __func__); +} + +module_init(dim_module_init); +module_exit(dim_module_exit); + +MODULE_DESCRIPTION("AMLOGIC MULTI-DI driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("4.0.0"); + diff --git a/drivers/amlogic/media/di_multi/di_sys.h b/drivers/amlogic/media/di_multi/di_sys.h new file mode 100644 index 000000000000..8aec249487e7 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_sys.h @@ -0,0 +1,26 @@ +/* + * drivers/amlogic/media/di_multi/di_sys.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_SYS_H__ +#define __DI_SYS_H__ + +#define DEVICE_NAME "di_multi" +#define CLASS_NAME "deinterlace" + +bool dim_rev_mem_check(void); + +#endif /*__DI_SYS_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_task.c b/drivers/amlogic/media/di_multi/di_task.c new file mode 100644 index 000000000000..9912fd45500f --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_task.c @@ -0,0 +1,315 @@ +/* + * drivers/amlogic/media/di_multi/di_task.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include /*ary add*/ +#include +#include +#include +#include + +#include "deinterlace.h" +#include "di_data_l.h" + +#include "di_prc.h" + +#include "di_task.h" +#include "di_vframe.h" + +static void task_wakeup(struct di_task *tsk); + +unsigned int di_dbg_task_flg; /*debug only*/ + +bool task_send_cmd(unsigned int cmd) +{ + struct di_task *tsk = get_task(); + unsigned int val; + + dbg_reg("%s:cmd[%d]:\n", __func__, cmd); + if (kfifo_is_full(&tsk->fifo_cmd)) { + if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int)) + != sizeof(unsigned int)) { + PR_ERR("%s:can't out\n", __func__); + return false; + } + + PR_ERR("%s:lost cmd[%d]\n", __func__, val); + tsk->err_cmd_cnt++; + /*return false;*/ + } + kfifo_in_spinlocked(&tsk->fifo_cmd, &cmd, sizeof(unsigned int), + &tsk->lock_cmd); + + task_wakeup(tsk); + return true; +} + +void task_send_ready(void) +{ + struct di_task *tsk = get_task(); + + task_wakeup(tsk); +} + +#if 0 +bool task_have_vf(unsigned int ch) +{ + struct di_task *tsk = get_task(); + + task_wakeup(tsk); +} +#endif +bool task_get_cmd(unsigned int *cmd) +{ + struct di_task *tsk = get_task(); + unsigned int val; + + if (kfifo_is_empty(&tsk->fifo_cmd)) + return false; + + if (kfifo_out(&tsk->fifo_cmd, &val, sizeof(unsigned int)) + != sizeof(unsigned int)) + return false; + + *cmd = val; + return true; +} + +void task_polling_cmd(void) +{ + int i; + union DI_L_CMD_BITS cmdbyte; + + for (i = 0; i < MAX_KFIFO_L_CMD_NUB; i++) { + if (!task_get_cmd(&cmdbyte.cmd32)) + break; + dip_chst_process_reg(cmdbyte.b.ch); + } +} + +static int task_is_exiting(struct di_task *tsk) +{ + if (tsk->exit) + return 1; + +/* if (afepriv->dvbdev->writers == 1) + * if (time_after_eq(jiffies, fepriv->release_jiffies + + * dvb_shutdown_timeout * HZ)) + * return 1; + */ + return 0; +} + +static int task_should_wakeup(struct di_task *tsk) +{ + if (tsk->wakeup) { + tsk->wakeup = 0; + /*dbg only dbg_tsk("wkg[%d]\n", di_dbg_task_flg);*/ + return 1; + } + return task_is_exiting(tsk); +} + +static void task_wakeup(struct di_task *tsk) +{ + tsk->wakeup = 1; + wake_up_interruptible(&tsk->wait_queue); + /*dbg_tsk("wks[%d]\n", di_dbg_task_flg);*/ +} + +static int di_test_thread(void *data) +{ + struct di_task *tsk = data; + bool semheld = false; + + tsk->delay = HZ; + tsk->status = 0; + tsk->wakeup = 0; + #if 0 + tsk->reinitialise = 0; + tsk->needfinish = 0; + tsk->finishflg = 0; + #endif + set_freezable(); + while (1) { + up(&tsk->sem);/* is locked when we enter the thread... */ +restart: + wait_event_interruptible_timeout(tsk->wait_queue, + task_should_wakeup(tsk) || + kthread_should_stop() || + freezing(current), + tsk->delay); + di_dbg_task_flg = 1; + + if (kthread_should_stop() || task_is_exiting(tsk)) { + /* got signal or quitting */ + if (!down_interruptible(&tsk->sem)) + semheld = true; + tsk->exit = 1; + break; + } + + if (try_to_freeze()) + goto restart; + + if (down_interruptible(&tsk->sem)) + break; +#if 0 + if (tsk->reinitialise) { + /*dvb_frontend_init(fe);*/ + + tsk->reinitialise = 0; + } +#endif + di_dbg_task_flg = 2; + task_polling_cmd(); + di_dbg_task_flg = 3; + dip_chst_process_ch(); + di_dbg_task_flg = 4; + if (get_reg_flag_all()) + dip_hw_process(); + + di_dbg_task_flg = 0; + } + + tsk->thread = NULL; + if (kthread_should_stop()) + tsk->exit = 1; + else + tsk->exit = 0; + /*mb();*/ + + if (semheld) + up(&tsk->sem); + + task_wakeup(tsk);/*?*/ + return 0; +} + +void task_stop(void/*struct di_task *tsk*/) +{ + struct di_task *tsk = get_task(); + +#if 1 /*not use cmd*/ + pr_info("."); + /*--------------------*/ + /*cmd buf*/ + if (tsk->flg_cmd) { + kfifo_free(&tsk->fifo_cmd); + tsk->flg_cmd = 0; + } + /*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/ + spin_lock_init(&tsk->lock_cmd); + tsk->err_cmd_cnt = 0; + /*--------------------*/ +#endif + tsk->exit = 1; + /*mb();*/ + + if (!tsk->thread) + return; + + kthread_stop(tsk->thread); + + sema_init(&tsk->sem, 1); + tsk->status = 0; + + /* paranoia check in case a signal arrived */ + if (tsk->thread) + PR_ERR("warning: thread %p won't exit\n", tsk->thread); +} + +int task_start(void) +{ + int ret; + int flg_err; + struct di_task *tsk = get_task(); + + struct task_struct *fe_thread; + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + + pr_info("."); + flg_err = 0; +#if 1 /*not use cmd*/ + /*--------------------*/ + /*cmd buf*/ + /*tsk->lock_cmd = SPIN_LOCK_UNLOCKED;*/ + spin_lock_init(&tsk->lock_cmd); + tsk->err_cmd_cnt = 0; + ret = kfifo_alloc(&tsk->fifo_cmd, + sizeof(unsigned int) * MAX_KFIFO_L_CMD_NUB, + GFP_KERNEL); + if (ret < 0) { + tsk->flg_cmd = false; + PR_ERR("%s:can't get kfifo\n", __func__); + return -1; + } + tsk->flg_cmd = true; + +#endif + /*--------------------*/ + sema_init(&tsk->sem, 1); + init_waitqueue_head(&tsk->wait_queue); + + if (tsk->thread) { + if (!tsk->exit) + return 0; + + task_stop(); + } + + if (signal_pending(current)) { + if (tsk->flg_cmd) { + kfifo_free(&tsk->fifo_cmd); + tsk->flg_cmd = 0; + } + return -EINTR; + } + if (down_interruptible(&tsk->sem)) { + if (tsk->flg_cmd) { + kfifo_free(&tsk->fifo_cmd); + tsk->flg_cmd = 0; + } + return -EINTR; + } + + tsk->status = 0; + tsk->exit = 0; + tsk->thread = NULL; + /*mb();*/ + + fe_thread = kthread_run(di_test_thread, tsk, "aml-ditest-0"); + if (IS_ERR(fe_thread)) { + ret = PTR_ERR(fe_thread); + PR_ERR(" failed to start kthread (%d)\n", ret); + up(&tsk->sem); + tsk->flg_init = 0; + return ret; + } + + sched_setscheduler_nocheck(fe_thread, SCHED_FIFO, ¶m); + tsk->flg_init = 1; + tsk->thread = fe_thread; + return 0; +} + +void dbg_task(void) +{ + struct di_task *tsk = get_task(); + + tsk->status = 1; + task_wakeup(tsk); +} diff --git a/drivers/amlogic/media/di_multi/di_task.h b/drivers/amlogic/media/di_multi/di_task.h new file mode 100644 index 000000000000..15cbced99474 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_task.h @@ -0,0 +1,36 @@ +/* + * drivers/amlogic/media/di_multi/di_task.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_TASK_H__ +#define __DI_TASK_H__ + +extern unsigned int di_dbg_task_flg; /*debug only*/ + +enum eTSK_STATE { + eTSK_STATE_IDLE, + eTSK_STATE_WORKING, +}; + +void task_stop(void); +int task_start(void); + +void dbg_task(void); + +bool task_send_cmd(unsigned int cmd); +void task_send_ready(void); + +#endif /*__DI_TASK_H__*/ diff --git a/drivers/amlogic/media/di_multi/di_vframe.c b/drivers/amlogic/media/di_multi/di_vframe.c new file mode 100644 index 000000000000..caf2832ade99 --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_vframe.c @@ -0,0 +1,556 @@ +/* + * drivers/amlogic/media/di_multi/di_vframe.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +#include "deinterlace.h" +#include "di_data_l.h" +#include "di_pre.h" +#include "di_prc.h" +#include "di_dbg.h" + +#include "di_vframe.h" + +struct dev_vfram_t *get_dev_vframe(unsigned int ch) +{ + if (ch < DI_CHANNEL_NUB) + return &get_datal()->ch_data[ch].vfm; + + pr_info("err:%s ch overflow %d\n", __func__, ch); + return &get_datal()->ch_data[0].vfm; +} + +const char * const di_rev_name[4] = { + "deinterlace", + "dimulti.1", + "dimulti.2", + "dimulti.3", +}; + +void dev_vframe_reg(struct dev_vfram_t *pvfm) +{ + if (pvfm->reg) { + PR_WARN("duplicate reg\n"); + return; + } + vf_reg_provider(&pvfm->di_vf_prov); + vf_notify_receiver(pvfm->name, VFRAME_EVENT_PROVIDER_START, NULL); + pvfm->reg = 1; +} + +void dev_vframe_unreg(struct dev_vfram_t *pvfm) +{ + if (pvfm->reg) { + vf_unreg_provider(&pvfm->di_vf_prov); + pvfm->reg = 0; + } else { + PR_WARN("duplicate ureg\n"); + } +} + +void di_vframe_reg(unsigned int ch) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + + dev_vframe_reg(pvfm); +} + +void di_vframe_unreg(unsigned int ch) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + dev_vframe_unreg(pvfm); +} + +/*--------------------------*/ + +const char * const di_receiver_event_cmd[] = { + "", + "_UNREG", + "_LIGHT_UNREG", + "_START", + NULL, /* "_VFRAME_READY", */ + NULL, /* "_QUREY_STATE", */ + "_RESET", + NULL, /* "_FORCE_BLACKOUT", */ + "_REG", + "_LIGHT_UNREG_RETURN_VFRAME", + NULL, /* "_DPBUF_CONFIG", */ + NULL, /* "_QUREY_VDIN2NR", */ + NULL, /* "_SET_3D_VFRAME_INTERLEAVE", */ + NULL, /* "_FR_HINT", */ + NULL, /* "_FR_END_HINT", */ + NULL, /* "_QUREY_DISPLAY_INFO", */ + NULL, /* "_PROPERTY_CHANGED", */ +}; + +#define VFRAME_EVENT_PROVIDER_CMD_MAX 16 + +static int di_receiver_event_fun(int type, void *data, void *arg) +{ + struct dev_vfram_t *pvfm; + unsigned int ch; + int ret = 0; + + ch = *(int *)arg; + + pvfm = get_dev_vframe(ch); + + if (type <= VFRAME_EVENT_PROVIDER_CMD_MAX && + di_receiver_event_cmd[type]) { + dbg_ev("ch[%d]:%s,%d:%s\n", ch, __func__, + type, + di_receiver_event_cmd[type]); + } + + switch (type) { + case VFRAME_EVENT_PROVIDER_UNREG: + ret = di_ori_event_unreg(ch); +/* task_send_cmd(LCMD1(eCMD_UNREG, 0));*/ + break; + case VFRAME_EVENT_PROVIDER_REG: + /*dev_vframe_reg(pvfm);*/ + ret = di_ori_event_reg(data, ch); +/* task_send_cmd(LCMD1(eCMD_REG, 0));*/ + break; + case VFRAME_EVENT_PROVIDER_START: + break; + + case VFRAME_EVENT_PROVIDER_LIGHT_UNREG: + ret = di_ori_event_light_unreg(ch); + break; + case VFRAME_EVENT_PROVIDER_VFRAME_READY: + ret = di_ori_event_ready(ch); + break; + case VFRAME_EVENT_PROVIDER_QUREY_STATE: + ret = di_ori_event_qurey_state(ch); + break; + case VFRAME_EVENT_PROVIDER_RESET: + ret = di_ori_event_reset(ch); + break; + case VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME: + ret = di_ori_event_light_unreg_revframe(ch); + break; + case VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR: + ret = di_ori_event_qurey_vdin2nr(ch); + break; + case VFRAME_EVENT_PROVIDER_SET_3D_VFRAME_INTERLEAVE: + di_ori_event_set_3D(type, data, ch); + break; + case VFRAME_EVENT_PROVIDER_FR_HINT: + case VFRAME_EVENT_PROVIDER_FR_END_HINT: + vf_notify_receiver(pvfm->name, type, data); + break; + + default: + break; + } + + return ret; +} + +static const struct vframe_receiver_op_s di_vf_receiver = { + .event_cb = di_receiver_event_fun +}; + +bool vf_type_is_prog(unsigned int type) +{ + bool ret = (type & VIDTYPE_TYPEMASK) == 0 ? true : false; + + return ret; +} + +bool vf_type_is_interlace(unsigned int type) +{ + bool ret = (type & VIDTYPE_INTERLACE) ? true : false; + + return ret; +} + +bool vf_type_is_top(unsigned int type) +{ + bool ret = ((type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) + ? true : false; + return ret; +} + +bool vf_type_is_bottom(unsigned int type) +{ + bool ret = ((type & VIDTYPE_INTERLACE_BOTTOM) + == VIDTYPE_INTERLACE_BOTTOM) + ? true : false; + + return ret; +} + +bool vf_type_is_inter_first(unsigned int type) +{ + bool ret = (type & VIDTYPE_INTERLACE_TOP) ? true : false; + + return ret; +} + +bool vf_type_is_mvc(unsigned int type) +{ + bool ret = (type & VIDTYPE_MVC) ? true : false; + + return ret; +} + +bool vf_type_is_no_video_en(unsigned int type) +{ + bool ret = (type & VIDTYPE_NO_VIDEO_ENABLE) ? true : false; + + return ret; +} + +bool vf_type_is_VIU422(unsigned int type) +{ + bool ret = (type & VIDTYPE_VIU_422) ? true : false; + + return ret; +} + +bool vf_type_is_VIU_FIELD(unsigned int type) +{ + bool ret = (type & VIDTYPE_VIU_FIELD) ? true : false; + + return ret; +} + +bool vf_type_is_VIU_SINGLE(unsigned int type) +{ + bool ret = (type & VIDTYPE_VIU_SINGLE_PLANE) ? true : false; + + return ret; +} + +bool vf_type_is_VIU444(unsigned int type) +{ + bool ret = (type & VIDTYPE_VIU_444) ? true : false; + + return ret; +} + +bool vf_type_is_VIUNV21(unsigned int type) +{ + bool ret = (type & VIDTYPE_VIU_NV21) ? true : false; + + return ret; +} + +bool vf_type_is_vscale_dis(unsigned int type) +{ + bool ret = (type & VIDTYPE_VSCALE_DISABLE) ? true : false; + + return ret; +} + +bool vf_type_is_canvas_toggle(unsigned int type) +{ + bool ret = (type & VIDTYPE_CANVAS_TOGGLE) ? true : false; + + return ret; +} + +bool vf_type_is_pre_interlace(unsigned int type) +{ + bool ret = (type & VIDTYPE_PRE_INTERLACE) ? true : false; + + return ret; +} + +bool vf_type_is_highrun(unsigned int type) +{ + bool ret = (type & VIDTYPE_HIGHRUN) ? true : false; + + return ret; +} + +bool vf_type_is_compress(unsigned int type) +{ + bool ret = (type & VIDTYPE_COMPRESS) ? true : false; + + return ret; +} + +bool vf_type_is_pic(unsigned int type) +{ + bool ret = (type & VIDTYPE_PIC) ? true : false; + + return ret; +} + +bool vf_type_is_scatter(unsigned int type) +{ + bool ret = (type & VIDTYPE_SCATTER) ? true : false; + + return ret; +} + +bool vf_type_is_vd2(unsigned int type) +{ + bool ret = (type & VIDTYPE_VD2) ? true : false; + + return ret; +} + +bool is_bypss_complete(struct dev_vfram_t *pvfm) +{ + return pvfm->bypass_complete; +} + +#if 0 +bool is_reg(unsigned int ch) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + + return pvfm->reg; +} +#endif + +void set_bypass_complete(struct dev_vfram_t *pvfm, bool on) +{ + if (on) + pvfm->bypass_complete = true; + else + pvfm->bypass_complete = false; +} + +void set_bypass2_complete(unsigned int ch, bool on) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + set_bypass_complete(pvfm, on); +} + +bool is_bypss2_complete(unsigned int ch) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + + return is_bypss_complete(pvfm); +} + +#if 0 +static void set_reg(unsigned int ch, int on) +{ + struct dev_vfram_t *pvfm; + + pvfm = get_dev_vframe(ch); + + if (on) + pvfm->reg = true; + else + pvfm->reg = false; +} +#endif +static struct vframe_s *di_vf_peek(void *arg) +{ + unsigned int ch = *(int *)arg; + + /*dim_print("%s:ch[%d]\n",__func__,ch);*/ + if (di_is_pause(ch)) + return NULL; + + if (is_bypss2_complete(ch)) + return pw_vf_peek(ch); + else + return di_vf_l_peek(ch); +} + +static struct vframe_s *di_vf_get(void *arg) +{ + unsigned int ch = *(int *)arg; + /*struct vframe_s *vfm;*/ + + dim_tr_ops.post_get2(5); + if (di_is_pause(ch)) + return NULL; + + di_pause_step_done(ch); + + /*pvfm = get_dev_vframe(ch);*/ + + if (is_bypss2_complete(ch)) + #if 0 + vfm = pw_vf_peek(ch); + if (dim_bypass_detect(ch, vfm)) + return NULL; + + #endif + return pw_vf_get(ch); + + return di_vf_l_get(ch); +} + +static void di_vf_put(struct vframe_s *vf, void *arg) +{ + unsigned int ch = *(int *)arg; + + if (is_bypss2_complete(ch)) { + pw_vf_put(vf, ch); + pw_vf_notify_provider(ch, + VFRAME_EVENT_RECEIVER_PUT, NULL); + return; + } + + di_vf_l_put(vf, ch); +} + +static int di_event_cb(int type, void *data, void *private_data) +{ + if (type == VFRAME_EVENT_RECEIVER_FORCE_UNREG) { + pr_info("%s: RECEIVER_FORCE_UNREG return\n", + __func__); + return 0; + } + return 0; +} + +static int di_vf_states(struct vframe_states *states, void *arg) +{ + unsigned int ch = *(int *)arg; + + if (!states) + return -1; + + dim_print("%s:ch[%d]\n", __func__, ch); + + di_vf_l_states(states, ch); + return 0; +} + +static const struct vframe_operations_s deinterlace_vf_provider = { + .peek = di_vf_peek, + .get = di_vf_get, + .put = di_vf_put, + .event_cb = di_event_cb, + .vf_states = di_vf_states, +}; + +#if 1 +struct vframe_s *pw_vf_get(unsigned int ch) +{ + sum_g_inc(ch); + return vf_get(di_rev_name[ch]); +} + +struct vframe_s *pw_vf_peek(unsigned int ch) +{ + return vf_peek(di_rev_name[ch]); +} + +void pw_vf_put(struct vframe_s *vf, unsigned int ch) +{ + sum_p_inc(ch); + vf_put(vf, di_rev_name[ch]); +} + +int pw_vf_notify_provider(unsigned int channel, int event_type, void *data) +{ + return vf_notify_provider(di_rev_name[channel], event_type, data); +} + +int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data) +{ + return vf_notify_receiver(di_rev_name[channel], event_type, data); +} + +void pw_vf_light_unreg_provider(unsigned int ch) +{ + struct dev_vfram_t *pvfm; + struct vframe_provider_s *prov; + + pvfm = get_dev_vframe(ch); + + prov = &pvfm->di_vf_prov; + vf_light_unreg_provider(prov); +} + +#else +struct vframe_s *pw_vf_get(unsigned int channel) +{ + return vf_get(VFM_NAME); +} + +struct vframe_s *pw_vf_peek(unsigned int channel) +{ + return vf_peek(VFM_NAME); +} + +void pw_vf_put(struct vframe_s *vf, unsigned int channel) +{ + vf_put(vf, VFM_NAME); +} + +int pw_vf_notify_provider(unsigned int channel, int event_type, void *data) +{ + return vf_notify_provider(VFM_NAME, event_type, data); +} + +int pw_vf_notify_receiver(unsigned int channel, int event_type, void *data) +{ + return vf_notify_receiver(VFM_NAME, event_type, data); +} + +#endif + +void dev_vframe_exit(void) +{ + struct dev_vfram_t *pvfm; + int ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + pvfm = get_dev_vframe(ch); + vf_unreg_provider(&pvfm->di_vf_prov); + vf_unreg_receiver(&pvfm->di_vf_recv); + } + pr_info("%s finish\n", __func__); +} + +void dev_vframe_init(void) +{ + struct dev_vfram_t *pvfm; + int ch; + + for (ch = 0; ch < DI_CHANNEL_NUB; ch++) { + pvfm = get_dev_vframe(ch); + pvfm->name = di_rev_name[ch]; + pvfm->indx = ch; + /*set_bypass_complete(pvfm, true);*/ /*test only*/ + + /*receiver:*/ + vf_receiver_init(&pvfm->di_vf_recv, pvfm->name, + &di_vf_receiver, &pvfm->indx); + vf_reg_receiver(&pvfm->di_vf_recv); + + /*provider:*/ + vf_provider_init(&pvfm->di_vf_prov, pvfm->name, + &deinterlace_vf_provider, &pvfm->indx); + } + pr_info("%s finish\n", __func__); +} diff --git a/drivers/amlogic/media/di_multi/di_vframe.h b/drivers/amlogic/media/di_multi/di_vframe.h new file mode 100644 index 000000000000..f5eb0d8f71fc --- /dev/null +++ b/drivers/amlogic/media/di_multi/di_vframe.h @@ -0,0 +1,68 @@ +/* + * drivers/amlogic/media/di_multi/di_vframe.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __DI_VFRAME_H__ +#define __DI_VFRAME_H__ + +#include +#include +#include + +void dev_vframe_init(void); +void dev_vframe_exit(void); +void di_vframe_reg(unsigned int ch); +void di_vframe_unreg(unsigned int ch); + +bool vf_type_is_prog(unsigned int type); +bool vf_type_is_interlace(unsigned int type); +bool vf_type_is_top(unsigned int type); +bool vf_type_is_bottom(unsigned int type); +bool vf_type_is_inter_first(unsigned int type); +bool vf_type_is_mvc(unsigned int type); +bool vf_type_is_no_video_en(unsigned int type); +bool vf_type_is_VIU422(unsigned int type); +bool vf_type_is_VIU_FIELD(unsigned int type); +bool vf_type_is_VIU_SINGLE(unsigned int type); +bool vf_type_is_VIU444(unsigned int type); +bool vf_type_is_VIUNV21(unsigned int type); +bool vf_type_is_vscale_dis(unsigned int type); +bool vf_type_is_canvas_toggle(unsigned int type); +bool vf_type_is_pre_interlace(unsigned int type); +bool vf_type_is_highrun(unsigned int type); +bool vf_type_is_compress(unsigned int type); +bool vf_type_is_pic(unsigned int type); +bool vf_type_is_scatter(unsigned int type); +bool vf_type_is_vd2(unsigned int type); + +extern const char * const di_rev_name[4]; + +struct vframe_s *pw_vf_get(unsigned int ch); +struct vframe_s *pw_vf_peek(unsigned int ch); +void pw_vf_put(struct vframe_s *vf, unsigned int ch); +int pw_vf_notify_provider(unsigned int channel, + int event_type, + void *data); +int pw_vf_notify_receiver(unsigned int channel, + int event_type, + void *data); +void pw_vf_light_unreg_provider(unsigned int ch); + +void set_bypass2_complete(unsigned int ch, bool on); +bool is_bypss_complete(struct dev_vfram_t *pvfm); +bool is_bypss2_complete(unsigned int ch); + +#endif /*__DI_VFRAME_H__*/ diff --git a/drivers/amlogic/media/di_multi/dim_trace.h b/drivers/amlogic/media/di_multi/dim_trace.h new file mode 100644 index 000000000000..59a5c0089748 --- /dev/null +++ b/drivers/amlogic/media/di_multi/dim_trace.h @@ -0,0 +1,71 @@ +/* + * drivers/amlogic/media/di_multi/dim_trace.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dim + +#if !defined(_DIM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _DIM_TRACE_H + +#include + +/* single lifecycle events */ +DECLARE_EVENT_CLASS(di_event_class, + TP_PROTO(const char *name, int field_cnt, unsigned long time), + TP_ARGS(name, field_cnt, time), + TP_STRUCT__entry( + __string(name, name) + __field(int, field_cnt) + __field(unsigned long, time) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->field_cnt = field_cnt; + __entry->time = time; + ), + TP_printk("[%s-%-4dth-%lums]", __get_str(name), + __entry->field_cnt, __entry->time) +); + +#define DEFINE_DI_EVENT(name) \ +DEFINE_EVENT(di_event_class, name, \ + TP_PROTO(const char *name, int field_cnt, unsigned long time), \ + TP_ARGS(name, field_cnt, time)) + +DEFINE_DI_EVENT(dim_pre); +DEFINE_DI_EVENT(dim_post); +/*2019-06-18*/ +DEFINE_DI_EVENT(dim_pre_getxx); +DEFINE_DI_EVENT(dim_pre_setxx); +DEFINE_DI_EVENT(dim_pre_ready); +DEFINE_DI_EVENT(dim_pst_ready); +DEFINE_DI_EVENT(dim_pst_getxx); +DEFINE_DI_EVENT(dim_pst_setxx); +DEFINE_DI_EVENT(dim_pst_irxxx); +DEFINE_DI_EVENT(dim_pst_doing); +DEFINE_DI_EVENT(dim_pst_peekx); +DEFINE_DI_EVENT(dim_pst_get2x); + +#endif /* _DIM_TRACE_H */ + +#if 0 +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE deinterlace_trace +#include +#endif diff --git a/drivers/amlogic/media/di_multi/nr_downscale.c b/drivers/amlogic/media/di_multi/nr_downscale.c new file mode 100644 index 000000000000..fc5e5613a9c0 --- /dev/null +++ b/drivers/amlogic/media/di_multi/nr_downscale.c @@ -0,0 +1,218 @@ +/* + * drivers/amlogic/media/di_multi/nr_downscale.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "register.h" +#include "nr_downscale.h" +#include "deinterlace.h" + +#include "di_data_l.h" +#include "di_api.h" + +static struct nr_ds_s nrds_dev; + +static void nr_ds_hw_init(unsigned int width, unsigned int height) +{ + unsigned char h_step = 0, v_step = 0; + unsigned int width_out, height_out; + + width_out = NR_DS_WIDTH; + height_out = NR_DS_HEIGHT; + + h_step = width / width_out; + v_step = height / height_out; + + /*Switch MIF to NR_DS*/ + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, 3, 5, 2); + /* config dsbuf_ocol*/ + dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, width_out, 0, 8); + /* config dsbuf_orow*/ + dim_RDMA_WR_BITS(NR_DS_BUF_SIZE_REG, height_out, 8, 8); + + dim_RDMA_WR_BITS(NRDSWR_X, (width_out - 1), 0, 13); + dim_RDMA_WR_BITS(NRDSWR_Y, (height_out - 1), 0, 13); + + dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (height_out - 1), 0, 13); + dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, (width_out - 1), 16, 13); + /* little endian */ + dim_RDMA_WR_BITS(NRDSWR_CAN_SIZE, 1, 13, 1); + + dim_RDMA_WR_BITS(NR_DS_CTRL, v_step, 16, 6); + dim_RDMA_WR_BITS(NR_DS_CTRL, h_step, 24, 6); +} + +/* + * init nr ds buffer + */ +void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start, + struct device *dev) +{ + unsigned int i = 0; + bool ret; + struct dim_mm_s omm; + + if (cma_flag == 0) { + nrds_dev.nrds_addr = mem_start; + } else { + #if 0 + nrds_dev.nrds_pages = dma_alloc_from_contiguous(dev, + NR_DS_PAGE_NUM, 0); + if (nrds_dev.nrds_pages) + nrds_dev.nrds_addr = page_to_phys(nrds_dev.nrds_pages); + else + PR_ERR("DI: alloc nr ds mem error.\n"); + #else + ret = dim_mm_alloc(cma_flag, NR_DS_PAGE_NUM, &omm); + if (ret) { + nrds_dev.nrds_pages = omm.ppage; + nrds_dev.nrds_addr = omm.addr; + } else { + PR_ERR("alloc nr ds mem error.\n"); + } + + #endif + } + for (i = 0; i < NR_DS_BUF_NUM; i++) + nrds_dev.buf[i] = nrds_dev.nrds_addr + (NR_DS_BUF_SIZE * i); + nrds_dev.cur_buf_idx = 0; +} + +void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev) +{ + unsigned int i = 0; + + if (cma_flag == 0) { + nrds_dev.nrds_addr = 0; + } else { + if (nrds_dev.nrds_pages) { + #if 0 + dma_release_from_contiguous(dev, + nrds_dev.nrds_pages, + NR_DS_PAGE_NUM); + #else + dim_mm_release(cma_flag, + nrds_dev.nrds_pages, + NR_DS_PAGE_NUM, + nrds_dev.nrds_addr); + #endif + nrds_dev.nrds_addr = 0; + nrds_dev.nrds_pages = NULL; + } else + pr_info("DI: no release nr ds mem.\n"); + } + for (i = 0; i < NR_DS_BUF_NUM; i++) + nrds_dev.buf[i] = 0; + nrds_dev.cur_buf_idx = 0; +} + +/* + * hw config, alloc canvas + */ +void dim_nr_ds_init(unsigned int width, unsigned int height) +{ + nr_ds_hw_init(width, height); + nrds_dev.field_num = 0; + + if (nrds_dev.canvas_idx != 0) + return; + + if (ext_ops.canvas_pool_alloc_canvas_table("nr_ds", + &nrds_dev.canvas_idx, 1, CANVAS_MAP_TYPE_1)) { + PR_ERR("%s alloc nrds canvas error.\n", __func__); + return; + } + pr_info("%s alloc nrds canvas %u.\n", + __func__, nrds_dev.canvas_idx); +} + +/* + * config nr ds mif, switch buffer + */ +void dim_nr_ds_mif_config(void) +{ + unsigned long mem_addr = 0; + + mem_addr = nrds_dev.buf[nrds_dev.cur_buf_idx]; + canvas_config(nrds_dev.canvas_idx, mem_addr, + NR_DS_WIDTH, NR_DS_HEIGHT, 0, 0); + dim_RDMA_WR_BITS(NRDSWR_CTRL, + nrds_dev.canvas_idx, 0, 8); + dim_nr_ds_hw_ctrl(true); +} + +/* + * enable/disable nr ds mif&hw + */ +void dim_nr_ds_hw_ctrl(bool enable) +{ + /*Switch MIF to NR_DS*/ + dim_RDMA_WR_BITS(VIUB_MISC_CTRL0, enable ? 3 : 2, 5, 2); + dim_RDMA_WR_BITS(NRDSWR_CTRL, enable ? 1 : 0, 12, 1); + dim_RDMA_WR_BITS(NR_DS_CTRL, enable ? 1 : 0, 30, 1); +} + +/* + * process in irq + */ +void dim_nr_ds_irq(void) +{ + dim_nr_ds_hw_ctrl(false); + nrds_dev.field_num++; + nrds_dev.cur_buf_idx++; + if (nrds_dev.cur_buf_idx >= NR_DS_BUF_NUM) + nrds_dev.cur_buf_idx = 0; +} + +/* + * get buf addr&size for dump + */ +void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size) +{ + *addr = nrds_dev.nrds_addr; + *size = NR_DS_BUF_SIZE; + pr_info("%s addr 0x%lx, size 0x%lx.\n", + __func__, *addr, *size); +} + +/* + * 0x37f9 ~ 0x37fc 0x3740 ~ 0x3743 8 regs + */ +void dim_dump_nrds_reg(unsigned int base_addr) +{ + unsigned int i = 0x37f9; + + pr_info("-----nrds reg start-----\n"); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (0x2006 << 2), i, dim_RDMA_RD(0x2006)); + for (i = 0x37f9; i < 0x37fd; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), i, dim_RDMA_RD(i)); + for (i = 0x3740; i < 0x3744; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), i, dim_RDMA_RD(i)); + pr_info("-----nrds reg end-----\n"); +} diff --git a/drivers/amlogic/media/di_multi/nr_downscale.h b/drivers/amlogic/media/di_multi/nr_downscale.h new file mode 100644 index 000000000000..873ce7069b1d --- /dev/null +++ b/drivers/amlogic/media/di_multi/nr_downscale.h @@ -0,0 +1,46 @@ +/* + * drivers/amlogic/media/di_multi/nr_downscale.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _NR_DS_H +#define _NR_DS_H + +#define NR_DS_WIDTH 128 +#define NR_DS_HEIGHT 96 +#define NR_DS_BUF_SIZE (96 << 7) +#define NR_DS_BUF_NUM 6 +#define NR_DS_MEM_SIZE (NR_DS_BUF_SIZE * NR_DS_BUF_NUM) +#define NR_DS_PAGE_NUM (NR_DS_MEM_SIZE >> PAGE_SHIFT) + +struct nr_ds_s { + unsigned int field_num; + unsigned long nrds_addr; + struct page *nrds_pages; + unsigned int canvas_idx; + unsigned char cur_buf_idx; + unsigned long buf[NR_DS_BUF_NUM]; +}; + +void dim_nr_ds_buf_init(unsigned int cma_flag, unsigned long mem_start, + struct device *dev); +void dim_nr_ds_buf_uninit(unsigned int cma_flag, struct device *dev); +void dim_nr_ds_init(unsigned int width, unsigned int height); +void dim_nr_ds_mif_config(void); +void dim_nr_ds_hw_ctrl(bool enable); +void dim_nr_ds_irq(void); +void dim_get_nr_ds_buf(unsigned long *addr, unsigned long *size); +void dim_dump_nrds_reg(unsigned int base_addr); +#endif diff --git a/drivers/amlogic/media/di_multi/register.h b/drivers/amlogic/media/di_multi/register.h new file mode 100644 index 000000000000..b05814dba827 --- /dev/null +++ b/drivers/amlogic/media/di_multi/register.h @@ -0,0 +1,4416 @@ +/* + * drivers/amlogic/media/di_multi/register.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __MACH_DEINTERLACE_REG_ADDR_H_ +#define __MACH_DEINTERLACE_REG_ADDR_H_ +#include +#include +#include +#include + +#define Wr(adr, val) aml_write_vcbus(adr, val) +#define Rd(adr) aml_read_vcbus(adr) +#define Wr_reg_bits(adr, val, start, len) \ + aml_vcbus_update_bits(adr, \ + ((1 << (len)) - 1) << (start), (val) << (start)) + +#define Rd_reg_bits(adr, start, len) \ + ((aml_read_vcbus(adr) & \ + (((1UL << (len)) - 1UL) << (start))) >> (start)) + +unsigned int dim_RDMA_WR(unsigned int adr, unsigned int val); +unsigned int dim_RDMA_RD(unsigned int adr); +unsigned int dim_RDMA_WR_BITS(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len); +unsigned int dim_RDMA_RD_BITS(unsigned int adr, unsigned int start, + unsigned int len); +void dim_DI_Wr(unsigned int addr, unsigned int val); +void dim_DI_Wr_reg_bits(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len); +void dim_VSYNC_WR_MPEG_REG(unsigned int addr, unsigned int val); +void dim_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, + unsigned int val, + unsigned int start, + unsigned int len); + +#define HHI_VPU_CLKB_CNTL 0x83 + +#define DI_WRARB_REQEN_SLV_L1C1_OLD 0x2795 +#define DI_RDARB_REQEN_SLV_L1C1_OLD 0x2791 +#define DI_ARB_DBG_STAT_L1C1_OLD 0x27b4 + +#define VIUB_SW_RESET 0x2001 +#define VIUB_SW_RESET0 0x2002 +#define VIUB_MISC_CTRL0 0x2006 + /* 0xd0108018 */ +#define VIUB_GCLK_CTRL0 0x2007 +#define VIUB_GCLK_CTRL1 0x2008 +#define VIUB_GCLK_CTRL2 0x2009 +#define VIUB_GCLK_CTRL3 0x200a +/* g12a add debug reg */ +#define DI_DBG_CTRL 0x200b +#define DI_DBG_CTRL1 0x200c +#define DI_DBG_SRDY_INF 0x200d +#define DI_DBG_RRDY_INF 0x200e +/* txl add if2 */ +#define DI_IF2_GEN_REG 0x2010 +#define DI_IF2_CANVAS0 0x2011 +#define DI_IF2_LUMA_X0 0x2012 +#define DI_IF2_LUMA_Y0 0x2013 +#define DI_IF2_CHROMA_X0 0x2014 +#define DI_IF2_CHROMA_Y0 0x2015 +#define DI_IF2_RPT_LOOP 0x2016 +#define DI_IF2_LUMA0_RPT_PAT 0x2017 +#define DI_IF2_CHROMA0_RPT_PAT 0x2018 +#define DI_IF2_DUMMY_PIXEL 0x2019 +#define DI_IF2_LUMA_FIFO_SIZE 0x201a +#define DI_IF2_RANGE_MAP_Y 0x201b +#define DI_IF2_RANGE_MAP_CB 0x201c +#define DI_IF2_RANGE_MAP_CR 0x201d +#define DI_IF2_GEN_REG2 0x201e +#define DI_IF2_FMT_CTRL 0x201f +#define DI_IF2_FMT_W 0x2020 +#define DI_IF2_URGENT_CTRL 0x2021 +#define DI_IF2_GEN_REG3 0x2022 +/*txl new add end*/ + +/* g12 new added */ +/* IF0 MIF */ +#define DI_IF0_GEN_REG 0x2030 +#define DI_IF0_CANVAS0 0x2031 +#define DI_IF0_LUMA_X0 0x2032 +#define DI_IF0_LUMA_Y0 0x2033 +#define DI_IF0_CHROMA_X0 0x2034 +#define DI_IF0_CHROMA_Y0 0x2035 +#define DI_IF0_REPEAT_LOOP 0x2036 +#define DI_IF0_LUMA0_RPT_PAT 0x2037 +#define DI_IF0_CHROMA0_RPT_PAT 0x2038 +#define DI_IF0_DUMMY_PIXEL 0x2039 +#define DI_IF0_LUMA_FIFO_SIZE 0x203A +#define DI_IF0_RANGE_MAP_Y 0x203B +#define DI_IF0_RANGE_MAP_CB 0x203C +#define DI_IF0_RANGE_MAP_CR 0x203D +#define DI_IF0_GEN_REG2 0x203E +#define DI_IF0_FMT_CTRL 0x203F +#define DI_IF0_FMT_W 0x2040 +#define DI_IF0_FMT_W 0x2040 +#define DI_IF0_URGENT_CTRL 0x2041 +#define DI_IF0_GEN_REG3 0x2042 +/* AXI ARB */ +#define DI_RDARB_MODE_L1C1 0x2050 +#define DI_RDARB_REQEN_SLV_L1C1 0x2051 +#define DI_RDARB_WEIGH0_SLV_L1C1 0x2052 +#define DI_RDARB_WEIGH1_SLV_L1C1 0x2053 +#define DI_WRARB_MODE_L1C1 0x2054 +#define DI_WRARB_REQEN_SLV_L1C1 0x2055 +#define DI_WRARB_WEIGH0_SLV_L1C1 0x2056 +#define DI_WRARB_WEIGH1_SLV_L1C1 0x2057 +#define DI_RDWR_ARB_STATUS_L1C1 0x2058 +#define DI_ARB_DBG_CTRL_L1C1 0x2059 +#define DI_ARB_DBG_STAT_L1C1 0x205a +#define DI_RDARB_UGT_L1C1 0x205b +#define DI_RDARB_LIMT0_L1C1 0x205c +#define DI_WRARB_UGT_L1C1 0x205d +#define DI_PRE_GL_CTRL 0x20ab +#define DI_PRE_GL_THD 0x20ac +#define DI_POST_GL_CTRL 0x20ad +#define DI_POST_GL_THD 0x20ae + +#define DI_SUB_RDARB_MODE 0x37c0 +#define DI_SUB_RDARB_REQEN_SLV 0x37c1 +#define DI_SUB_RDARB_WEIGH0_SLV 0x37c2 +#define DI_SUB_RDARB_WEIGH1_SLV 0x37c3 +#define DI_SUB_RDARB_UGT 0x37c4 +#define DI_SUB_RDARB_LIMT0 0x37c5 +#define DI_SUB_WRARB_MODE 0x37c6 +#define DI_SUB_WRARB_REQEN_SLV 0x37c7 +#define DI_SUB_WRARB_WEIGH0_SLV 0x37c8 +#define DI_SUB_WRARB_WEIGH1_SLV 0x37c9 +#define DI_SUB_WRARB_UGT 0x37ca +#define DI_SUB_RDWR_ARB_STATUS 0x37cb +#define DI_SUB_ARB_DBG_CTRL 0x37cc +#define DI_SUB_ARB_DBG_STAT 0x37cd +#define CONTRD_CTRL1 0x37d0 +#define CONTRD_CTRL2 0x37d1 +#define CONTRD_SCOPE_X 0x37d2 +#define CONTRD_SCOPE_Y 0x37d3 +#define CONTRD_RO_STAT 0x37d4 +#define CONT2RD_CTRL1 0x37d5 +#define CONT2RD_CTRL2 0x37d6 +#define CONT2RD_SCOPE_X 0x37d7 +#define CONT2RD_SCOPE_Y 0x37d8 +#define CONT2RD_RO_STAT 0x37d9 +#define MTNRD_CTRL1 0x37da +#define MTNRD_CTRL2 0x37db +#define MTNRD_SCOPE_X 0x37dc +#define MTNRD_SCOPE_Y 0x37dd +#define MTNRD_RO_STAT 0x37de +#define MCVECRD_CTRL1 0x37df +#define MCVECRD_CTRL2 0x37e0 +#define MCVECRD_SCOPE_X 0x37e1 +#define MCVECRD_SCOPE_Y 0x37e2 +#define MCVECRD_RO_STAT 0x37e3 +#define MCINFRD_CTRL1 0x37e4 +#define MCINFRD_CTRL2 0x37e5 +#define MCINFRD_SCOPE_X 0x37e6 +#define MCINFRD_SCOPE_Y 0x37e7 +#define MCINFRD_RO_STAT 0x37e8 +#define CONTWR_X 0x37e9 +#define CONTWR_Y 0x37ea +#define CONTWR_CTRL 0x37eb +#define CONTWR_CAN_SIZE 0x37ec +#define MTNWR_X 0x37ed +#define MTNWR_Y 0x37ee +#define MTNWR_CTRL 0x37ef +#define MTNWR_CAN_SIZE 0x37f0 +#define MCVECWR_X 0x37f1 +#define MCVECWR_Y 0x37f2 +#define MCVECWR_CTRL 0x37f3 +#define MCVECWR_CAN_SIZE 0x37f4 +#define MCINFWR_X 0x37f5 +#define MCINFWR_Y 0x37f6 +#define MCINFWR_CTRL 0x37f7 +#define MCINFWR_CAN_SIZE 0x37f8 +/* DI SCALE */ +#define DI_SCO_FIFO_CTRL 0x374e +#define DI_SC_TOP_CTRL 0x374f +#define DI_SC_DUMMY_DATA 0x3750 +#define DI_SC_LINE_IN_LENGTH 0x3751 +#define DI_SC_PIC_IN_HEIGHT 0x3752 +#define DI_SC_COEF_IDX 0x3753 +#define DI_SC_COEF 0x3754 +#define DI_VSC_REGION12_STARTP 0x3755 +#define DI_VSC_REGION34_STARTP 0x3756 +#define DI_VSC_REGION4_ENDP 0x3757 +#define DI_VSC_START_PHASE_STEP 0x3758 +#define DI_VSC_REGION0_PHASE_SLOPE 0x3759 +#define DI_VSC_REGION1_PHASE_SLOPE 0x375a +#define DI_VSC_REGION3_PHASE_SLOPE 0x375b +#define DI_VSC_REGION4_PHASE_SLOPE 0x375c +#define DI_VSC_PHASE_CTRL 0x375d +#define DI_VSC_INI_PHASE 0x375e +#define DI_HSC_REGION12_STARTP 0x3760 +#define DI_HSC_REGION34_STARTP 0x3761 +#define DI_HSC_REGION4_ENDP 0x3762 +#define DI_HSC_START_PHASE_STEP 0x3763 +#define DI_HSC_REGION0_PHASE_SLOPE 0x3764 +#define DI_HSC_REGION1_PHASE_SLOPE 0x3765 +#define DI_HSC_REGION3_PHASE_SLOPE 0x3766 +#define DI_HSC_REGION4_PHASE_SLOPE 0x3767 +#define DI_HSC_PHASE_CTRL 0x3768 +#define DI_SC_MISC 0x3769 +#define DI_HSC_PHASE_CTRL1 0x376a +#define DI_HSC_INI_PAT_CTRL 0x376b +#define DI_SC_GCLK_CTRL 0x376c +#define DI_SC_HOLD_LINE 0x376d + +/* DI H DOWN SCALER which IC? */ +#define DI_VIU_HSC_WIDTHM1 0x37b0 +#define DI_VIU_HSC_PHASE_STEP 0x37b1 +#define DI_VIU_HSC_CTRL 0x37b2 +#define DI_VIU_HSC_PHASE_CTRL 0x37b3 +#define DI_VIU_HSC_COEF 0x37b4 +#define DI_VIU_HSC_COEF_IDX 0x37b5 + +/* NR DOWNSAMPLE */ +#define NRDSWR_X 0x37f9 +#define NRDSWR_Y 0x37fa +#define NRDSWR_CTRL 0x37fb +#define NRDSWR_CAN_SIZE 0x37fc +#define NR_DS_BUF_SIZE_REG 0x3740 +#define NR_DS_CTRL 0x3741 +#define NR_DS_OFFSET 0x3742 +#define NR_DS_BLD_COEF 0x3743 +/* di */ +#define DI_IF1_URGENT_CTRL (0x20a3) /* << 2 + 0xd0100000*/ +/* bit15, auto enable; bit14, canvas write mode ;7:4, high threshold ;3:0 , + * low threshold for di inp chroma path + * bit31, auto enable; bit30, canvas write mode ;23:20, high threshold ;19:16 , + * low threshold for di inp luma path + */ +#define DI_INP_URGENT_CTRL (0x20a4) /* << 2 + 0xd0100000*/ +/* bit15, auto enable; bit14, canvas write mode ;7:4, high threshold ;3:0 , + * low threshold for di mem chroma path + * bit31, auto enable; bit30, canvas write mode ;23:20, high threshold ;19:16 , + * low threshold for di mem luma path + */ +#define DI_MEM_URGENT_CTRL (0x20a5) /* << 2 + 0xd0100000*/ +/* bit15, auto enable; bit14, canvas write mode ;7:4, high threshold ;3:0 , + * low threshold for di chan2 chroma path + * bit31, auto enable; bit30, canvas write mode ;23:20, high threshold ;19:16 , + * low threshold for di chan2 luma path + */ +#define DI_CHAN2_URGENT_CTRL (0x20a6) /* << 2 + 0xd0100000*/ + +#define DI_PRE_CTRL ((0x1700)) /* << 2) + 0xd0100000) */ +/* bit 31, cbus_pre_frame_rst */ +/* bit 30, cbus_pre_soft_rst */ +/* bit 29, pre_field_num */ +/* bit 27:26, mode_444c422 */ +/* bit 25, di_cont_read_en */ +/* bit 24:23, mode_422c444 */ +/* bit 22, mtn_after_nr */ +/* bit 21:16, pre_hold_fifo_lines */ +/* bit 15, nr_wr_by */ +/* bit 14, use_vdin_go_line */ +/* bit 13, di_prevdin_en */ +/* bit 12, di_pre_viu_link */ +/* bit 11, di_pre_repeat */ /*ary : g12a: di_chan3_enable*/ +/* bit 10, di_pre_drop_1st */ +/* bit 9, di_buf2_en */ +/* bit 8, di_chan2_en */ +/* bit 7, prenr_hist_en */ +/* bit 6, chan2_hist_en */ +/* bit 5, hist_check_en */ +/* bit 4, check_after_nr */ +/* bit 3, check222p_en */ +/* bit 2, check322p_en */ +/* bit 1, mtn_en */ +/* bit 0, nr_en */ +/* #define DI_POST_CTRL ((0x1701)) */ +/* bit 31, cbus_post_frame_rst */ +/* bit 30, cbus_post_soft_rst */ +/* bit 29, post_field_num */ +/* bit 21:16, post_hold_fifo_lines */ +/* bit 13, prepost_link */ +/* bit 12, di_post_viu_link */ +/* bit 11, di_post_repeat */ +/* bit 10, di_post_drop_1st */ +/* bit 9, mif0_to_vpp_en */ +/* bit 8, di_vpp_out_en */ +/* bit 7, di_wr_bk_en */ +/* bit 6, di_mux_en */ +/* bit 5, di_blend_en */ +/* bit 4, di_mtnp_read_en */ +/* bit 3, di_mtn_buf_en */ +/* bit 2, di_ei_en */ +/* bit 1, di_buf1_en */ +/* bit 0, di_buf0_en */ +/* #define DI_POST_SIZE ((0x1702)) */ +/* bit 28:16, vsize1post */ +/* bit 12:0, hsize1post */ +#define DI_PRE_SIZE ((0x1703)) /* << 2) + 0xd0100000) */ +/* bit 28:16, vsize1pre */ +/* bit 12:0, hsize1pre */ +#define DI_EI_CTRL0 ((0x1704)) /* << 2) + 0xd0100000) */ +/* bit 23:16, ei0_filter[2:+] abs_diff_left>filter && + * ...right>filter && ...top>filter && ...bot>filter -> filter + */ +/* bit 15:8, ei0_threshold[2:+] */ +/* bit 3, ei0_vertical */ +/* bit 2, ei0_bpscf2 */ +/* bit 1, ei0_bpsfar1 */ +#define DI_EI_CTRL1 ((0x1705)) /* << 2) + 0xd0100000) */ +/* bit 31:24, ei0_diff */ +/* bit 23:16, ei0_angle45 */ +/* bit 15:8, ei0_peak */ +/* bit 7:0, ei0_cross */ +#define DI_EI_CTRL2 ((0x1706)) /* << 2) + 0xd0100000) */ +/* bit 31:24, ei0_close2 */ +/* bit 23:16, ei0_close1 */ +/* bit 15:8, ei0_far2 */ +/* bit 7:0, ei0_far1 */ +#define DI_NR_CTRL0 ((0x1707)) /* << 2) + 0xd0100000) */ +/* bit 26, nr_cue_en */ +/* bit 25, nr2_en */ +#define DI_NR_CTRL1 ((0x1708)) /* << 2) + 0xd0100000) */ +/* bit 31:30, mot_p1txtcore_mode */ +/* bit 29:24, mot_p1txtcore_clmt */ +/* bit 21:16, mot_p1txtcore_ylmt */ +/* bit 15:8, mot_p1txtcore_crate */ +/* bit 7:0, mot_p1txtcore_yrate */ +#define DI_NR_CTRL2 ((0x1709)) /* << 2) + 0xd0100000) */ +/* bit 29:24, mot_curtxtcore_clmt */ +/* bit 21:16, mot_curtxtcore_ylmt */ +/* bit 15:8, mot_curtxtcore_crate */ +/* bit 7:0, mot_curtxtcore_yrate */ +/* `define DI_NR_CTRL3 8'h0a */ +/* no use */ +/* `define DI_MTN_CTRL 8'h0b */ +/* no use */ +#define DI_MTN_CTRL1 ((0x170c)) /* << 2) + 0xd0100000) */ +/* bit 13 , me enable */ +/* bit 12 , me autoenable */ +/* bit 11:8, mtn_paramtnthd */ +/* bit 7:0, mtn_parafltthd */ +#define DI_BLEND_CTRL ((0x170d)) /* << 2) + 0xd0100000) */ +/* bit 31, blend_1_en */ +/* bit 30, blend_mtn_lpf */ +/* bit 28, post_mb_en */ +/* bit 27, blend_mtn3p_max */ +/* bit 26, blend_mtn3p_min */ +/* bit 25, blend_mtn3p_ave */ +/* bit 24, blend_mtn3p_maxtb */ +/* bit 23, blend_mtn_flt_en */ +/* bit 22, blend_data_flt_en */ +/* bit 21:20, blend_top_mode */ +/* bit 19, blend_reg3_enable */ +/* bit 18, blend_reg2_enable */ +/* bit 17, blend_reg1_enable */ +/* bit 16, blend_reg0_enable */ +/* bit 15:14, blend_reg3_mode */ +/* bit 13:12, blend_reg2_mode */ +/* bit 11:10, blend_reg1_mode */ +/* bit 9:8, blend_reg0_mode */ +/* bit 7:0, kdeint */ +/* `define DI_BLEND_CTRL1 8'h0e */ +/* no use */ +/* `define DI_BLEND_CTRL2 8'h0f */ +/* no use */ +#define DI_ARB_CTRL ((0x170f)) /* << 2) + 0xd0100000) */ +/* bit 31:26, di_arb_thd1 */ +/* bit 25:20, di_arb_thd0 */ +/* bit 19, di_arb_tid_mode */ +/* bit 18, di_arb_arb_mode */ +/* bit 17, di_arb_acq_en */ +/* bit 16, di_arb_disable_clk */ +/* bit 15:0, di_arb_req_en */ +#define DI_BLEND_REG0_X ((0x1710)) /* << 2) + 0xd0100000) */ +/* bit 27:16, blend_reg0_startx */ +/* bit 11:0, blend_reg0_endx */ +#define DI_BLEND_REG0_Y ((0x1711)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG1_X ((0x1712)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG1_Y ((0x1713)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG2_X ((0x1714)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG2_Y ((0x1715)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG3_X ((0x1716)) /* << 2) + 0xd0100000) */ +#define DI_BLEND_REG3_Y ((0x1717)) /* << 2) + 0xd0100000) */ +#define DI_CLKG_CTRL ((0x1718)) /* << 2) + 0xd0100000) */ +/* bit 31:24, pre_gclk_ctrl no clk gate control. if ==1, + * module clk is not gated (always on). [3] for pulldown,[2] + * for mtn_1,[1] for mtn_0,[0] for nr + * bit 23:16, post_gclk_ctrl no clk gate control. [4] + * for ei_1, [3] for ei_0,[2] for ei_top, [1] for blend_1, [0] for blend_0 + * bit 1, di_gate_all clk shut down. if ==1 , + * all di clock shut down + * bit 0, di_no_clk_gate no clk gate control. + * if di_gated_all==0 and di_no_clk_gate ==1, all di clock is always working. + */ +#define DI_EI_CTRL3 ((0x1719)) /* << 2) + 0xd0100000) */ +/* bit 31, reg_ei_1 */ +/* bit 30, reg_demon_en */ +/* bit 26:24, reg_demon_mux */ +/* bit 23:20, reg_right_win */ +/* bit 19:16, reg_left_win */ +/* bit 7:4, reg_ei_sadm_quatize_margin */ +/* bit 1:0, reg_ei_sad_relative_mode */ +#define DI_EI_CTRL4 ((0x171a)) /* << 2) + 0xd0100000) */ +/* bit 29, reg_ei_caldrt_ambliike2_biasvertical */ +/* bit 28:24, reg_ei_caldrt_addxla2list_drtmax */ +/* bit 22:20, reg_ei_caldrt_addxla2list_signm0th */ +/* bit 19, reg_ei_caldrt_addxla2list_mode */ +/* bit 18:16, reg_ei_signm_sad_cor_rate */ +/* bit 15:12, reg_ei_signm_sadi_cor_rate */ +/* bit 11:6, reg_ei_signm_sadi_cor_ofst */ +/* bit 5:0, reg_ei_signm_sad_ofst */ +#define DI_EI_CTRL5 ((0x171b)) /* << 2) + 0xd0100000) */ +/* bit 30:28, reg_ei_caldrt_cnflcctchk_frcverthrd */ +/* bit 26:24, reg_ei_caldrt_cnflctchk_mg */ +/* bit 23:22, reg_ei_caldrt_cnflctchk_ws */ +/* bit 21, reg_ei_caldrt_cnflctchk_en */ +/* bit 20, reg_ei_caldrt_verfrc_final_en */ +/* bit 19, reg_ei_caldrt_verfrc_retimflt_en */ +/* bit 18:16, reg_ei_caldrt_verftc_eithratemth */ +/* bit 15, reg_ei_caldrt_verfrc_retiming_en */ +/* bit 14:12, reg_ei_caldrt_verfrc_bothratemth */ +/* bit 11:9, reg_ei_caldrt_ver_thrd */ +/* bit 8:4, reg_ei_caldrt_addxla2list_drtmin */ +/* bit 3:0, reg_ei_caldrt_addxla2list_drtlimit */ +#define DI_EI_CTRL6 ((0x171c)) /* << 2) + 0xd0100000) */ +/* bit 31:24, reg_ei_caldrt_abext_sad12thhig */ +/* bit 23:16, reg_ei_caldrt_abext_sad00thlow */ +/* bit 15:8, reg_ei_caldrt_abext_sad12thlow */ +/* bit 6:4, reg_ei_caldrt_abext_ratemth */ +/* bit 2:0, reg_ei_caldrt_abext_drtthrd */ +#define DI_EI_CTRL7 ((0x171d)) /* << 2) + 0xd0100000) */ +/* bit 29, reg_ei_caldrt_xlanopeak_codien */ +/* bit 28:24, reg_ei_caldrt_xlanopeak_drtmax */ +/* bit 23, reg_ei_caldrt_xlanopeak_en */ +/* bit 28:24, reg_ei_caldrt_abext_monotrnd_alpha */ +/* bit 28:24, reg_ei_caldrt_abext_mononum12_thrd */ +/* bit 28:24, reg_ei_caldrt_abext_mononum00_thrd */ +/* bit 28:24, reg_ei_caldrt_abext_sad00rate */ +/* bit 28:24, reg_ei_caldrt_abext_sad12rate */ +/* bit 28:24, reg_ei_caldrt_abext_sad00thhig */ +#define DI_EI_CTRL8 ((0x171e)) /* << 2) + 0xd0100000) */ +/* bit 30:28, reg_ei_assign_headtail_magin */ +/* bit 26:24, reg_ei_retime_lastcurpncnfltchk_mode */ +/* bit 22:21, reg_ei_retime_lastcurpncnfltchk_drtth */ +/* bit 20, reg_ei_caldrt_histchk_cnfid */ +/* bit 19:16, reg_ei_caldrt_histchk_thrd */ +/* bit 15, reg_ei_caldrt_histchk_abext */ +/* bit 14, reg_ei_caldrt_histchk_npen */ +/* bit 13:11, reg_ei_caldrt_amblike2_drtmg */ +/* bit 10:8, reg_ei_caldrt_amblike2_valmg */ +/* bit 7:4, reg_ei_caldrt_amblike2_alpha */ +/* bit 3:0, reg_ei_caldrt_amblike2_drtth */ +#define DI_EI_CTRL9 ((0x171f)) /* << 2) + 0xd0100000) */ +/* bit 31:28, reg_ei_caldrt_hcnfcheck_frcvert_xla_th3 */ +/* bit 27, reg_ei_caldrt_hcnfcheck_frcvert_xla_en */ +/* bit 26:24, reg_ei_caldrt_conf_drtth */ +/* bit 23:20, reg_ei_caldrt_conf_absdrtth */ +/* bit 19:18, reg_ei_caldrt_abcheck_mode1 */ +/* bit 17:16, reg_ei_caldrt_abcheck_mode0 */ +/* bit 15:12, reg_ei_caldrt_abcheck_drth1 */ +/* bit 11:8, reg_ei_caldrt_abcheck_drth0 */ +/* bit 6:4, reg_ei_caldrt_abpnchk1_th */ +/* bit 1, reg_ei_caldrt_abpnchk1_en */ +/* bit 0, reg_ei_caldrt_abpnchk0_en */ +#define DI_EI_CTRL10 ((0x1793)) /* << 2) + 0xd0100000) */ +/* bit 31:28, reg_ei_caldrt_hstrrgchk_drtth */ +/* bit 27:24, reg_ei_caldrt_hstrrgchk_frcverthrd */ +/* bit 23:20, reg_ei_caldrt_hstrrgchk_mg */ +/* bit 19, reg_ei_caldrt_hstrrgchk_1sidnul */ +/* bit 18, reg_ei_caldrt_hstrrgchk_excpcnf */ +/* bit 17:16, reg_ei_caldrt_hstrrgchk_ws */ +/* bit 15, reg_ei_caldrt_hstrrgchk_en */ +/* bit 14:13, reg_ei_caldrt_hpncheck_mode */ +/* bit 12, reg_ei_caldrt_hpncheck_mute */ +/* bit 11:9, reg_ei_caldrt_hcnfcheck_mg2 */ +/* bit 8:6, reg_ei_caldrt_hcnfcheck_mg1 */ +/* bit 5:4, reg_ei_caldrt_hcnfcheck_mode */ +/* bit 3:0, reg_ei_caldrt_hcnfcheck_mg2 */ +#define DI_EI_CTRL11 ((0x179e)) /* << 2) + 0xd0100000) */ +/* bit 30:29, reg_ei_amb_detect_mode */ +/* bit 28:24, reg_ei_amb_detect_winth */ +/* bit 23:21, reg_ei_amb_decide_rppth */ +/* bit 20:19, reg_ei_retime_lastmappncnfltchk_drtth */ +/* bit 18:16, reg_ei_retime_lastmappncnfltchk_mode */ +/* bit 15:14, reg_ei_retime_lastmapvertfrcchk_mode */ +/* bit 13:12, reg_ei_retime_lastvertfrcchk_mode */ +/* bit 11:8, reg_ei_retime_lastpnchk_drtth */ +/* bit 6, reg_ei_retime_lastpnchk_en */ +/* bit 5:4, reg_ei_retime_mode */ +/* bit 3, reg_ei_retime_last_en */ +/* bit 2, reg_ei_retime_ab_en */ +/* bit 1, reg_ei_caldrt_hstrvertfrcchk_en */ +/* bit 0, reg_ei_caldrt_hstrrgchk_mode */ +#define DI_EI_CTRL12 ((0x179f)) /* << 2) + 0xd0100000) */ +/* bit 31:28, reg_ei_drtdelay2_lmt */ +/* bit 27:26, reg_ei_drtdelay2_notver_lrwin */ +/* bit 25:24, reg_ei_drtdelay_mode */ +/* bit 23, reg_ei_drtdelay2_mode */ +/* bit 22:20, reg_ei_assign_xla_signm0th */ +/* bit 19, reg_ei_assign_pkbiasvert_en */ +/* bit 18, reg_ei_assign_xla_en */ +/* bit 17:16, reg_ei_assign_xla_mode */ +/* bit 15:12, reg_ei_assign_nlfilter_magin */ +/* bit 11:8, reg_ei_localsearch_maxrange */ +/* bit 7:4, reg_ei_xla_drtth */ +/* bit 3:0, reg_ei_flatmsad_thrd */ +#define DI_EI_CTRL13 ((0x17a8)) /* << 2) + 0xd0100000) */ +/* bit 27:24, reg_ei_int_drt2x_chrdrt_limit */ +/* bit 23:20, reg_ei_int_drt16x_core */ +/* bit 19:16, reg_ei_int_drtdelay2_notver_cancv */ +/* bit 15:8, reg_ei_int_drtdelay2_notver_sadth */ +/* bit 7:0, reg_ei_int_drtdelay2_vlddrt_sadth */ +#define DI_EI_XWIN0 ((0x1798)) /* << 2) + 0xd0100000) */ +/* bit 27:16, ei_xend0 */ +/* bit 11:0, ei_xstart0 */ +#define DI_EI_XWIN1 ((0x1799)) /* << 2) + 0xd0100000) */ +/* DEINTERLACE mode check. */ +#define DI_MC_REG0_X ((0x1720)) /* << 2) + 0xd0100000) */ +/* bit 27:16, mc_reg0_start_x */ +/* bit 11:0, mc_reg0_end_x */ +#define DI_MC_REG0_Y ((0x1721)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG1_X ((0x1722)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG1_Y ((0x1723)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG2_X ((0x1724)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG2_Y ((0x1725)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG3_X ((0x1726)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG3_Y ((0x1727)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG4_X ((0x1728)) /* << 2) + 0xd0100000) */ +#define DI_MC_REG4_Y ((0x1729)) /* << 2) + 0xd0100000) */ +#define DI_MC_32LVL0 ((0x172a)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mc_reg2_32lvl */ +/* bit 23:16, mc_reg1_32lvl */ +/* bit 15:8, mc_reg0_32lvl */ +/* bit 7:0, field_32lvl */ +#define DI_MC_32LVL1 ((0x172b)) /* << 2) + 0xd0100000) */ +/* bit 15:8, mc_reg3_32lvl */ +/* bit 7:0, mc_reg4_32lvl */ +#define DI_MC_22LVL0 ((0x172c)) /* << 2) + 0xd0100000) */ +/* bit 31:16, mc_reg0_22lvl */ +/* bit 15:0, field_22lvl */ +#define DI_MC_22LVL1 ((0x172d)) /* << 2) + 0xd0100000) */ +/* bit 31:16, mc_reg2_22lvl */ +/* bit 15:0, mc_reg1_22lvl */ +#define DI_MC_22LVL2 ((0x172e)) /* << 2) + 0xd0100000) */ +/* bit 31:16, mc_reg4_22lvl */ +/* bit 15:0, mc_reg3_22lvl */ +#define DI_MC_CTRL ((0x172f)) /* << 2) + 0xd0100000) */ +/* bit 4, mc_reg4_en */ +/* bit 3, mc_reg3_en */ +/* bit 2, mc_reg2_en */ +/* bit 1, mc_reg1_en */ +/* bit 0, mc_reg0_en */ +#define DI_INTR_CTRL ((0x1730)) /* << 2) + 0xd0100000) */ +#define DI_INFO_ADDR ((0x1731)) /* << 2) + 0xd0100000) */ +#define DI_INFO_DATA ((0x1732)) /* << 2) + 0xd0100000) */ +#define DI_PRE_HOLD ((0x1733)) /* << 2) + 0xd0100000) */ +#define DI_MTN_1_CTRL1 ((0x1740)) /* << 2) + 0xd0100000) */ +/* bit 31, mtn_1_en */ +/* bit 30, mtn_init */ +/* bit 29, di2nr_txt_en */ +/* bit 28, di2nr_txt_mode */ +/* bit 27:24, mtn_def */ +/* bit 23:16, mtn_adp_yc */ +/* bit 15:8, mtn_adp_2c */ +/* bit 7:0, mtn_adp_2y */ +#define DI_MTN_1_CTRL2 ((0x1741)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_ykinter */ +/* bit 23:16, mtn_ckinter */ +/* bit 15:8, mtn_ykintra */ +/* bit 7:0, mtn_ckintra */ +#define DI_MTN_1_CTRL3 ((0x1742)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_tyrate */ +/* bit 23:16, mtn_tcrate */ +/* bit 15: 8, mtn_mxcmby */ +/* bit 7: 0, mtn_mxcmbc */ +#define DI_MTN_1_CTRL4 ((0x1743)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_tcorey */ +/* bit 23:16, mtn_tcorec */ +/* bit 15: 8, mtn_minth */ +/* bit 7: 0, mtn_maxth */ +#define DI_MTN_1_CTRL5 ((0x1744)) /* << 2) + 0xd0100000) */ +/* bit 31:28, mtn_m1b_extnd */ +/* bit 27:24, mtn_m1b_errod */ +/* bit 19:18, mtn_replace_cbyy */ +/* bit 17:16, mtn_replace_ybyc */ +/* bit 15: 8, mtn_core_ykinter */ +/* bit 7: 0, mtn_core_ckinter */ +#define DI_MTN_1_CTRL6 ((0x17a9)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_m1b_extnd */ +/* bit 23:16, mtn_m1b_errod */ +/* bit 15: 8, mtn_core_ykinter */ +/* bit 7: 0, mtn_core_ckinter */ +#define DI_MTN_1_CTRL7 ((0x17aa)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_core_mxcmby */ +/* bit 23:16, mtn_core_mxcmbc */ +/* bit 15: 8, mtn_core_y */ +/* bit 7: 0, mtn_core_c */ +#define DI_MTN_1_CTRL8 ((0x17ab)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_fcore_ykinter */ +/* bit 23:16, mtn_fcore_ckinter */ +/* bit 15: 8, mtn_fcore_ykintra */ +/* bit 7: 0, mtn_fcore_ckintra */ +#define DI_MTN_1_CTRL9 ((0x17ac)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_fcore_2yrate */ +/* bit 23:16, mtn_fcore_2crate */ +/* bit 15: 8, mtn_fcore_y */ +/* bit 7: 0, mtn_fcore_c */ +#define DI_MTN_1_CTRL10 ((0x17ad)) /* << 2) + 0xd0100000) */ +/* bit 27:24, mtn_motfld0 */ +/* bit 19:16, mtn_stlfld0 */ +/* bit 11: 8, mtn_motfld1 */ +/* bit 3: 0, mtn_stlfld1 */ +#define DI_MTN_1_CTRL11 ((0x17ae)) /* << 2) + 0xd0100000) */ +/* bit 27:24, mtn_smotevn */ +/* bit 20:16, mtn_smotodd */ +/* bit 11: 8, mtn_sstlevn */ +/* bit 4: 0, mtn_sstlodd */ +#define DI_MTN_1_CTRL12 ((0x17af)) /* << 2) + 0xd0100000) */ +/* bit 31:24, mtn_mgain */ +/* bit 17:16, mtn_mmode */ +/* bit 15: 8, mtn_sthrd */ +/* bit 4: 0, mtn_sgain */ +/* // DET 3D REG DEFINE BEGIN //// */ +/* // 8'h34~8'h3f */ +#define DET3D_MOTN_CFG ((0x1734)) /* << 2) + 0xd0100000) */ +/* Bit 16, reg_det3d_intr_en Det3d interrupt enable + * Bit 9:8, reg_Det3D_Motion_Mode + * U2 Different mode for Motion Calculation of Luma and Chroma: + * 0: MotY, 1: (2*MotY + (MotU + MotV))/4; + * 2: Max(MotY, MotU,MotV); 3:Max(MotY, (MotU+MotV)/2) + * Bit 7:4, reg_Det3D_Motion_Core_Rate U4 K Rate to Edge (HV) details + * for coring of Motion Calculations, normalized to 32 + * Bit 3:0, reg_Det3D_Motion_Core_Thrd + * U4 2X: static coring value for Motion Detection. + */ +#define DET3D_CB_CFG ((0x1735)) /* << 2) + 0xd0100000) */ +/* Bit 7:4, reg_Det3D_ChessBd_NHV_ofst + * U4, Noise immune offset for NON-Horizotnal or vertical combing detection. + * + * Bit 3:0, reg_Det3D_ChessBd_HV_ofst + * U4, Noise immune offset for Horizotnal or vertical combing detection. + */ +#define DET3D_SPLT_CFG ((0x1736)) /* << 2) + 0xd0100000) */ +/* Bit 7:4, reg_Det3D_SplitValid_ratio + * U4, Ratio between max_value and the avg_value of + * the edge mapping for split line valid detection. + * The smaller of this value, the easier of the split line detected. + * Bit 3:0, reg_Det3D_AvgIdx_ratio U4,Ratio to the avg_value of the + * edge mapping for split line position estimation. + */ +/* The smaller of this value, + * the more samples will be added to the estimation. + */ +#define DET3D_HV_MUTE ((0x1737)) /* << 2) + 0xd0100000) */ +/* Bit 23:20, reg_Det3D_Edge_Ver_Mute U4 X2: Horizontal pixels to be mute + * from H/V Edge calculation Top and Bottom border part. + * Bit 19:16, reg_Det3D_Edge_Hor_Mute U4 X2: Horizontal pixels to be mute + * from H/V Edge calculation Left and right border part. + * Bit 15:12, reg_Det3D_ChessBd_Ver_Mute U4 X2: Horizontal pixels to + * be mute from ChessBoard statistics calculation in middle part + * Bit 11:8, reg_Det3D_ChessBd_Hor_Mute U4 X2: Horizontal pixels to + * be mute from ChessBoard statistics calculation in middle part + * Bit 7:4, reg_Det3D_STA8X8_Ver_Mute U4 1X: Vertical pixels to be + * mute from 8x8 statistics calculation in each block. + * Bit 3:0, reg_Det3D_STA8X8_Hor_Mute U4 1X: Horizontal pixels to + * be mute from 8x8 statistics calculation in each block. + */ +#define DET3D_MAT_STA_P1M1 ((0x1738)) /* << 2) + 0xd0100000) */ +/* Bit 31:24, reg_Det3D_STA8X8_P1_K0_R8 U8 SAD to SAI ratio to decide P1, + * normalized to 256 (0.8) + * Bit 23:16, reg_Det3D_STA8X8_P1_K1_R7 U8 SAD to ENG ratio to decide P1, + * normalized to 128 (0.5) + * Bit 15:8, reg_Det3D_STA8X8_M1_K0_R6 + * U8 SAD to SAI ratio to decide M1, normalized to 64 (1.1) + * Bit 7:0, reg_Det3D_STA8X8_M1_K1_R6 + * U8 SAD to ENG ratio to decide M1, normalized to 64 (0.8) + */ +#define DET3D_MAT_STA_P1TH ((0x1739)) /* << 2) + 0xd0100000) */ +/* Bit 23:16, reg_Det3D_STAYUV_P1_TH_L4 U8 SAD to ENG Thrd offset to + * decide P1, X16 (100) + * Bit 15:8, reg_Det3D_STAEDG_P1_TH_L4 U8 SAD to ENG Thrd + * offset to decide P1, X16 (80) + * Bit 7:0, reg_Det3D_STAMOT_P1_TH_L4 U8 SAD to ENG Thrd + * offset to decide P1, X16 (48) + */ +#define DET3D_MAT_STA_M1TH ((0x173a)) /* << 2) + 0xd0100000) */ +/* Bit 23:16, reg_Det3D_STAYUV_M1_TH_L4 U8 SAD to + * ENG Thrd offset to decide M1, X16 (100) + * Bit 15:8, reg_Det3D_STAEDG_M1_TH_L4 + * U8 SAD to ENG Thrd offset to decide M1, X16 (80) + * Bit 7:0, reg_Det3D_STAMOT_M1_TH_L4 + * U8 SAD to ENG Thrd offset to decide M1, X16 (64) + */ +#define DET3D_MAT_STA_RSFT ((0x173b)) /* << 2) + 0xd0100000) */ +/* Bit 5:4, reg_Det3D_STAYUV_RSHFT U2 YUV statistics SAD and SAI + * calculation result right shift bits to accommodate the 12bits clipping: + * 0: mainly for images <=720x480: + * 1: mainly for images <=1366x768: + * 2: mainly + * for images <=1920X1080: 2; 3: other higher resolutions + * Bit 3:2, reg_Det3D_STAEDG_RSHFT U2 Horizontal and Vertical Edge + * Statistics SAD and SAI calculation result right shift bits to + * accommodate the 12bits clipping: + * 0: mainly for images <=720x480: 1: mainly for images <=1366x768: + * 2: mainly for images <=1920X1080: 2; 3: other higher resolutions + * Bit 1:0, reg_Det3D_STAMOT_RSHFT U2 Motion SAD and SAI + * calculation result right shift bits to accommodate the 12bits clipping: + * 0: mainly for images <=720x480: 1: mainly for images <=1366x768: + * 2: mainly for images <=1920X1080: 2; 3: other higher resolutions + */ +#define DET3D_MAT_SYMTC_TH ((0x173c)) /* << 2) + 0xd0100000) */ +/* Bit 31:24, reg_Det3D_STALUM_symtc_Th U8 threshold to decide + * if the Luma statistics is TB or LR symmetric. + * Bit 23:16, reg_Det3D_STACHR_symtc_Th U8 threshold to decide + * if the Chroma (UV) statistics is TB or LR symmetric. + * Bit 15:8, reg_Det3D_STAEDG_symtc_Th U8 threshold to + * decide if the Horizontal and Vertical Edge statistics is TB or LR symmetric. + * Bit 7:0, reg_Det3D_STAMOT_symtc_Th U8 threshold to + * decide if the Motion statistics is TB or LR symmetric. + */ +#define DET3D_RO_DET_CB_HOR ((0x173d)) /* << 2) + 0xd0100000) */ +/* Bit 31:16, RO_Det3D_ChessBd_NHor_value U16 X64: number of Pixels + * of Horizontally Surely NOT matching Chessboard pattern. + * Bit 15:0, RO_Det3D_ChessBd_Hor_value U16 X64: number of + * Pixels of Horizontally Surely matching Chessboard pattern. + */ +#define DET3D_RO_DET_CB_VER ((0x173e)) /* << 2) + 0xd0100000) */ +/* Bit 31:16, RO_Det3D_ChessBd_NVer_value U16 X64: number of + * Pixels of Vertically Surely NOT matching Chessboard pattern. + * Bit 15:0, RO_Det3D_ChessBd_Ver_value U16 X64: number + * of Pixels of Vertically Surely matching Chessboard pattern. + */ +#define DET3D_RO_SPLT_HT ((0x173f)) /* << 2) + 0xd0100000) */ +/* Bit 24, RO_Det3D_Split_HT_valid U1 horizontal LR split border + * detected valid signal for top half picture + * Bit 20:16, RO_Det3D_Split_HT_pxnum U5 number of pixels included for the + * LR split position estimation for top half picture + * Bit 9:0, RO_Det3D_Split_HT_idxX4 S10 X4: horizontal pixel + * shifts of LR split position to the (ColMax/2) for top half picture + * // DET 3D REG DEFINE END //// + * // NR2 REG DEFINE BEGIN//// + */ +#define NR2_MET_NM_CTRL ((0x1745)) /* << 2) + 0xd0100000) */ +/* Bit 28, reg_NM_reset Reset to the status of the Loop filter. + * Bit 27:24, reg_NM_calc_length Length mode of the Noise + * measurement sample number for statistics. + * 0: 256 samples; 1: 512 samples; 2: 1024 samples; + * ¡­X: 2^(8+x) samples + * Bit 23:20, reg_NM_inc_step Loop filter input gain increase step. + * Bit 19:16, reg_NM_dec_step Loop filter input gain decrease step. + * Bit 15:8, reg_NM_YHPmot_thrd Luma channel HP portion motion + * for condition of pixels included in Luma Noise measurement. + * Bit 7:0, reg_NM_CHPmot_thrd Chroma channel HP portion motion + * for condition of pixels included in Chroma Noise measurement. + */ +#define NR2_MET_NM_YCTRL ((0x1746)) /* << 2) + 0xd0100000) */ +/* Bit 31:28, reg_NM_YPLL_target Target rate of + * NM_Ynoise_thrd to mean of the Luma Noise + * Bit 27:24, reg_NM_YLPmot_thrd Luma channel LP + * portion motion for condition of pixels included in Luma Noise measurement. + * Bit 23:16, reg_NM_YHPmot_thrd_min Minimum threshold for + * Luma channel HP portion motion to decide whether the pixel + * will be included in Luma noise measurement. + * Bit 15:8, reg_NM_YHPmot_thrd_max Maximum threshold for Luma + * channel HP portion motion to decide whether the pixel will be included in + * Luma noise measurement. + * Bit 7:0, reg_NM_Ylock_rate Rate to decide whether the + * Luma noise measurement is lock or not. + */ +#define NR2_MET_NM_CCTRL ((0x1747)) /* << 2) + 0xd0100000) */ +/* Bit 31:28, reg_NM_CPLL_target + * Target rate of NM_Cnoise_thrd to mean of the Chroma Noise + * Bit 27:24, reg_NM_CLPmot_thrd Chroma channel LP portion motion + * for condition of pixels included in Chroma Noise measurement. + * Bit 23:16, reg_NM_CHPmot_thrd_min Minimum threshold for Chroma channel + * HP portion motion to decide whether the pixel will be + * included in Chroma noise measurement. + * Bit 15:8, reg_NM_CHPmot_thrd_max Maximum threshold for Chroma + * channel HP portion motion to decide whether the pixel will be included in + * Chroma noise measurement. + * Bit 7:0, reg_NM_Clock_rate Rate to decide whether the Chroma + * noise measurement is lock or not; + */ +#define NR2_MET_NM_TNR ((0x1748)) /* << 2) + 0xd0100000) */ +/* Bit 25, ro_NM_TNR_Ylock Read-only register to tell + * ifLuma channel noise measurement is locked or not. + * Bit 24, ro_NM_TNR_Clock Read-only register to tell + * if Chroma channel noise measurement is locked or not. + * Bit 23:12, ro_NM_TNR_Ylevel Read-only register to give Luma + * channel noise level. It was 16x of pixel difference in 8 bits of YHPmot. + * Bit 11:0, ro_NM_TNR_ClevelRead-only register to give Chroma channel noise + * level.It was 16x of pixel difference in 8 bits of CHPmot. + */ +#define NR2_MET_NMFRM_TNR_YLEV ((0x1749)) /* << 2) + 0xd0100000) */ +/* Bit 28:0, ro_NMFrm_TNR_Ylevel Frame based Read-only register + * to give Luma channel noise level within one frame/field. + */ +#define NR2_MET_NMFRM_TNR_YCNT ((0x174a)) /* << 2) + 0xd0100000) */ +/* Bit 23:0, ro_NMFrm_TNR_Ycount Number ofLuma channel pixels + * included in Frame/Field based noise level measurement. + */ +#define NR2_MET_NMFRM_TNR_CLEV ((0x174b)) /* << 2) + 0xd0100000) */ +/* Bit 28:0, ro_NMFrm_TNR_Clevel Frame based Read-only register + * to give Chroma channel noise level within one frame/field. + */ +#define NR2_MET_NMFRM_TNR_CCNT ((0x174c)) /* << 2) + 0xd0100000) */ +/* Bit 23:0, ro_NMFrm_TNR_Ccount Number of Chroma channel pixels + * included in Frame/Field based noise level measurement. + */ +#define NR2_3DEN_MODE ((0x174d)) /* << 2) + 0xd0100000) */ +/* Bit 6:4, Blend_3dnr_en_r */ +/* Bit 2:0, Blend_3dnr_en_l */ +#define NR2_IIR_CTRL ((0x174e)) /* << 2) + 0xd0100000) */ +/* Bit 15:14, reg_LP_IIR_8bit_mode LP IIR membitwidth mode: + * 0: 10bits will be store in memory; + * 1: 9bits will be store in memory; + * 2: 8bits will be store in memory; + * 3: 7bits will be store in memory; + * Bit 13:12, reg_LP_IIR_mute_mode Mode for the LP IIR mute, + * Bit 11:8,reg_LP_IIR_mute_thrd Threshold of LP IIR mute to avoid ghost: + * Bit 7:6, reg_HP_IIR_8bit_mode IIR membitwidth mode: + * 0: 10bits will be store in memory; + * 1: 9bits will be store in memory; + * 2: 8bits will be store in memory; + * 3: 7bits will be store in memory; + * Bit 5:4, reg_HP_IIR_mute_mode Mode for theLP IIR mute + * Bit 3:0,reg_HP_IIR_mute_thrd Threshold of HP IIR mute to avoid ghost + */ +#define NR2_SW_EN ((0x174f)) /* << 2) + 0xd0100000) */ +/* Bit 17:8, Clk_gate_ctrl + * Bit 7, Cfr_enable + * Bit 5, Det3d_en + * Bit 4, Nr2_proc_en + * Bit 0, Nr2_sw_en + */ +#define NR2_FRM_SIZE ((0x1750)) /* << 2) + 0xd0100000) */ +/* Bit 27:16, Frm_heigh Frame/field height */ +/* Bit 11: 0, Frm_width Frame/field width */ +#define NR2_SNR_SAD_CFG ((0x1751)) /* << 2) + 0xd0100000) */ +/* Bit 12, reg_MATNR_SNR_SAD_CenRPL U1, Enable signal for Current + * pixel position SAD to be replaced by SAD_min.0: do not replace Current pixel + * position SAD by SAD_min;1: do replacements + * Bit 11:8, reg_MATNR_SNR_SAD_coring Coring value of the intra-frame + * SAD. sum = (sum - reg_MATNR_SNR_SAD_coring); + * sum = (sum<0) ? 0: (sum>255)? 255: sum; + * Bit 6:5, reg_MATNR_SNR_SAD_WinMod Unsigned, Intra-frame SAD + * matching window mode:0: 1x1; 1: [1 1 1] 2: [1 2 1]; 3: [1 2 2 2 1]; + * Bit 4:0, Sad_coef_num Sad coeffient + */ +#define NR2_MATNR_SNR_OS ((0x1752)) /* << 2) + 0xd0100000) */ +/* Bit 7:4, reg_MATNR_SNR_COS SNR Filter overshoot control + * margin for UV channel (X2 to u10 scale) + * Bit 3:0, reg_MATNR_SNR_YOS SNR Filter overshoot control + * margin for luma channel (X2 to u10 scale) + */ +#define NR2_MATNR_SNR_NRM_CFG ((0x1753)) /* << 2) + 0xd0100000) */ +/* Bit 23:16, reg_MATNR_SNR_NRM_ofst Edge based SNR + * boosting normalization offset to SAD_max ; + * Bit 15:8, reg_MATNR_SNR_NRM_max + * Edge based SNR boosting normalization Max value + * Bit 7:0, reg_MATNR_SNR_NRM_min + * Edge based SNR boosting normalization Min value + */ +#define NR2_MATNR_SNR_NRM_GAIN ((0x1754)) /* << 2) + 0xd0100000) */ +/* Bit 15:8, reg_MATNR_SNR_NRM_Cgain Edge based SNR boosting + * normalization Gain for Chrm channel (norm 32 as 1) + * Bit 7:0, reg_MATNR_SNR_NRM_Ygain Edge based SNR boosting + * normalization Gain for Luma channel (norm 32 as 1) + */ +#define NR2_MATNR_SNR_LPF_CFG ((0x1755)) /* << 2) + 0xd0100000) */ +/* Bit 23:16,reg_MATNR_SNRLPF_SADmaxTH U8, Threshold to SADmax to use TNRLPF + * to replace SNRLPF. i.e.if (SAD_max=) between LR and LL/RR. unsigned , default = 2 + */ +/* Bit 23:16, reg_dnr_hbof_edgethd , + * edge threshold (<=) for LR . unsigned , default = 32 + */ +/* Bit 15: 8, reg_dnr_hbof_flatthd , + * flat threshold (>=) for LR . unsigned , default = 0 + */ +/* Bit 7, reserved */ +/* Bit 6: 4, reg_dnr_hbof_delta , + * delta for weighted bin accumulator. unsigned , default = 1 + */ +/* Bit 3, reserved */ +/* Bit 2: 0, reg_dnr_hbof_statmod , + * statistic mode for horizontal block offset, 0: count flags for 8-bin, + * 1: count LRs for 8-bin, 2: count difs for 8-bin, + * 3: count weighted flags for 8-bin, 4: count flags for first 32-bin, + * 5: count LRs for first 32-bin, 6 or 7: count difs for first 32-bin. + * unsigned , default = 2 + */ +#define DNR_VBOFFST_STAT ((0x2d06)) +/* Bit 31:24, reg_dnr_vbof_difthd , + * dif threshold (>=) between Up and Dw. unsigned , default = 1 + */ +/* Bit 23:16, reg_dnr_vbof_edgethd , + * edge threshold (<=) for Up/Dw. unsigned , default = 16 + */ +/* Bit 15: 8, reg_dnr_vbof_flatthd , + * flat threshold (>=) for Up/Dw. unsigned , default = 0 + */ +/* Bit 7, reserved */ +/* Bit 6: 4, reg_dnr_vbof_delta , + * delta for weighted bin accumulator. unsigned , default = 1 + */ +/* Bit 3, reserved */ +/* Bit 2: 0, reg_dnr_vbof_statmod , + * statistic mode for vertical block offset, 0: count flags for 8-bin, + * 1: count Ups for 8-bin, 2: count difs for 8-bin, 3: count weighted + * flags for 8-bin, 4: count flags for first 32-bin, 5: count Ups for + * first 32-bin, 6 or 7: count difs for first 32-bin. unsigned , default = 2 + */ +#define DNR_GBS_STAT ((0x2d07)) +/* Bit 31:24, reg_dnr_gbs_edgethd , + * edge threshold (<=) for LR . unsigned , default = 32 + */ +/* Bit 23:16, reg_dnr_gbs_flatthd , + * flat threshold (>=) for LR . unsigned , default = 0 + */ +/* Bit 15: 8, reg_dnr_gbs_varthd , + * variation threshold (<=) for Lvar/Rvar. unsigned , default = 16 + */ +/* Bit 7: 0, reg_dnr_gbs_difthd , + * dif threshold (>=) between LR and LL/RR. unsigned , default = 2 + */ +#define DNR_STAT_X_START_END ((0x2d08)) +/* Bit 31:30, reserved */ +/* Bit 29:16, reg_dnr_stat_xst . unsigned , default = 24 */ +/* Bit 15:14, reserved */ +/* Bit 13: 0, reg_dnr_stat_xed . unsigned , default = HSIZE - 25 */ +#define DNR_STAT_Y_START_END ((0x2d09)) +/* Bit 31:30, reserved */ +/* Bit 29:16, reg_dnr_stat_yst . unsigned , default = 24 */ +/* Bit 15:14, reserved */ +/* Bit 13: 0, reg_dnr_stat_yed . unsigned , default = VSIZE - 25 */ +#define DNR_LUMA ((0x2d0a)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_dnr_luma_sqrtshft , + * left shift for fast squart of chroma, [0, 4]. unsigned , default = 2 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_dnr_luma_sqrtoffst , + * offset for fast squart of chroma. signed , default = 0 + */ +/* Bit 15, reserved */ +/* Bit 14:12, reg_dnr_luma_wcmod , + * theta related to warm/cool segment line, 0: 0, 1: 45, 2: 90, 3: 135, + * 4: 180, 5: 225, 6: 270, 7: 315. . unsigned , default = 3 + */ +/* Bit 11: 8, reg_dnr_luma_cshft , + * shift for calc. delta part, 0~8, . unsigned , default = 8 + */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_dnr_luma_cgain , + * final gain for delta part, 32 normalized to "1". unsigned , default = 4 + */ +#define DNR_DB_YEDGE_THD ((0x2d0b)) +/* Bit 31:24, reg_dnr_db_yedgethd0 , + * edge threshold0 for luma . unsigned , default = 12 + */ +/* Bit 23:16, reg_dnr_db_yedgethd1 , + * edge threshold1 for luma . unsigned , default = 15 + */ +/* Bit 15: 8, reg_dnr_db_yedgethd2 , + * edge threshold2 for luma . unsigned , default = 18 + */ +/* Bit 7: 0, reg_dnr_db_yedgethd3 , + * edge threshold3 for luma . unsigned , default = 25 + */ +#define DNR_DB_CEDGE_THD ((0x2d0c)) +/* Bit 31:24, reg_dnr_db_cedgethd0 , + * edge threshold0 for chroma . unsigned , default = 12 + */ +/* Bit 23:16, reg_dnr_db_cedgethd1 , + * edge threshold1 for chroma . unsigned , default = 15 + */ +/* Bit 15: 8, reg_dnr_db_cedgethd2 , + * edge threshold2 for chroma . unsigned , default = 18 + */ +/* Bit 7: 0, reg_dnr_db_cedgethd3 , + * edge threshold3 for chroma . unsigned , default = 25 + */ +#define DNR_DB_HGAP ((0x2d0d)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_dnr_db_hgapthd , + * horizontal gap thd (<=) for very sure blockiness . unsigned , default = 8 + */ +/* Bit 15: 8, reg_dnr_db_hgapdifthd , + * dif thd between hgap and lft/rgt hdifs. unsigned , default = 1 + */ +/* Bit 7: 1, reserved */ +/* Bit 0, reg_dnr_db_hgapmod , + * horizontal gap calc. mode, 0: just use current col x, + * 1: find max between (x-1, x, x+1) . unsigned , default = 0 + */ +#define DNR_DB_HBS ((0x2d0e)) +/* Bit 31: 6, reserved */ +/* Bit 5: 4, reg_dnr_db_hbsup , + * horizontal bs up value . unsigned , default = 1 + */ +/* Bit 3: 2, reg_dnr_db_hbsmax , + * max value of hbs for global control. unsigned , default = 3 + */ +/* Bit 1: 0, reg_dnr_db_hgbsthd , + * gbs thd (>=) for hbs calc. . unsigned , default = 1 + */ +#define DNR_DB_HACT ((0x2d0f)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_dnr_db_hactthd0 , + * thd0 of hact, for block classification. unsigned , default = 10 + */ +/* Bit 7: 0, reg_dnr_db_hactthd1 , + * thd1 of hact, for block classification. unsigned , default = 32 + */ +#define DNR_DB_YHDELTA_GAIN ((0x2d10)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_dnr_db_yhdeltagain1 , + * (p1-q1) gain for Y's delta calc. when bs=1, normalized 8 as "1" . + * unsigned , default = 2 + */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_dnr_db_yhdeltagain2 , + * (p1-q1) gain for Y's delta calc. when bs=2, normalized 8 as "1" . + * unsigned , default = 0 + */ +/* Bit 19, reserved */ +/* Bit 18:16, reg_dnr_db_yhdeltagain3 , + * (p1-q1) gain for Y's delta calc. when bs=3, normalized 8 as "1" . + * unsigned , default = 0 + */ +/* Bit 15, reserved */ +/* Bit 14: 8, reg_dnr_db_yhdeltaadjoffst , + * offset for adjust Y's hdelta (-64, 63). signed , default = 0 + */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_dnr_db_yhdeltaadjgain , + * gain for adjust Y's hdelta, normalized 32 as "1" . unsigned , default = 32 + */ +#define DNR_DB_YHDELTA2_GAIN ((0x2d11)) +/* Bit 31:30, reserved */ +/* Bit 29:24, reg_dnr_db_yhdelta2gain2 , + * gain for bs=2's adjust Y's hdelta2, normalized 64 as "1" . + * unsigned , default = 8 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_dnr_db_yhdelta2offst2 , + * offset for bs=2's adjust Y's hdelta2 (-16, 15). signed , default = 0 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_dnr_db_yhdelta2gain3 , + * gain for bs=3's adjust Y's hdelta2, normalized 64 as "1" . + * unsigned , default = 4 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_db_yhdelta2offst3 , + * offset for bs=3's adjust Y's hdelta2 (-16, 15). signed , default = 0 + */ +#define DNR_DB_CHDELTA_GAIN ((0x2d12)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_dnr_db_chdeltagain1 , + * (p1-q1) gain for UV's delta calc. when bs=1, normalized 8 as "1". + * unsigned , default = 2 + */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_dnr_db_chdeltagain2 , + * (p1-q1) gain for UV's delta calc. when bs=2, + * normalized 8 as "1". unsigned , default = 0 + */ +/* Bit 19, reserved */ +/* Bit 18:16, reg_dnr_db_chdeltagain3 , + * (p1-q1) gain for UV's delta calc. when bs=3, normalized 8 as "1". + * unsigned , default = 0 + */ +/* Bit 15, reserved */ +/* Bit 14: 8, reg_dnr_db_chdeltaadjoffst , + * offset for adjust UV's hdelta (-64, 63). signed , default = 0 + */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_dnr_db_chdeltaadjgain , + * gain for adjust UV's hdelta, normalized 32 as "1". unsigned , default = 32 + */ +#define DNR_DB_CHDELTA2_GAIN ((0x2d13)) +/* Bit 31:30, reserved */ +/* Bit 29:24, reg_dnr_db_chdelta2gain2 , + * gain for bs=2's adjust UV's hdelta2, normalized 64 as "1" . + * unsigned , default = 8 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_dnr_db_chdelta2offst2 , + * offset for bs=2's adjust UV's hdelta2 (-16, 15). signed , default = 0 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_dnr_db_chdelta2gain3 , + * gain for bs=2's adjust UV's hdelta2, normalized 64 as "1" . + * unsigned , default = 4 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_db_chdelta2offst3 , + * offset for bs=2's adjust UV's hdelta2 (-16, 15). signed , default = 0 + */ +#define DNR_DB_YC_VEDGE_THD ((0x2d14)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_dnr_db_yvedgethd , + * special Y's edge thd for vdb. unsigned , default = 12 + */ +/* Bit 7: 0, reg_dnr_db_cvedgethd , + * special UV's edge thd for vdb. unsigned , default = 12 + */ +#define DNR_DB_VBS_MISC ((0x2d15)) +/* Bit 31:24, reg_dnr_db_vgapthd , + * vertical gap thd (<=) for very sure blockiness . unsigned , default = 8 + */ +/* Bit 23:16, reg_dnr_db_vactthd , + * thd of vact, for block classification . unsigned , default = 10 + */ +/* Bit 15: 8, reg_dnr_db_vgapdifthd , + * dif thd between vgap and vact. unsigned , default = 4 + */ +/* Bit 7: 4, reserved */ +/* Bit 3: 2, reg_dnr_db_vbsmax , + * max value of vbs for global control. unsigned , default = 2 + */ +/* Bit 1: 0, reg_dnr_db_vgbsthd , + * gbs thd (>=) for vbs calc. . unsigned , default = 1 + */ +#define DNR_DB_YVDELTA_GAIN ((0x2d16)) +/* Bit 31:30, reserved */ +/* Bit 29:24, reg_dnr_db_yvdeltaadjgain , + * gain for adjust Y's vdelta, normalized 32 as "1". unsigned , default = 32 + */ +/* Bit 23, reserved */ +/* Bit 22:16, reg_dnr_db_yvdeltaadjoffst , + * offset for adjust Y's vdelta (-64, 63). signed , default = 0 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_dnr_db_yvdelta2gain , + * gain for adjust Y's vdelta2, normalized 64 as "1". unsigned , default = 8 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_db_yvdelta2offst , + * offset for adjust Y's vdelta2 (-16, 15). signed , default = 0 + */ +#define DNR_DB_CVDELTA_GAIN ((0x2d17)) +/* Bit 31:30, reserved */ +/* Bit 29:24, reg_dnr_db_cvdeltaadjgain , + * gain for adjust UV's vdelta, normalized 32 as "1". unsigned , default = 32 + */ +/* Bit 23, reserved */ +/* Bit 22:16, reg_dnr_db_cvdeltaadjoffst , + * offset for adjust UV's vdelta (-64, 63). signed , default = 0 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_dnr_db_cvdelta2gain , + * gain for adjust UV's vdelta2, normalized 64 as "1". unsigned , default = 8 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_db_cvdelta2offst , + * offset for adjust UV's vdelta2 (-16, 15). signed , default = 0 + */ +#define DNR_RO_GBS_STAT_LR ((0x2d18)) +/* Bit 31: 0, ro_gbs_stat_lr + * . unsigned , default = 0 + */ +#define DNR_RO_GBS_STAT_LL ((0x2d19)) +/* Bit 31: 0, ro_gbs_stat_ll + * . unsigned , default = 0 + */ +#define DNR_RO_GBS_STAT_RR ((0x2d1a)) +/* Bit 31: 0, ro_gbs_stat_rr + * . unsigned , default = 0 + */ +#define DNR_RO_GBS_STAT_DIF ((0x2d1b)) +/* Bit 31: 0, ro_gbs_stat_dif + * . unsigned , default = 0 + */ +#define DNR_RO_GBS_STAT_CNT ((0x2d1c)) +/* Bit 31: 0, ro_gbs_stat_cnt + * . unsigned , default = 0 + */ +#define DNR_RO_HBOF_STAT_CNT_0 ((0x2d1d)) +/* Bit 31: 0, ro_hbof_stat_cnt0 + * . unsigned , default = 0 + */ +#define DNR_RO_HBOF_STAT_CNT_1 ((0x2d1e)) +/* Bit 31: 0, ro_hbof_stat_cnt1 + * . unsigned , default = 0 + */ +#define DNR_RO_HBOF_STAT_CNT_2 ((0x2d1f)) +/* Bit 31: 0, ro_hbof_stat_cnt2 + * . unsigned , default = 0 + */ +#define DNR_RO_HBOF_STAT_CNT_3 ((0x2d20)) +/* Bit 31: 0, ro_hbof_stat_cnt3 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_4 ((0x2d21)) +/* Bit 31: 0, ro_hbof_stat_cnt4 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_5 ((0x2d22)) +/* Bit 31: 0, ro_hbof_stat_cnt5 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_6 ((0x2d23)) +/* Bit 31: 0, ro_hbof_stat_cnt6 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_7 ((0x2d24)) +/* Bit 31: 0, ro_hbof_stat_cnt7 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_8 ((0x2d25)) +/* Bit 31: 0, ro_hbof_stat_cnt8 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_9 ((0x2d26)) +/* Bit 31: 0, ro_hbof_stat_cnt9 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_10 ((0x2d27)) +/* Bit 31: 0, ro_hbof_stat_cnt10 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_11 ((0x2d28)) +/* Bit 31: 0, ro_hbof_stat_cnt11 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_12 ((0x2d29)) +/* Bit 31: 0, ro_hbof_stat_cnt12 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_13 ((0x2d2a)) +/* Bit 31: 0, ro_hbof_stat_cnt13 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_14 ((0x2d2b)) +/* Bit 31: 0, ro_hbof_stat_cnt14 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_15 ((0x2d2c)) +/* Bit 31: 0, ro_hbof_stat_cnt15 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_16 ((0x2d2d)) +/* Bit 31: 0, ro_hbof_stat_cnt16 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_17 ((0x2d2e)) +/* Bit 31: 0, ro_hbof_stat_cnt17 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_18 ((0x2d2f)) +/* Bit 31: 0, ro_hbof_stat_cnt18 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_19 ((0x2d30)) +/* Bit 31: 0, ro_hbof_stat_cnt19 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_20 ((0x2d31)) +/* Bit 31: 0, ro_hbof_stat_cnt20 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_21 ((0x2d32)) +/* Bit 31: 0, ro_hbof_stat_cnt21 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_22 ((0x2d33)) +/* Bit 31: 0, ro_hbof_stat_cnt22 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_23 ((0x2d34)) +/* Bit 31: 0, ro_hbof_stat_cnt23 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_24 ((0x2d35)) +/* Bit 31: 0, ro_hbof_stat_cnt24 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_25 ((0x2d36)) +/* Bit 31: 0, ro_hbof_stat_cnt25 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_26 ((0x2d37)) +/* Bit 31: 0, ro_hbof_stat_cnt26 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_27 ((0x2d38)) +/* Bit 31: 0, ro_hbof_stat_cnt27 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_28 ((0x2d39)) +/* Bit 31: 0, ro_hbof_stat_cnt28 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_29 ((0x2d3a)) +/* Bit 31: 0, ro_hbof_stat_cnt29 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_30 ((0x2d3b)) +/* Bit 31: 0, ro_hbof_stat_cnt30 . unsigned , default = 0 */ +#define DNR_RO_HBOF_STAT_CNT_31 ((0x2d3c)) +/* Bit 31: 0, ro_hbof_stat_cnt31 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_0 ((0x2d3d)) +/* Bit 31: 0, ro_vbof_stat_cnt0 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_1 ((0x2d3e)) +/* Bit 31: 0, ro_vbof_stat_cnt1 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_2 ((0x2d3f)) +/* Bit 31: 0, ro_vbof_stat_cnt2 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_3 ((0x2d40)) +/* Bit 31: 0, ro_vbof_stat_cnt3 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_4 ((0x2d41)) +/* Bit 31: 0, ro_vbof_stat_cnt4 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_5 ((0x2d42)) +/* Bit 31: 0, ro_vbof_stat_cnt5 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_6 ((0x2d43)) +/* Bit 31: 0, ro_vbof_stat_cnt6 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_7 ((0x2d44)) +/* Bit 31: 0, ro_vbof_stat_cnt7 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_8 ((0x2d45)) +/* Bit 31: 0, ro_vbof_stat_cnt8 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_9 ((0x2d46)) +/* Bit 31: 0, ro_vbof_stat_cnt9 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_10 ((0x2d47)) +/* Bit 31: 0, ro_vbof_stat_cnt10 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_11 ((0x2d48)) +/* Bit 31: 0, ro_vbof_stat_cnt11 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_12 ((0x2d49)) +/* Bit 31: 0, ro_vbof_stat_cnt12 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_13 ((0x2d4a)) +/* Bit 31: 0, ro_vbof_stat_cnt13 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_14 ((0x2d4b)) +/* Bit 31: 0, ro_vbof_stat_cnt14 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_15 ((0x2d4c)) +/* Bit 31: 0, ro_vbof_stat_cnt15 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_16 ((0x2d4d)) +/* Bit 31: 0, ro_vbof_stat_cnt16 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_17 ((0x2d4e)) +/* Bit 31: 0, ro_vbof_stat_cnt17 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_18 ((0x2d4f)) +/* Bit 31: 0, ro_vbof_stat_cnt18 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_19 ((0x2d50)) +/* Bit 31: 0, ro_vbof_stat_cnt19 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_20 ((0x2d51)) +/* Bit 31: 0, ro_vbof_stat_cnt20 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_21 ((0x2d52)) +/* Bit 31: 0, ro_vbof_stat_cnt21 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_22 ((0x2d53)) +/* Bit 31: 0, ro_vbof_stat_cnt22 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_23 ((0x2d54)) +/* Bit 31: 0, ro_vbof_stat_cnt23 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_24 ((0x2d55)) +/* Bit 31: 0, ro_vbof_stat_cnt24 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_25 ((0x2d56)) +/* Bit 31: 0, ro_vbof_stat_cnt25 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_26 ((0x2d57)) +/* Bit 31: 0, ro_vbof_stat_cnt26 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_27 ((0x2d58)) +/* Bit 31: 0, ro_vbof_stat_cnt27 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_28 ((0x2d59)) +/* Bit 31: 0, ro_vbof_stat_cnt28 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_29 ((0x2d5a)) +/* Bit 31: 0, ro_vbof_stat_cnt29 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_30 ((0x2d5b)) +/* Bit 31: 0, ro_vbof_stat_cnt30 . unsigned , default = 0 */ +#define DNR_RO_VBOF_STAT_CNT_31 ((0x2d5c)) +/* Bit 31: 0, ro_vbof_stat_cnt31 . unsigned , default = 0 */ +#define DNR_DM_CTRL ((0x2d60)) +/* Bit 31:13, reserved */ +/* Bit 12, reg_dnr_dm_fedgeflg_en , + * enable edge flag calc. of each frame. unsigned , default = 1 + */ +/* Bit 11, reg_dnr_dm_fedgeflg_cl , + * clear frame edge flag if needed. unsigned , default = 1 + */ +/* Bit 10, reg_dnr_dm_fedgeflg_df , + * user defined edge when reg_dnr_dm_fedgeflg_en=0, default = 1 + */ +/* Bit 9, reg_dnr_dm_en , + * enable demosquito function . unsigned , default = 1 + */ +/* Bit 8, reg_dnr_dm_chrmen , + * enable chrome processing for demosquito. unsigned , default = 1 + */ +/* Bit 7: 6, reg_dnr_dm_level , + * demosquito level . unsigned , default = 3 + */ +/* Bit 5: 4, reg_dnr_dm_leveldw0 , + * level down when gbs is small. unsigned , default = 1 + */ +/* Bit 3: 2, reg_dnr_dm_leveldw1 , + * level down for no edge/flat blocks. unsigned , default = 1 + */ +/* Bit 1: 0, reg_dnr_dm_gbsthd , + * small/large threshold for gbs (<=). unsigned , default = 0 + */ +#define DNR_DM_NR_BLND ((0x2d61)) +/* Bit 31:25, reserved */ +/* Bit 24, reg_dnr_dm_defalpen , + * enable user define alpha for dm & nr blend. unsigned , default = 0 + */ +/* Bit 23:16, reg_dnr_dm_defalp , + * user define alpha for dm & nr blend if enable. unsigned , default = 0 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_dnr_dm_alpgain , + * gain for nr/dm alpha, normalized 32 as "1". unsigned , default = 32 + */ +/* Bit 7: 0, reg_dnr_dm_alpoffst , + * (-128, 127), offset for nr/dm alpha. signed , default = 0 + */ +#define DNR_DM_RNG_THD ((0x2d62)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_dnr_dm_rngminthd . unsigned , default = 2 */ +/* Bit 15: 8, reg_dnr_dm_rngmaxthd . unsigned , default = 64 */ +/* Bit 7: 0, reg_dnr_dm_rngdifthd . unsigned , default = 4 */ +#define DNR_DM_RNG_GAIN_OFST ((0x2d63)) +/* Bit 31:14, reserved */ +/* Bit 13: 8, reg_dnr_dm_rnggain , + * normalized 16 as "1" . unsigned , default = 16 + */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_dnr_dm_rngofst . unsigned , default = 0 */ +#define DNR_DM_DIR_MISC ((0x2d64)) +/* Bit 31:30, reserved */ +/* Bit 29, reg_dnr_dm_diralpen . unsigned , default = 1 */ +/* Bit 28:24, reg_dnr_dm_diralpgain . unsigned , default = 0 */ +/* Bit 23:22, reserved */ +/* Bit 21:16, reg_dnr_dm_diralpofst . unsigned , default = 0 */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_diralpmin . unsigned , default = 0 */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_diralpmax . unsigned , default = 31 */ +#define DNR_DM_COR_DIF ((0x2d65)) +/* Bit 31: 4, reserved */ +/* Bit 3: 1, reg_dnr_dm_cordifshft . unsigned , default = 3 */ +/* Bit 0, reg_dnr_dm_cordifmod , + * 0:use max dir dif as cordif, 1: use max3x3 - min3x3 as cordif. + * unsigned , default = 1 + */ +#define DNR_DM_FLT_THD ((0x2d66)) +/* Bit 31:24, reg_dnr_dm_fltthd00 , + * block flat threshold0 for block average difference when gbs is small, + * for flat block detection. unsigned , default = 4 + */ +/* Bit 23:16, reg_dnr_dm_fltthd01 , + * block flat threshold1 for block average difference when gbs is small, + * for flat block detection. unsigned , default = 6 + */ +/* Bit 15: 8, reg_dnr_dm_fltthd10 , + * block flat threshold0 for block average difference when gbs is large, + * for flat block detection. unsigned , default = 9 + */ +/* Bit 7: 0, reg_dnr_dm_fltthd11 , + * block flat threshold1 for block average difference when gbs is large, + * for flat block detection. unsigned , default = 12 + */ +#define DNR_DM_VAR_THD ((0x2d67)) +/* Bit 31:24, reg_dnr_dm_varthd00 , + * block variance threshold0 (>=) when gbs is small, for flat block + * detection. unsigned , default = 2 + */ +/* Bit 23:16, reg_dnr_dm_varthd01 , + * block variance threshold1 (<=) when gbs is small, for flat block + * detection. unsigned , default = 15 + */ +/* Bit 15: 8, reg_dnr_dm_varthd10 , + * block variance threshold0 (>=) when gbs is large, for flat block + * detection. unsigned , default = 3 + */ +/* Bit 7: 0, reg_dnr_dm_varthd11 , + * block variance threshold1 (<=) when gbs is large, for flat block + * detection. unsigned , default = 24 + */ +#define DNR_DM_EDGE_DIF_THD ((0x2d68)) +/* Bit 31:24, reg_dnr_dm_edgethd0 , + * block edge threshold (<=) when gbs is small, for flat block detection. + * unsigned , default = 32 + */ +/* Bit 23:16, reg_dnr_dm_edgethd1 , + * block edge threshold (<=) when gbs is large, for flat block detection. + * unsigned , default = 48 + */ +/* Bit 15: 8, reg_dnr_dm_difthd0 , + * block dif threshold (<=) when gbs is small, for flat block detection. + * unsigned , default = 48 + */ +/* Bit 7: 0, reg_dnr_dm_difthd1 , + * block dif threshold (<=) when gbs is large, for flat block detection. + * unsigned , default = 64 + */ +#define DNR_DM_AVG_THD ((0x2d69)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_dnr_dm_avgthd0 , + * block average threshold (>=), for flat block detection. + * unsigned ,default = 160 + */ +/* Bit 7: 0, reg_dnr_dm_avgthd1 , + * block average threshold (<=), for flat block detection. unsigned + * , default = 128 + */ +#define DNR_DM_AVG_VAR_DIF_THD ((0x2d6a)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_dnr_dm_avgdifthd , + * block average dif threshold (<) between cur and up block, for flat + * block detection. unsigned , default = 12 + */ +/* Bit 7: 0, reg_dnr_dm_vardifthd , + * block variance dif threshold (>=) between cur and up block, for flat + * block detection. unsigned , default = 1 + */ +#define DNR_DM_VAR_EDGE_DIF_THD2 ((0x2d6b)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_dnr_dm_varthd2, block variance threshold (>=), + * for edge block detection.unsigned, default = 24 + */ +/* Bit 15: 8, reg_dnr_dm_edgethd2 , + * block edge threshold (>=), for edge block detection. unsigned , default = 40 + */ +/* Bit 7: 0, reg_dnr_dm_difthd2 , + * block dif threshold (>=), for edge block detection. unsigned , default = 80 + */ +#define DNR_DM_DIF_FLT_MISC ((0x2d6c)) +/* Bit 31:28, reg_dnr_dm_ldifoob , + * pre-defined large dif when pixel out of blocks. unsigned , default = 0 + */ +/* Bit 27:24, reg_dnr_dm_bdifoob , + * pre-defined block dif when pixel out of blocks;. unsigned , default = 0 + */ +/* Bit 23:16, reg_dnr_dm_fltalp , + * pre-defined alpha for dm and nr blending, when block is flat + * with mos.. unsigned , default = 200 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_dnr_dm_fltminbdif , + * pre-defined min block dif for dm filter, + * when block is flat with mos.. unsigned , default = 12 + */ +/* Bit 7, reserved */ +/* Bit 6: 2, reg_dnr_dm_difnormgain , + * gain for pixel dif normalization for dm filter, + * normalized 16 as "1". unsigned , default = 16 + */ +/* Bit 1, reg_dnr_dm_difnormen , + * enable pixel dif normalization for dm filter. unsigned , default = 1 + */ +/* Bit 0, reg_dnr_dm_difupden , + * enable block dif update using max of left, cur, right difs. + * unsigned , default = 0 + */ +#define DNR_DM_SDIF_LUT0_2 ((0x2d6d)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_sdiflut0 , + * normally 0-16 . unsigned , default = 16 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_sdiflut1 , + * normally 0-16 . unsigned , default = 14 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_sdiflut2 , + * normally 0-16 . unsigned , default = 13 + */ +#define DNR_DM_SDIF_LUT3_5 ((0x2d6e)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_sdiflut3 , + * normally 0-16 . unsigned , default = 10 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_sdiflut4 , + * normally 0-16 . unsigned , default = 7 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_sdiflut5 , + * normally 0-16 . unsigned , default = 5 + */ +#define DNR_DM_SDIF_LUT6_8 ((0x2d6f)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_sdiflut6 , + * normally 0-16 . unsigned , default = 3 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_sdiflut7 , + * normally 0-16 . unsigned , default = 1 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_sdiflut8 , + * normally 0-16 . unsigned , default = 0 + */ +#define DNR_DM_LDIF_LUT0_2 ((0x2d70)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_ldiflut0 , + * normally 0-16 . unsigned , default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_ldiflut1 , + * normally 0-16 . unsigned , default = 4 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_ldiflut2 , + * normally 0-16 . unsigned , default = 12 + */ +#define DNR_DM_LDIF_LUT3_5 ((0x2d71)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_ldiflut3 , + * normally 0-16 . unsigned , default = 14 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_ldiflut4 , + * normally 0-16 . unsigned , default = 15 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_ldiflut5 , + * normally 0-16 . unsigned , default = 16 + */ +#define DNR_DM_LDIF_LUT6_8 ((0x2d72)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_ldiflut6 , + * normally 0-16 . unsigned , default = 16 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_ldiflut7 , + * normally 0-16 . unsigned , default = 16 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_ldiflut8 , + * normally 0-16 . unsigned , default = 16 + */ +#define DNR_DM_DIF2NORM_LUT0_2 ((0x2d73)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_dif2normlut0 , + * normally 0-16 . unsigned , default = 16 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_dif2normlut1 , + * normally 0-16 . unsigned , default = 5 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_dif2normlut2 , + * normally 0-16 . unsigned , default = 3 + */ +#define DNR_DM_DIF2NORM_LUT3_5 ((0x2d74)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_dif2normlut3 , + * normally 0-16 . unsigned , default = 2 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_dif2normlut4 , + * normally 0-16 . unsigned , default = 2 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_dif2normlut5 , + * normally 0-16 . unsigned , default = 1 + */ +#define DNR_DM_DIF2NORM_LUT6_8 ((0x2d75)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_dnr_dm_dif2normlut6 , + * normally 0-16 . unsigned , default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_dnr_dm_dif2normlut7 , + * normally 0-16 . unsigned , default = 1 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_dnr_dm_dif2normlut8 , + * normally 0-16 . unsigned , default = 1 + */ +#define DNR_DM_GMS_THD ((0x2d76)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_gms_stat_thd0 . unsigned , default = 0 */ +/* Bit 7: 0, reg_gms_stat_thd1 . unsigned , default = 128 */ +#define DNR_RO_DM_GMS_STAT_CNT ((0x2d77)) +/* Bit 31: 0, ro_dm_gms_stat_cnt . unsigned , default = 0 */ +#define DNR_RO_DM_GMS_STAT_MS ((0x2d78)) +/* Bit 31: 0, ro_dm_gms_stat_ms . unsigned , default = 0 */ +/* txl added */ +#define DECOMB_DET_VERT_CON0 (0x2d80) +#define DECOMB_DET_VERT_CON1 (0x2d81) +#define DECOMB_DET_EDGE_CON0 (0x2d82) +#define DECOMB_DET_EDGE_CON1 (0x2d83) +#define DECOMB_PARA (0x2d84) +#define DECOMB_BLND_CON0 (0x2d85) +#define DECOMB_BLND_CON1 (0x2d86) +#define DECOMB_YC_THRD (0x2d87) +#define DECOMB_MTN_GAIN_OFST (0x2d88) +#define DECOMB_CMB_SEL_GAIN_OFST (0x2d89) +#define DECOMB_WIND00 (0x2d8a) +#define DECOMB_WIND01 (0x2d8b) +#define DECOMB_WIND10 (0x2d8c) +#define DECOMB_WIND11 (0x2d8d) +#define DECOMB_MODE (0x2d8e) +#define DECOMB_FRM_SIZE (0x2d8f) +#define DECOMB_HV_BLANK (0x2d90) +#define NR2_POLAR3_MODE (0x2d98) +#define NR2_POLAR3_THRD (0x2d99) +#define NR2_POLAR3_PARA0 (0x2d9a) +#define NR2_POLAR3_PARA1 (0x2d9b) +#define NR2_POLAR3_CTRL (0x2d9c) +#define NR2_RO_POLAR3_NUMOFPIX (0x2d9d) +#define NR2_RO_POLAR3_SMOOTHMV (0x2d9e) +#define NR2_RO_POLAR3_M1 (0x2d9f) +#define NR2_RO_POLAR3_P1 (0x2da0) +#define NR2_RO_POLAR3_M2 (0x2da1) +#define NR2_RO_POLAR3_P2 (0x2da2) +#define NR2_RO_POLAR3_32 (0x2da3) +/* txl end */ + +#define VPU_VD1_MMC_CTRL (0x2703) +#define VPU_VD2_MMC_CTRL (0x2704) +#define VPU_DI_IF1_MMC_CTRL (0x2705) +#define VPU_DI_MEM_MMC_CTRL (0x2706) +#define VPU_DI_INP_MMC_CTRL (0x2707) +#define VPU_DI_MTNRD_MMC_CTRL (0x2708) +#define VPU_DI_CHAN2_MMC_CTRL (0x2709) +#define VPU_DI_MTNWR_MMC_CTRL (0x270a) +#define VPU_DI_NRWR_MMC_CTRL (0x270b) +#define VPU_DI_DIWR_MMC_CTRL (0x270c) + +#define MCDI_PD_22_CHK_WND0_X (0x2f59) +#define MCDI_PD_22_CHK_WND0_Y (0x2f5a) +#define MCDI_PD_22_CHK_WND1_X (0x2f5b) +#define MCDI_PD_22_CHK_WND1_Y (0x2f5c) +#define MCDI_PD_22_CHK_FLG_CNT (0x2f5e) +/* mc di */ +/* //=================================================================//// */ +/* // memc di core 0 */ +/* //=================================================================//// */ +#define MCDI_HV_SIZEIN ((0x2f00)) +/* Bit 31:29, reserved */ +/* Bit 28:16, reg_mcdi_hsize + * image horizontal size (number of cols) default=1024 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 0, reg_mcdi_vsize + * image vertical size (number of rows) default=1024 + */ +#define MCDI_HV_BLKSIZEIN ((0x2f01)) +/* Bit 31, reg_mcdi_vrev default = 0 */ +/* Bit 30, reg_mcdi_hrev default = 0 */ +/* Bit 29:28, reserved */ +/* Bit 27:16, reg_mcdi_blkhsize + * image horizontal blk size (number of cols) default=1024 + */ +/* Bit 15:13, reserved */ +/* Bit 11: 0, reg_mcdi_blkvsize + * image vertical blk size (number of rows) default=1024 + */ +#define MCDI_BLKTOTAL ((0x2f02)) +/* Bit 31:24, reserved */ +/* Bit 23: 0, reg_mcdi_blktotal */ +#define MCDI_MOTINEN ((0x2f03)) +/* Bit 31: 2, reserved */ +/* Bit 1, reg_mcdi_motionrefen. + * enable motion refinement of MA, default = 1 + */ +/* Bit 0, reg_mcdi_motionparadoxen. + * enable motion paradox detection, default = 1 + */ +#define MCDI_CTRL_MODE ((0x2f04)) +/* Bit 31:28, reserved */ +/* Bit 27:26, reg_mcdi_lmvlocken + * 0:disable, 1: use max Lmv, 2: use no-zero Lmv, + * lmv lock enable mode, default = 2 + */ +/* Bit 25, reg_mcdi_reldetrptchken */ +/* 0: unable; 1: enable, enable repeat pattern + * check (not repeat mv detection) in rel det part, default = 1 + */ +/* Bit 24, reg_mcdi_reldetgmvpd22chken */ +/* 0: unable; 1: enable, enable pull-down 22 mode + * check in gmv lock mode for rel det, default = 1 + */ +/* Bit 23, reg_mcdi_pd22chken */ +/* 0: unable; 1: enable, enable pull-down 22 + * mode check (lock) function, default = 1 + */ +/* Bit 22, reg_mcdi_reldetlpfen */ +/* 0: unable; 1: enable, enable det value lpf, default = 1 */ +/* Bit 21, reg_mcdi_reldetlmvpd22chken */ +/* 0: unable; 1: enable, enable pull-down 22 + * mode check in lmv lock mode for rel det, default = 1 + */ +/* Bit 20, reg_mcdi_reldetlmvdifchken */ +/* 0: unable; 1: enable, enable lmv dif check + * in lmv lock mode for rel det, default = 1 + */ +/* Bit 19, reg_mcdi_reldetgmvdifchken */ +/* 0: unable; 1: enable, enable lmv dif check in + * lmv lock mode for rel det, default = 1 + */ +/* Bit 18, reg_mcdi_reldetpd22chken */ +/* 0: unable; 1: enable, enable pull-down 22 + * mode check for rel det refinement, default = 1 + */ +/* Bit 17, reg_mcdi_reldetfrqchken */ +/* 0: unable; 1: enable, enable mv frequency check in rel det, default = 1 */ +/* Bit 16, reg_mcdi_qmeen */ +/* 0: unable; 1: enable, enable quarter motion estimation, defautl = 1 */ +/* Bit 15, reg_mcdi_refrptmven */ +/* 0: unable; 1: enable, use repeat mv in refinement, default = 1 */ +/* Bit 14, reg_mcdi_refgmven */ +/* 0: unable; 1: enable, use gmv in refinement, default = 1 */ +/* Bit 13, reg_mcdi_reflmven */ +/* 0: unable; 1: enable, use lmvs in refinement, default = 1 */ +/* Bit 12, reg_mcdi_refnmven */ +/* 0: unable; 1: enable, use neighoring mvs in refinement, default = 1 */ +/* Bit 11, reserved */ +/* Bit 10, reg_mcdi_referrfrqchken */ +/* 0: unable; 1: enable, enable mv frquency + * check while finding min err in ref, default = 1 + */ +/* Bit 9, reg_mcdi_refen */ +/* 0: unable; 1: enable, enable mv refinement, default = 1 + */ +/* Bit 8, reg_mcdi_horlineen */ +/* 0: unable; 1: enable,enable horizontal lines + * detection by sad map, default = 1 + */ +/* Bit 7, reg_mcdi_highvertfrqdeten */ +/* 0: unable; 1: enable, enable high vertical + * frequency pattern detection, default = 1 + */ +/* Bit 6, reg_mcdi_gmvlocken */ +/* 0: unable; 1: enable, enable gmv lock mode, default = 1 */ +/* Bit 5, reg_mcdi_rptmven */ +/* 0: unable; 1: enable, enable repeat pattern detection, default = 1 */ +/* Bit 4, reg_mcdi_gmven */ +/* 0: unable; 1: enable, enable global motion estimation, default = 1 */ +/* Bit 3, reg_mcdi_lmven */ +/* 0: unable; 1: enable, enable line mv estimation for hme, default = 1 */ +/* Bit 2, reg_mcdi_chkedgeen */ +/* 0: unable; 1: enable, enable check edge function, default = 1 */ +/* Bit 1, reg_mcdi_txtdeten */ +/* 0: unable; 1: enable, enable texture detection, default = 1 */ +/* Bit 0, reg_mcdi_memcen */ +/* 0: unable; 1: enable, enable of memc di, default = 1 */ +#define MCDI_UNI_MVDST ((0x2f05)) +/* Bit 31:20, reserved */ +/* Bit 19:17, reg_mcdi_unimvdstabsseg0 + * segment0 for uni-mv abs, default = 1 + */ +/* Bit 16:12, reg_mcdi_unimvdstabsseg1 + * segment1 for uni-mv abs, default = 15 + */ +/* Bit 11: 8, reg_mcdi_unimvdstabsdifgain0 + * 2/2, gain0 of uni-mv abs dif for segment0, normalized 2 to '1', default = 2 + */ +/* Bit 7: 5, reg_mcdi_unimvdstabsdifgain1 + * 2/2, gain1 of uni-mv abs dif for segment1, normalized 2 to '1', default = 2 + */ +/* Bit 4: 2, reg_mcdi_unimvdstabsdifgain2 + * 2/2, gain2 of uni-mv abs dif beyond segment1,normalized 2 to '1', default = 2 + */ +/* Bit 1: 0, reg_mcdi_unimvdstsgnshft + * shift for neighboring distance of uni-mv, default = 0 + */ +#define MCDI_BI_MVDST ((0x2f06)) +/* Bit 31:20, reserved */ +/* Bit 19:17, reg_mcdi_bimvdstabsseg0 + * segment0 for bi-mv abs, default = 1 + */ +/* Bit 16:12, reg_mcdi_bimvdstabsseg1 + * segment1 for bi-mv abs, default = 9 + */ +/* Bit 11: 8, reg_mcdi_bimvdstabsdifgain0 + * 6/2, gain0 of bi-mv abs dif for segment0, normalized 2 to '1', default = 6 + */ +/* Bit 7: 5, reg_mcdi_bimvdstabsdifgain1 + * 3/2, gain1 of bi-mvabs dif for segment1, normalized 2 to '1', default = 3 + */ +/* Bit 4: 2, reg_mcdi_bimvdstabsdifgain2 + * 2/2, gain2 of bi-mvabs dif beyond segment1, normalized 2 to '1', default = 2 + */ +/* Bit 1: 0, reg_mcdi_bimvdstsgnshft + * shift for neighboring distance of bi-mv, default = 0 + */ +#define MCDI_SAD_GAIN ((0x2f07)) +/* Bit 31:19, reserved */ +/* Bit 18:17, reg_mcdi_unisadcorepxlgain + * uni-sad core pixels gain, default = 3 + */ +/* Bit 16, reg_mcdi_unisadcorepxlnormen + * enable uni-sad core pixels normalization, default = 0 + */ +/* Bit 15:11, reserved */ +/* Bit 10: 9, reg_mcdi_bisadcorepxlgain + * bi-sad core pixels gain, default = 3 + */ +/* Bit 8, reg_mcdi_bisadcorepxlnormen + * enable bi-sad core pixels normalization, default = 1 + */ +/* Bit 7: 3, reserved */ +/* Bit 2: 1, reg_mcdi_biqsadcorepxlgain + * bi-qsad core pixels gain, default = 3 + */ +/* Bit 0, reg_mcdi_biqsadcorepxlnormen + * enable bi-qsad core pixels normalization, default = 1 + */ +#define MCDI_TXT_THD ((0x2f08)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_txtminmaxdifthd, + * min max dif threshold (>=) for texture detection, default = 24 + */ +/* Bit 15: 8, reg_mcdi_txtmeandifthd, + * mean dif threshold (<) for texture detection, default = 9 + */ +/* Bit 7: 3, reserved */ +/* Bit 2: 0, reg_mcdi_txtdetthd, + * texture detecting threshold, 0~4, default = 2 + */ +#define MCDI_FLT_MODESEL ((0x2f09)) +/* Bit 31 reserved */ +/* Bit 30:28, reg_mcdi_flthorlineselmode + * mode for horizontal line detecting flat calculation,default = 1,same as below + */ +/* Bit 27 reserved */ +/* Bit 26:24, reg_mcdi_fltgmvselmode + * mode for gmv flat calculation, default = 4, same as below + */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_mcdi_fltsadselmode + * mode for sad flat calculation, default = 2, same as below + */ +/* Bit 19, reserved */ +/* Bit 18:16, reg_mcdi_fltbadwselmode + * mode for badw flat calculation, default = 3, same as below + */ +/* Bit 15, reserved */ +/* Bit 14:12, reg_mcdi_fltrptmvselmode + * mode for repeat mv flat calculation, default = 4, same as below + */ +/* Bit 11, reserved */ +/* Bit 10: 8, reg_mcdi_fltbadrelselmode + * mode for bad rel flat calculation, default = 4, same as below + */ +/* Bit 7, reserved */ +/* Bit 6: 4, reg_mcdi_fltcolcfdselmode + * mode for col cfd flat calculation, default = 2, same as below + */ +/* Bit 3, reserved */ +/* Bit 2: 0, reg_mcdi_fltpd22chkselmode + * mode for pd22 check flat calculation, default = 2, # + * 0:cur dif h, 1: cur dif v, 2: pre dif h, 3: pre dif v, + * 4: cur flt, 5: pre flt, 6: cur+pre, 7: max all(cur,pre) + */ +#define MCDI_CHK_EDGE_THD ((0x2f0a)) +/* Bit 23:28, reserved. */ +/* Bit 27:24, reg_mcdi_chkedgedifsadthd. + * thd (<=) for sad dif check, 0~8, default = 1 + */ +/* Bit 23:16, reserved. */ +/* Bit 15:12, reg_mcdi_chkedgemaxedgethd. + * max drt of edge, default = 15 + */ +/* Bit 11: 8, reg_mcdi_chkedgeminedgethd. + * min drt of edge, default = 2 + */ +/* Bit 7, reserved. */ +/* Bit 6: 0, reg_mcdi_chkedgevdifthd. + * thd for vertical dif in check edge, default = 14 + */ +#define MCDI_CHK_EDGE_GAIN_OFFST ((0x2f0b)) +/* Bit 31:24, reserved. */ +/* Bit 23:20, reg_mcdi_chkedgedifthd1. + * thd1 for edge dif check (<=), default = 4 + */ +/* Bit 19:16, reg_mcdi_chkedgedifthd0. + * thd0 for edge dif check (>=), default = 15 + */ +/* Bit :15, reserved. */ +/* Bit 14:10, reg_mcdi_chkedgechklen. + * total check length for edge check, 1~24 (>0), default = 24 + */ +/* Bit 9: 8, reg_mcdi_chkedgeedgesel. + * final edge select mode, 0: original start edge, 1: lpf start edge, + * 2: orignal start+end edge, 3: lpf start+end edge, default = 1 + */ +/* Bit 7: 3, reg_mcdi_chkedgesaddstgain. + * distance gain for sad calc while getting edges, default = 4 + */ +/* Bit 2, reg_mcdi_chkedgechkmode. + * edge used in check mode, 0: original edge, 1: lpf edge, defautl = 1 + */ +/* Bit 1, reg_mcdi_chkedgestartedge. + * edge mode for start edge, 0: original edge, 1: lpf edge, defautl = 0 + */ +/* Bit 0, reg_mcdi_chkedgeedgelpf. + * edge lpf mode, 0:[0,2,4,2,0], 1:[1,2,2,2,1], default = 0 + */ +#define MCDI_LMV_RT ((0x2f0c)) +/* BIt 31:15, reserved */ +/* Bit 14:12, reg_mcdi_lmvvalidmode + * valid mode for lmv calc., 100b:use char det, 010b: use flt,001b: use hori flg + */ +/* Bit 11:10, reg_mcdi_lmvgainmvmode + * four modes of mv selection for lmv weight calucluation, default = 1 + */ +/* 0: cur(x-3), lst(x-1,x,x+1); 1: cur(x-4,x-3), lst(x,x+1); + * 2: cur(x-5,x-4,x-3), lst(x-1,x,x+1,x+2,x+3); + * 3: cur(x-6,x-5,x-4,x-3), lst(x-1,x,x+1,x+2); + */ +/* Bit 9, reg_mcdi_lmvinitmode + * initial lmvs at first row of input field, 0: initial value = 0; + * 1: initial = 32 (invalid), default = 0 + */ +/* Bit 8, reserved */ +/* Bit 7: 4, reg_mcdi_lmvrt0 ratio of max mv, default = 5 */ +/* Bit 3: 0, reg_mcdi_lmvrt1 ratio of second max mv, default = 5 */ +#define MCDI_LMV_GAINTHD ((0x2f0d)) +/* Bit 31:24, reg_mcdi_lmvvxmaxgain max gain of lmv weight, default = 96 */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_mcdi_lmvdifthd0 + * dif threshold 0 (<) for small lmv, default = 1 + */ +/* Bit 19:17, reg_mcdi_lmvdifthd1 + * dif threshold 1 (<) for median lmv, default = 2 + */ +/* Bit 16:14, reg_mcdi_lmvdifthd2 + * dif threshold 2 (<) for large lmv, default = 3 + */ +/* Bit 13: 8, reg_mcdi_lmvnumlmt + * least/limit number of (total number - max0), default = 20 + */ +/* Bit 7: 0, reg_mcdi_lmvfltthd + * flt cnt thd (<) for lmv, default = 9 + */ +#define MCDI_RPTMV_THD0 ((0x2f0e)) +/* Bit 31:25, reg_mcdi_rptmvslpthd2 + * slope thd (>=) between i and i+3/i-3 (i+4/i-4), default = 64 + */ +/* Bit 24:20, reg_mcdi_rptmvslpthd1 + * slope thd (>=) between i and i+2/i-2, default = 4 + */ +/* Bit 19:10, reg_mcdi_rptmvampthd2 + * amplitude thd (>=) between max and min, when count cycles, default = 300 + */ +/* Bit 9: 0, reg_mcdi_rptmvampthd1 + * amplitude thd (>=) between average of max and min, default = 400 + */ +#define MCDI_RPTMV_THD1 ((0x2f0f)) +/* Bit 31:28, reserved */ +/* Bit 27:25, reg_mcdi_rptmvcyccntthd + * thd (>=) of total cycles count, default = 2 + */ +/* Bit 24:21, reg_mcdi_rptmvcycdifthd + * dif thd (<) of cycles length, default = 3 + */ +/* Bit 20:18, reg_mcdi_rptmvcycvldthd + * thd (>) of valid cycles number, default = 1 + */ +/* Bit 17:15, reg_mcdi_rptmvhalfcycminthd + * min length thd (>=) of half cycle, default = 2 + */ +/* Bit 14:11, reg_mcdi_rptmvhalfcycdifthd + * neighboring half cycle length dif thd (<), default = 5 + */ +/* Bit 10: 8, reg_mcdi_rptmvminmaxcntthd + * least number of valid max and min, default = 2 + */ +/* Bit 7: 5, reg_mcdi_rptmvcycminthd + * min length thd (>=) of cycles, default = 2 + */ +/* Bit 4: 0, reg_mcdi_rptmvcycmaxthd + * max length thd (<) of cycles, default = 17 + */ +#define MCDI_RPTMV_THD2 ((0x2f10)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_rptmvhdifthd0 + * higher hdif thd (>=) (vertical edge) for rpt detection, default = 8 + */ +/* Bit 15: 8, reg_mcdi_rptmvhdifthd1 + * hdif thd (>=) (slope edge) for rpt detection, default = 4 + */ +/* Bit 7: 0, reg_mcdi_rptmvvdifthd + * vdif thd (>=) (slope edge) for rpt detection, default = 1 + */ +#define MCDI_RPTMV_SAD ((0x2f11)) +/* Bit 31:26, reserved */ +/* Bit 25:16, reg_mcdi_rptmvsaddifthdgain + * 7x3x(16/16), gain for sad dif thd in rpt mv detection, + * 0~672, normalized 16 as '1', default = 336 + */ +/* Bit 15:10, reserved */ +/* Bit 9: 0, reg_mcdi_rptmvsaddifthdoffst + * offset for sad dif thd in rpt mv detection, -512~511, default = 16 + */ +#define MCDI_RPTMV_FLG ((0x2f12)) +/* Bit 31:18, reserved */ +/* Bit 17:16, reg_mcdi_rptmvmode + * select mode of mvs for repeat motion estimation, 0: hmv, + * 1: qmv/2, 2 or 3: qmv/4, default = 2 + */ +/* Bit 15: 8, reg_mcdi_rptmvflgcntthd + * thd (>=) of min count number for rptmv of whole field, + * for rptmv estimation, default = 64 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_rptmvflgcntrt + * 4/32, ratio for repeat mv flag count, normalized 32 as '1', set 31 to 32, + */ +#define MCDI_RPTMV_GAIN ((0x2f13)) +/* Bit 31:24, reg_mcdi_rptmvlftgain + * up repeat mv gain for hme, default = 96 + */ +/* Bit 23:16, reg_mcdi_rptmvuplftgain + * up left repeat mv gain for hme, default = 32 + */ +/* Bit 15: 8, reg_mcdi_rptmvupgain + * up repeat mv gain for hme, default = 64 + */ +/* Bit 7: 0, reg_mcdi_rptmvuprightgain + * up right repeat mv gain for hme, default = 32 + */ +#define MCDI_GMV_RT ((0x2f14)) +/* Bit 31, reserved */ +/* Bit 30:24, reg_mcdi_gmvmtnrt0 + * ratio 0 for motion senario, set 127 to 128, normalized 128 as '1',default =32 + */ +/* Bit 23, reserved */ +/* Bit 22:16, reg_mcdi_gmvmtnrt1 + * ratio 1 for motion senario, set 127 to 128 normalized 128 as '1',default = 56 + */ +/* Bit 15, reserved */ +/* Bit 14: 8, reg_mcdi_gmvstlrt0 + * ratio 0 for still senario, set 127 to 128,normalized 128 as '1', default = 56 + */ +/* Bit 7, reserved */ +/* Bit 6: 0, reg_mcdi_gmvstlrt1 + * ratio 1 for still senario, set 127 to 128, normalized 128 as '1',default = 80 + */ +#define MCDI_GMV_GAIN ((0x2f15)) +/* Bit 31:25, reg_mcdi_gmvzeromvlockrt0 + * ratio 0 for locking zero mv, set 127 to 128, + * normalized 128 as '1', default = 100 + */ +/* Bit 24:18, reg_mcdi_gmvzeromvlockrt1 + * ratio 1 for locking zero mv, set 127 to 128, + * normalized 128 as '1', default = 112 + */ +/* Bit 17:16, reg_mcdi_gmvvalidmode + * valid mode for gmv calc., 10b: use flt, 01b: use hori flg, default = 3 + */ +/* Bit 15: 8, reg_mcdi_gmvvxgain + * gmv's vx gain when gmv locked for hme, default = 0 + */ +/* Bit 7: 0, reg_mcdi_gmvfltthd + * flat thd (<) for gmv calc. default = 3 + */ +#define MCDI_HOR_SADOFST ((0x2f16)) +/* Bit 31:25, reserved */ +/* Bit 24:16, reg_mcdi_horsaddifthdgain + * 21*1/8, gain/divisor for sad dif threshold in hor line detection, + * normalized 8 as '1', default = 21 + */ +/* Bit 15: 8, reg_mcdi_horsaddifthdoffst + * offset for sad dif threshold in hor line detection, -128~127, default = 0 + */ +/* Bit 7: 0, reg_mcdi_horvdifthd + * threshold (>=) of vertical dif of next block for + * horizontal line detection, default = 24 + */ +#define MCDI_REF_MV_NUM ((0x2f17)) +/* Bit 31: 2, reserved */ +/* Bit 1: 0, reg_mcdi_refmcmode. motion compensated mode used in + * refinement, 0: pre, 1: next, 2: (pre+next)/2, default = 0 + */ +#define MCDI_REF_BADW_THD_GAIN ((0x2f18)) +/* Bit 31:28, reserved */ +/* Bit 27:24, reg_mcdi_refbadwcnt2gain. + * gain for badwv count num==3, default = 6 + */ +/* Bit 23:20, reg_mcdi_refbadwcnt1gain. + * gain for badwv count num==2, default = 3 + */ +/* Bit 19:16, reg_mcdi_refbadwcnt0gain. + * gain for badwv count num==1, default = 1 + */ +/* Bit 15:12, reg_mcdi_refbadwthd3. + * threshold 3 for detect badweave with largest average luma, default = 4 + */ +/* Bit 11: 8, reg_mcdi_refbadwthd2. + * threshold 2 for detect badweave with third smallest average luma, default = 3 + */ +/* Bit 7: 4, reg_mcdi_refbadwthd1. + * threshold 1 for detect badweave with second smallest average luma,default = 2 + */ +/* Bit 3: 0, reg_mcdi_refbadwthd0. + * threshold 0 for detect badweave with smallest average luma, default = 1 + */ +#define MCDI_REF_BADW_SUM_GAIN ((0x2f19)) +/* Bit 31:13, reserved */ +/* Bit 12: 8, reg_mcdi_refbadwsumgain0. + * sum gain for r channel, 0~16, default = 8 + */ +/* Bit 7: 5, reserved */ +/* Bit 4, reg_mcdi_refbadwcalcmode. + * mode for badw calculation, 0:sum, 1:max, default = 0 + */ +/* Bit 3: 0, reserved */ +#define MCDI_REF_BS_THD_GAIN ((0x2f1a)) +/* Bit 31:28, reg_mcdi_refbsudgain1. + * up & down block stregth gain1, normalized to 8 as '1', default = 2 + */ +/* Bit 27:24, reg_mcdi_refbsudgain0. + * up & down block stregth gain0, normalized to 8 as '1', default = 4 + */ +/* Bit 23:19, reserved */ +/* Bit 18:16, reg_mcdi_refbslftgain. + * left block strength gain, default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_refbsthd1. + * threshold 1 for detect block stregth in refinment, default = 16 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_refbsthd0. + * threshold 0 for detect block stregth in refinment, default = 8 + */ +#define MCDI_REF_ERR_GAIN0 ((0x2f1b)) +/* Bit 31, reserved */ +/* Bit 30:24, reg_mcdi_referrnbrdstgain. + * neighoring mv distances gain for err calc. in ref, + * normalized to 8 as '1', default = 48 + */ +/* Bit 23:20, reserved */ +/* Bit 19:16, reg_mcdi_referrbsgain. + * bs gain for err calc. in ref, normalized to 8 as '1', default = 4 + */ +/* Bit 15, reserved */ +/* Bit 14: 8, reg_mcdi_referrbadwgain. + * badw gain for err calc. in ref, normalized to 8 as '1', default = 64 + */ +/* Bit 7: 4, reserved */ +/* Bit 3: 0, reg_mcdi_referrsadgain. + * sad gain for err calc. in ref, normalized to 8 as '1', default = 4 + */ +#define MCDI_REF_ERR_GAIN1 ((0x2f1c)) +/* Bit 31:20, reserved */ +/* Bit 19:16, reg_mcdi_referrchkedgegain. + * check edge gain for err calc. in ref, normalized to 8 as '1', default = 4 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_mcdi_referrlmvgain. + * (locked) lmv gain for err calc. in ref, normalized to 8 as '1', default = 0 + */ +/* Bit 7: 4, reserved */ +/* Bit 3: 0, reg_mcdi_referrgmvgain. + * (locked) gmv gain for err calc. in ref, normalized to 8 as '1', default = 0 + */ +#define MCDI_REF_ERR_FRQ_CHK ((0x2f1d)) +/* Bit 31:28, reserved */ +/* Bit 27:24, reg_mcdi_referrfrqgain. + * gain for mv frquency, normalized to 4 as '1', default = 10 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_referrfrqmax. + * max gain for mv frquency check, default = 31 + */ +/* Bit 15, reserved */ +/* Bit 14:12, reg_mcdi_ref_errfrqmvdifthd2. + * mv dif threshold 2 (<) for mv frquency check, default = 3 + */ +/* Bit 11, reserved */ +/* Bit 10: 8, reg_mcdi_ref_errfrqmvdifthd1. + * mv dif threshold 1 (<) for mv frquency check, default = 2 + */ +/* Bit 7, reserved */ +/* Bit 6: 4, reg_mcdi_ref_errfrqmvdifthd0. + * mv dif threshold 0 (<) for mv frquency check, default = 1 + */ +/* Bit 3: 0, reserved */ +#define MCDI_QME_LPF_MSK ((0x2f1e)) +/* Bit 31:28, reserved */ +/* Bit 27:24, reg_mcdi_qmechkedgelpfmsk0. + * lpf mask0 for chk edge in qme, 0~8, msk1 = (8-msk0), + * normalized to 8 as '1', default = 7 + */ +/* Bit 23:20, reserved */ +/* Bit 19:16, reg_mcdi_qmebslpfmsk0. + * lpf mask0 for bs in qme, 0~8, msk1 = (8-msk0), + * normalized to 8 as '1', default = 7 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_mcdi_qmebadwlpfmsk0. + * lpf mask0 for badw in qme, 0~8, msk1 = (8-msk0), + * normalized to 8 as '1', default = 7 + */ +/* Bit 7: 4, reserved */ +/* Bit 3: 0, reg_mcdi_qmesadlpfmsk0. + * lpf mask0 for sad in qme, 0~8, msk1 = (8-msk0), + * normalized to 8 as '1', default = 7 + */ +#define MCDI_REL_DIF_THD_02 ((0x2f1f)) +/* Bit 31:24, reserved. */ +/* Bit 23:16, reg_mcdi_reldifthd2. + * thd (<) for (hdif+vdif), default = 9 + */ +/* Bit 15: 8, reg_mcdi_reldifthd1. + * thd (<) for (vdif), default = 5 + */ +/* Bit 7: 0, reg_mcdi_reldifthd0. + * thd (>=) for (hdif-vdif), default = 48 + */ +#define MCDI_REL_DIF_THD_34 ((0x2f20)) +/* Bit 31:16, reserved. */ +/* Bit 15: 8, reg_mcdi_reldifthd4. + * thd (<) for (hdif), default = 255 + */ +/* Bit 7: 0, reg_mcdi_reldifthd3. + * thd (>=) for (vdif-hdif), default = 48 + */ +#define MCDI_REL_BADW_GAIN_OFFST_01 ((0x2f21)) +/* Bit 31:24, reg_mcdi_relbadwoffst1. + * offset for badw adj, for flat block, -128~127, default = 0 + */ +/* Bit 23:16, reg_mcdi_relbadwgain1. + * gain for badw adj, for flat block, default = 128 + */ +/* Bit 15: 8, reg_mcdi_relbadwoffst0. + * offset for badw adj, for vertical block, -128~127, default = 0 + */ +/* Bit 7: 0, reg_mcdi_relbadwgain0. + * gain for badw adj, for vertical block, default = 160 + */ +#define MCDI_REL_BADW_GAIN_OFFST_23 ((0x2f22)) +/* Bit 31:24, reg_mcdi_relbadwoffst3. + * offset for badw adj, for other block, -128~127, default = 0 + */ +/* Bit 23:16, reg_mcdi_relbadwgain3. + * gain for badw adj, for other block, default = 48 + */ +/* Bit 15: 8, reg_mcdi_relbadwoffst2. + * offset for badw adj, for horizontal block, -128~127, default = 0 + */ +/* Bit 7: 0, reg_mcdi_relbadwgain2. + * gain for badw adj, for horizontal block, default = 48 + */ +#define MCDI_REL_BADW_THD_GAIN_OFFST ((0x2f23)) +/* Bit 31:23, reserved. */ +/* Bit 22:16, reg_mcdi_relbadwoffst. + * offset for badw thd adj, -64~63, default = 0 + */ +/* Bit 15: 8, reserved. */ +/* Bit 7: 0, reg_mcdi_relbadwthdgain. + * gain0 for badw thd adj, normalized to 16 as '1', default = 16 + */ +#define MCDI_REL_BADW_THD_MIN_MAX ((0x2f24)) +/* Bit 31:18, reserved. */ +/* Bit 17: 8, reg_mcdi_relbadwthdmax. + * max for badw thd adj, default = 256 + */ +/* Bit 7: 0, reg_mcdi_relbadwthdmin. + * min for badw thd adj, default = 16 + */ +#define MCDI_REL_SAD_GAIN_OFFST_01 ((0x2f25)) +/* Bit 31:24, reg_mcdi_relsadoffst1. + * offset for sad adj, for flat block, -128~127, default = 0 + */ +/* Bit 23:20, reserved. */ +/* Bit 19:16, reg_mcdi_relsadgain1. + * gain for sad adj, for flat block, normalized to 8 as '1', default = 8 + */ +/* Bit 15: 8, reg_mcdi_relsadoffst0. + * offset for sad adj, for vertical block, -128~127, default = 0 + */ +/* Bit 7: 4, reserved. */ +/* Bit 3: 0, reg_mcdi_relsadgain0. + * gain for sad adj, for vertical block, normalized to 8 as '1', default = 6 + */ +#define MCDI_REL_SAD_GAIN_OFFST_23 ((0x2f26)) +/* Bit 31:24, reg_mcdi_relsadoffst3. + * offset for sad adj, for other block, -128~127, default = 0 + */ +/* Bit 23:20, reserved. */ +/* Bit 19:16, reg_mcdi_relsadgain3. + * gain for sad adj, for other block, normalized to 8 as '1', default = 8 + */ +/* Bit 15: 8, reg_mcdi_relsadoffst2. + * offset for sad adj, for horizontal block, -128~127, default = 0 + */ +/* Bit 7: 4, reserved. */ +/* Bit 3: 0, reg_mcdi_relsadgain2. + * gain for sad adj, for horizontal block, normalized to 8 as '1', default = 12 + */ +#define MCDI_REL_SAD_THD_GAIN_OFFST ((0x2f27)) +/* Bit 31:24, reserved. */ +/* Bit 23:16, reg_mcdi_relsadoffst. + * offset for sad thd adj, -128~127, default = 0 + */ +/* Bit 15:10, reserved. */ +/* Bit 9: 0, reg_mcdi_relsadthdgain. + * gain for sad thd adj, 21*2/16, normalized to 16 as '1', default = 42 + */ +#define MCDI_REL_SAD_THD_MIN_MAX ((0x2f28)) +/* Bit 31:27, reserved. */ +/* Bit 26:16, reg_mcdi_relsadthdmax. + * max for sad thd adj, 21*32, default = 672 + */ +/* Bit 15: 9, reserved. */ +/* Bit 8: 0, reg_mcdi_relsadthdmin. + * min for sad thd adj, 21*2, default = 42 + */ +#define MCDI_REL_DET_GAIN_00 ((0x2f29)) +/* Bit 31:21, reserved. */ +/* Bit 20:16, reg_mcdi_reldetbsgain0. + * gain0 (gmv locked) for bs, for det. calc. normalized to 16 as '1', + * default = 8 + */ +/* Bit 15:14, reserved. */ +/* Bit 13: 8, reg_mcdi_reldetbadwgain0. + * gain0 (gmv locked) for badw, for det. calc. + * normalized to 16 as '1', default = 12 + */ +/* Bit 7: 5, reserved. */ +/* Bit 4: 0, reg_mcdi_reldetsadgain0. + * gain0 (gmv locked) for qsad, for det. calc. + * normalized to 16 as '1', default = 8 + */ +#define MCDI_REL_DET_GAIN_01 ((0x2f2a)) +/* Bit 31:14, reserved. */ +/* Bit 12: 8, reg_mcdi_reldetchkedgegain0. + * gain0 (gmv locked) for chk_edge, for det. calc. + * normalized to 16 as '1', default = 2 + */ +/* Bit 7, reserved. */ +/* Bit 6: 0, reg_mcdi_reldetnbrdstgain0. + * gain0 (gmv locked) for neighoring dist, for det. + * calc. normalized to 16 as '1', default = 24 + */ +#define MCDI_REL_DET_GAIN_10 ((0x2f2b)) +/* Bit 31:21, reserved. */ +/* Bit 20:16, reg_mcdi_reldetbsgain1. + * gain1 (lmv locked) for bs, for det. calc. normalized + * to 16 as '1', default = 0 + */ +/* Bit 15:14, reserved. */ +/* Bit 13: 8, reg_mcdi_reldetbadwgain1. + * gain1 (lmv locked) for badw, for det. calc. + * normalized to 16 as '1', default = 8 + */ +/* Bit 7: 5, reserved. */ +/* Bit 4: 0, reg_mcdi_reldetsadgain1. + * gain1 (lmv locked) for qsad, for det. calc. + * normalized to 16 as '1', default = 8 + */ +#define MCDI_REL_DET_GAIN_11 ((0x2f2c)) +/* Bit 31:14, reserved. */ +/* Bit 12: 8, reg_mcdi_reldetchkedgegain1. + * gain1 (lmv locked) for chk_edge, for det. calc. + * normalized to 16 as '1', default = 0 + */ +/* Bit 7, reserved. */ +/* Bit 6: 0, reg_mcdi_reldetnbrdstgain1. + * gain1 (lmv locked) for neighoring dist, for det. + * calc. normalized to 16 as '1', default = 24 + */ +#define MCDI_REL_DET_GAIN_20 ((0x2f2d)) +/* Bit 31:21, reserved. */ +/* Bit 20:16, reg_mcdi_reldetbsgain2. + * gain2 (no locked) for bs, for det. calc.normalized to 16 as '1', default = 12 + */ +/* Bit 15:14, reserved. */ +/* Bit 13: 8, reg_mcdi_reldetbadwgain2. + * gain2 (no locked) for badw, for det. calc. + * normalized to 16 as '1',default = 32 + */ +/* Bit 7: 5, reserved. */ +/* Bit 4: 0, reg_mcdi_reldetsadgain2. + * gain2 (no locked) for qsad, for det. calc. + * normalized to 16 as '1', default = 16 + */ +#define MCDI_REL_DET_GAIN_21 ((0x2f2e)) +/* Bit 31:26, reserved */ +/* Bit 25:16, reg_mcdi_reldetoffst. + * offset for rel calculation, for det. calc. -512~511, default = 0 + */ +/* Bit 15:14, reserved. */ +/* Bit 12: 8, reg_mcdi_reldetchkedgegain2. + * gain2 (no locked) for chk_edge, for det. calc. + * normalized to 16 as '1', default = 10 + */ +/* Bit 7, reserved. */ +/* Bit 6: 0, reg_mcdi_reldetnbrdstgain2. + * gain2 (no locked) for neighoring dist, for det. calc. + * normalized to 16 as '1', default = 32 + */ +#define MCDI_REL_DET_GMV_DIF_CHK ((0x2f2f)) +/* Bit 31:24, reserved. */ +/* Bit 23:16, reg_mcdi_reldetgmvfltthd. + * flat thd (>=) for gmv lock decision, default = 0 + */ +/* Bit 15, reserved. */ +/* Bit 14:12, reg_mcdi_reldetgmvdifthd. + * dif thd (>=) for current mv different from gmv for gmv dif check, + * actually used in Lmv lock check, default = 3 + */ +/* Bit 11, reserved. */ +/* Bit 10: 8, reg_mcdi_reldetgmvdifmin. + * min mv dif for gmv dif check, default = 1, note: dif between + * reg_mcdi_rel_det_gmv_dif_max and reg_mcdi_rel_det_gmv_dif_min + * should be; 0,1,3,7, not work for others + */ +/* Bit 7: 4, reg_mcdi_reldetgmvdifmax. + * max mv dif for gmv dif check, default = 4 + */ +/* Bit 3: 1, reserved */ +/* Bit 0, reg_mcdi_reldetgmvdifmvmode. + * mv mode used for gmv dif check, 0: use refmv, 1: use qmv, default = 0 + */ +#define MCDI_REL_DET_LMV_DIF_CHK ((0x2f30)) +/* Bit 31:24, reserved. */ +/* Bit 23:16, reg_mcdi_reldetlmvfltthd. + * flat thd (>=) for lmv lock decision, default = 12 + */ +/* Bit 15:14, reserved. */ +/* Bit 13:12, reg_mcdi_reldetlmvlockchkmode. + * lmv lock check mode, 0:cur Lmv, 1: cur & (last | next), + * 2: last & cur & next Lmv, default = 1 + */ +/* Bit 11, reserved. */ +/* Bit 10: 8, reg_mcdi_reldetlmvdifmin. + * min mv dif for lmv dif check, default = 1, note: dif between + * reg_mcdi_rel_det_lmv_dif_max and reg_mcdi_rel_det_lmv_dif_min should be; + * 0,1,3,7, not work for others + */ +/* Bit 7: 4, reg_mcdi_reldetlmvdifmax. + * max mv dif for lmv dif check, default = 4 + */ +/* Bit 3: 1, reserved */ +/* Bit 0, reg_mcdi_reldetlmvdifmvmode. + * mv mode used for lmv dif check, 0: use refmv, 1: use qmv, default = 0 + */ +#define MCDI_REL_DET_FRQ_CHK ((0x2f31)) +/* Bit 31:12, reserved. */ +/* Bit 11: 8, reg_mcdi_reldetfrqgain. + * gain for frequency check, normalized to 4 as '1', default = 10 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetfrqmax. + * max value for frequency check, default = 31 + */ +#define MCDI_REL_DET_PD22_CHK ((0x2f32)) +/* Bit 31:18, reserved. */ +/* Bit 17: 8, reg_mcdi_reldetpd22chkoffst. + * offset for pd22 check happened, default = 512 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetpd22chkgain. + * gain for pd22 check happened, normalized to 8 as '1', default = 12 + */ +#define MCDI_REL_DET_RPT_CHK_ROW ((0x2f33)) +/* Bit 31:27, reserved */ +/* Bit 26:16, reg_mcdi_reldetrptchkendrow. + * end row (<) number for repeat check, default = 2047 + */ +/* Bit 15:11, reserved */ +/* Bit 10: 0, reg_mcdi_reldetrptchkstartrow. + * start row (>=) number for repeat check, default = 0 + */ +#define MCDI_REL_DET_RPT_CHK_GAIN_QMV ((0x2f34)) +/* Bit 31:30, reserved */ +/* Bit 29:24, reg_mcdi_reldetrptchkqmvmax. + * max thd (<) of abs qmv for repeat check, default = 15, + * note that quarter mv's range is -63~63 + */ +/* Bit 23:22, reserved */ +/* Bit 21:16, reg_mcdi_reldetrptchkqmvmin. + * min thd (>=) of abs qmv for repeat check, default = 10, + * note that quarter mv's range is -63~63 + */ +/* Bit 15, reserved/ */ +/* Bit 14: 4, reg_mcdi_reldetrptchkoffst. + * offset for repeat check, default = 512 + */ +/* Bit 3: 0, reg_mcdi_reldetrptchkgain. + * gain for repeat check, normalized to 8 as '1', default = 4 + */ +#define MCDI_REL_DET_RPT_CHK_THD_0 ((0x2f35)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_reldetrptchkzerosadthd. + * zero sad thd (<) for repeat check, default = 255 + */ +/* Bit 15:14, reserved. */ +/* Bit 13: 8, reg_mcdi_reldetrptchkzerobadwthd. + * zero badw thd (>=) for repeat check, default = 16 + */ +/* Bit 7: 4, reserved */ +/* Bit 3: 0, reg_mcdi_reldetrptchkfrqdifthd. + * frequency dif thd (<) for repeat check, 0~10, default = 5 + */ +#define MCDI_REL_DET_RPT_CHK_THD_1 ((0x2f36)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_mcdi_reldetrptchkvdifthd. + * vertical dif thd (<) for repeat check, default = 16 + */ +/* Bit 7: 0, reg_mcdi_reldetrptchkhdifthd. + * horizontal dif thd (>=) for repeat check, default = 16 + */ +#define MCDI_REL_DET_LPF_DIF_THD ((0x2f37)) +/* Bit 31:24, reg_mcdi_reldetlpfdifthd3. + * hdif thd (<) for lpf selection of horizontal block, default = 9 + */ +/* Bit 23:16, reg_mcdi_reldetlpfdifthd2. + * vdif-hdif thd (>=) for lpf selection of horizontal block, default = 48 + */ +/* Bit 15: 8, reg_mcdi_reldetlpfdifthd1. + * vdif thd (<) for lpf selection of vertical block, default = 9 + */ +/* Bit 7: 0, reg_mcdi_reldetlpfdifthd0. + * hdif-vdif thd (>=) for lpf selection of vertical block, default = 48 + */ +#define MCDI_REL_DET_LPF_MSK_00_03 ((0x2f38)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_reldetlpfmsk03. + * det lpf mask03 for gmv/lmv locked mode, 0~16, default = 1 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_reldetlpfmsk02. + * det lpf mask02 for gmv/lmv locked mode, 0~16, default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_reldetlpfmsk01. + * det lpf mask01 for gmv/lmv locked mode, 0~16, default = 5 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetlpfmsk00. + * det lpf mask00 for gmv/lmv locked mode, 0~16, default = 8 + */ +#define MCDI_REL_DET_LPF_MSK_04_12 ((0x2f39)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_reldetlpfmsk12. + * det lpf mask12 for vertical blocks, 0~16, default = 0 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_reldetlpfmsk11. + * det lpf mask11 for vertical blocks, 0~16, default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_reldetlpfmsk10. + * det lpf mask10 for vertical blocks, 0~16, default = 16 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetlpfmsk04. + * det lpf mask04 for gmv/lmv locked mode, 0~16, default = 1 + */ +#define MCDI_REL_DET_LPF_MSK_13_21 ((0x2f3a)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_reldetlpfmsk21. + * det lpf mask21 for horizontal blocks, 0~16, default = 6 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_reldetlpfmsk20. + * det lpf mask20 for horizontal blocks, 0~16, default = 8 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_reldetlpfmsk14. + * det lpf mask14 for vertical blocks, 0~16, default = 0 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetlpfmsk13. + * det lpf mask13 for vertical blocks, 0~16, default = 0 + */ +#define MCDI_REL_DET_LPF_MSK_22_30 ((0x2f3b)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_reldetlpfmsk30. + * det lpf mask30 for other blocks, 0~16, default = 16 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_reldetlpfmsk24. + * det lpf mask24 for horizontal blocks, 0~16, default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_reldetlpfmsk23. + * det lpf mask23 for horizontal blocks, 0~16, default = 0 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetlpfmsk22. + * det lpf mask22 for horizontal blocks, 0~16, default = 1 + */ +#define MCDI_REL_DET_LPF_MSK_31_34 ((0x2f3c)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_reldetlpfmsk34. + * det lpf mask34 for other blocks, 0~16, default = 0 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_reldetlpfmsk33. + * det lpf mask33 for other blocks, 0~16, default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_reldetlpfmsk32. + * det lpf mask32 for other blocks, 0~16, default = 0 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_reldetlpfmsk31. + * det lpf mask31 for other blocks, 0~16, default = 0 + */ +/* Note: there are four group lpf masks from addr 37~3b, + * each group sum equal to 16. + */ +#define MCDI_REL_DET_MIN ((0x2f3d)) +/* Bit 31: 7, reserved */ +/* Bit 6: 0, reg_mcdi_reldetmin. + * min of detected value, default = 16 + */ +#define MCDI_REL_DET_LUT_0_3 ((0x2f3e)) +/* Bit 31:24, reg_mcdi_reldetmaplut3. default = 8 */ +/* Bit 23:16, reg_mcdi_reldetmaplut2. default = 4 */ +/* Bit 15: 8, reg_mcdi_reldetmaplut1. default = 2 */ +/* Bit 7: 0, reg_mcdi_reldetmaplut0. default = 0 */ +#define MCDI_REL_DET_LUT_4_7 ((0x2f3f)) +/* Bit 31:24, reg_mcdi_reldetmaplut7. default = 64 */ +/* Bit 23:16, reg_mcdi_reldetmaplut6. default = 48 */ +/* Bit 15: 8, reg_mcdi_reldetmaplut5. default = 32 */ +/* Bit 7: 0, reg_mcdi_reldetmaplut4. default = 16 */ +#define MCDI_REL_DET_LUT_8_11 ((0x2f40)) +/* Bit 31:24, reg_mcdi_reldetmaplut11. default = 160 */ +/* Bit 23:16, reg_mcdi_reldetmaplut10. default = 128 */ +/* Bit 15: 8, reg_mcdi_reldetmaplut9. default = 96 */ +/* Bit 7: 0, reg_mcdi_reldetmaplut8. default = 80 */ +#define MCDI_REL_DET_LUT_12_15 ((0x2f41)) +/* Bit 31:24, reg_mcdi_reldetmaplut15. default = 255 */ +/* Bit 23:16, reg_mcdi_reldetmaplut14. default = 240 */ +/* Bit 15: 8, reg_mcdi_reldetmaplut13. default = 224 */ +/* Bit 7: 0, reg_mcdi_reldetmaplut12. default = 192 */ +#define MCDI_REL_DET_COL_CFD_THD ((0x2f42)) +/* Bit 31:24, reg_mcdi_reldetcolcfdfltthd. + * thd for flat smaller than (<) of column cofidence, default = 5 + */ +/* Bit 23:16, reg_mcdi_reldetcolcfdthd1. + * thd for rel larger than (>=) in rel calc. + * mode col confidence without gmv locking, default = 160 + */ +/* Bit 15: 8, reg_mcdi_reldetcolcfdthd0. + * thd for rel larger than (>=) in rel calc. + * mode col confidence when gmv locked, default = 100 + */ +/* Bit 7: 2, reg_mcdi_reldetcolcfdbadwthd. + * thd for badw larger than (>=) in qbadw calc. + * mode of column cofidence, default = 16 + */ +/* Bit 1, reserved */ +/* Bit 0, reg_mcdi_reldetcolcfdcalcmode. calc. + * mode for column cofidence, 0: use rel, 1: use qbadw, default = 0 + */ +#define MCDI_REL_DET_COL_CFD_AVG_LUMA ((0x2f43)) +/* Bit 31:24, reg_mcdi_reldetcolcfdavgmin1. + * avg luma min1 (>=) for column cofidence, valid between 16~235, default = 235 + */ +/* Bit 23:16, reg_mcdi_reldetcolcfdavgmax1. + * avg luma max1 (<) for column cofidence, valid between 16~235, default = 235 + */ +/* Bit 15: 8, reg_mcdi_reldetcolcfdavgmin0. + * avg luma min0 (>=) for column cofidence, valid between 16~235, default = 16 + */ +/* Bit 7: 0, reg_mcdi_reldetcolcfdavgmax0. + * avg luma max0 (<) for column cofidence, valid between 16~235, default = 21 + */ +#define MCDI_REL_DET_BAD_THD_0 ((0x2f44)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_mcdi_reldetbadsadthd. + * thd (>=) for bad sad, default = 120 (480/4) + */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_mcdi_reldetbadbadwthd. + * thd (>=) for bad badw, 0~42, default = 12 + */ +#define MCDI_REL_DET_BAD_THD_1 ((0x2f45)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_reldetbadrelfltthd. + * thd (>=) of flat for bad rel detection, default = 4 + */ +/* Bit 15: 8, reg_mcdi_reldetbadrelthd1. + * thd (>=) for bad rel without gmv/lmv locked, default = 160 + */ +/* Bit 7: 0, reg_mcdi_reldetbadrelthd0. + * thd (>=) for bad rel with gmv/lmv locked, default = 120 + */ +#define MCDI_PD22_CHK_THD ((0x2f46)) +/* Bit 31:25, reserved */ +/* Bit 24:16, reg_mcdi_pd22chksaddifthd. + * sad dif thd (>=) for (pd22chksad - qsad) for pd22 check, default = 64 + */ +/* Bit 15:14, reserved */ +/* Bit 13: 8, reg_mcdi_pd22chkqmvthd. + * thd (>=) of abs qmv for pd22 check, default = 2 + */ +/* Bit 7: 0, reg_mcdi_pd22chkfltthd. + * thd (>=) of flat for pd22 check, default = 4 + */ +#define MCDI_PD22_CHK_GAIN_OFFST_0 ((0x2f47)) +/* Bit 31:24, reg_mcdi_pd22chkedgeoffst0. + * offset0 of pd22chkedge from right film22 phase, -128~127, default = 0 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_pd22chkedgegain0. + * gain0 of pd22chkedge from right film22 phase, + * normalized to 16 as '1', default = 16 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_mcdi_pd22chkbadwoffst0. + * offset0 of pd22chkbadw from right film22 phase, -8~7, default = 0 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_pd22chkbadwgain0. + * gain0 of pd22chkbadw from right film22 phase, + * normalized to 16 as '1', default = 8 + */ +#define MCDI_PD22_CHK_GAIN_OFFST_1 ((0x2f48)) +/* Bit 31:24, reg_mcdi_pd22chkedgeoffst1. + * offset1 of pd22chkedge from right film22 phase, -128~127, default = 0 + */ +/* Bit 23:21, reserved */ +/* Bit 20:16, reg_mcdi_pd22chkedgegain1. + * gain1 of pd22chkedge from right film22 phase, + * normalized to 16 as '1', default = 16 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_mcdi_pd22chkbadwoffst1. + * offset1 of pd22chkbadw from right film22 phase, -8~7, default = 0 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_pd22chkbadwgain1. + * gain1 of pd22chkbadw from right film22 phase, + * normalized to 16 as '1', default = 12 + */ +#define MCDI_LMV_LOCK_CNT_THD_GAIN ((0x2f49)) +/* Bit 31:20, reserved */ +/* Bit 19:16, reg_mcdi_lmvlockcntmax. + * max lmv lock count number, default = 6 + */ +/* Bit 15:12, reg_mcdi_lmvlockcntoffst. + * offset for lmv lock count, -8~7, default = 0 + */ +/* Bit 11: 8, reg_mcdi_lmvlockcntgain. + * gain for lmv lock count, normalized 8 as '1', 15 is set to 16, default = 8 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_lmvlockcntthd. + * lmv count thd (>=) before be locked, 1~31, default = 4 + */ +#define MCDI_LMV_LOCK_ABS_DIF_THD ((0x2f4a)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_mcdi_lmvlockdifthd2. + * lmv dif thd for third part, before locked, default = 1 + */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_mcdi_lmvlockdifthd1. + * lmv dif thd for second part, before locked, default = 1 + */ +/* Bit 19, reserved */ +/* Bit 18:16, reg_mcdi_lmvlockdifthd0. + * lmv dif thd for first part, before locked, default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_lmvlockabsmax. + * max abs (<) of lmv to be locked, default = 24 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_lmvlockabsmin. + * min abs (>=) of lmv to be locked, default = 1 + */ +#define MCDI_LMV_LOCK_ROW ((0x2f4b)) +/* Bit 31:27, reserved */ +/* Bit 26:16, reg_mcdi_lmvlockendrow. + * end row (<) for lmv lock, default = 2047 + */ +/* Bit 15:11, reserved */ +/* Bit 10: 0, reg_mcdi_lmvlockstartrow. + * start row (>=) for lmv lock, default = 0 + */ +#define MCDI_LMV_LOCK_RT_MODE ((0x2f4c)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_mcdi_lmvlockextmode. + * extend lines for lmv lock check, check how many lines + * for lmv locking, default = 2 + */ +/* Bit 23:16, reg_mcdi_lmvlockfltcntrt. + * ratio of flt cnt for lock check, normalized 256 as '1', + * 255 is set to 256, default = 32 + */ +/* Bit 15: 8, reg_mcdi_lmvlocklmvcntrt1. + * ratio when use non-zero lmv for lock check, + * normalized 256 as '1', 255 is set to 256, default = 48 + */ +/* Bit 7: 0, reg_mcdi_lmvlocklmvcntrt0. + * ratio when use max lmv for lock check, normalized 256 as '1', +255 is set to 256, default = 106 +*/ +#define MCDI_GMV_LOCK_CNT_THD_GAIN ((0x2f4d)) +/* Bit 31:20, reserved */ +/* Bit 19:16, reg_mcdi_gmvlockcntmax. + * max gmv lock count number, default = 6 + */ +/* Bit 15:12, reg_mcdi_gmvlockcntoffst. + * offset for gmv lock count, -8~7, default = 0 + */ +/* Bit 11: 8, reg_mcdi_gmvlockcntgain. + * gain for gmv lock count, normalized 8 as '1', 15 is set to 16, default = 8 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_gmvlockcntthd. + * gmv count thd (>=) before be locked, 1~31, default = 4 + */ +#define MCDI_GMV_LOCK_ABS_DIF_THD ((0x2f4e)) +/* Bit 31:27, reserved */ +/* Bit 26:24, reg_mcdi_gmvlockdifthd2. + * gmv dif thd for third part, before locked, default = 3 + */ +/* Bit 23, reserved */ +/* Bit 22:20, reg_mcdi_gmvlockdifthd1. + * gmv dif thd for second part, before locked, default = 2 + */ +/* Bit 19, reserved */ +/* Bit 18:16, reg_mcdi_gmvlockdifthd0. + * gmv dif thd for first part, before locked, default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_gmvlockabsmax. + * max abs of gmv to be locked, default = 15 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_gmvlockabsmin. + * min abs of gmv to be locked, default = 1 + */ +#define MCDI_HIGH_VERT_FRQ_DIF_THD ((0x2f4f)) +/* Bit 31: 0, reg_mcdi_highvertfrqfldavgdifthd. + * high_vert_frq field average luma dif thd (>=), 3*Blk_Width*Blk_Height, + * set by software, default = 103680 + */ +#define MCDI_HIGH_VERT_FRQ_DIF_DIF_THD ((0x2f50)) +/* Bit 31: 0, reg_mcdi_highvertfrqfldavgdifdifthd. + * high_vert_frq field average luma dif's dif thd (<), 3*Blk_Width*Blk_Height, + * set by software, default = 103680 + */ +#define MCDI_HIGH_VERT_FRQ_RT_GAIN ((0x2f51)) +/* Bit 31:20, reserved */ +/* Bit 19:16, reg_mcdi_highvertfrqcntthd. + * high_vert_frq count thd (>=) before locked, 1~31, default = 4 + */ +/* Bit 15: 8, reg_mcdi_highvertfrqbadsadrt. + * ratio for high_vert_frq bad sad count, normalized 256 as '1', + * 255 is set to 256, default = 24 + */ +/* Bit 7: 0, reg_mcdi_highvertfrqbadbadwrt. + * ratio for high_vert_frq badw count, normalized 256 as '1', + * 255 is set to 256, default = 130 + */ +#define MCDI_MOTION_PARADOX_THD ((0x2f52)) +/* Bit 31:29, reserved */ +/* Bit 28:24, reg_mcdi_motionparadoxcntthd. + * motion paradox count thd (>=) before locked, 1~31, default = 4 + */ +/* Bit 23:22, reserved */ +/* Bit 21:16, reg_mcdi_motionparadoxgmvthd. + * abs gmv thd (<) of motion paradox, 0~32, note that 32 + * means invalid gmv, be careful, default = 32 + */ +/* Bit 15: 0, reserved */ +#define MCDI_MOTION_PARADOX_RT ((0x2f53)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_motionparadoxbadsadrt. + * ratio for field bad sad count of motion paradox, + * normalized 256 as '1', 255 is set to 256, default = 24 + */ +/* Bit 15: 8, reg_mcdi_motionparadoxbadrelrt. + * ratio for field bad reliabilty count of motion paradox, + * normalized 256 as '1', 255 is set to 256, default = 120 + */ +/* Bit 7: 0, reg_mcdi_motionparadoxmtnrt. + * ratio for field motion count of motion paradox, + * normalized 256 as '1', 255 is set to 256, default = 218 + */ +#define MCDI_MOTION_REF_THD ((0x2f54)) +/* Bit 31:24, reserved */ +/* Bit 23:20, reg_mcdi_motionrefoffst. + * motion ref additive offset, default = 15 + */ +/* Bit 19:16, reg_mcdi_motionrefgain. + * motion ref gain, normalized 8 as '1', default = 8 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_motionrefrptmvthd. + * abs thd (>=) of rpt mv (0~31, 32 means invalid) for motion ref, default = 1 + */ +/* Bit 7: 2, reg_mcdi_motionrefqmvthd. + * min thd (>=) of abs qmv for motion ref, + * note that quarter mv's range is -63~63, default = 2 + */ +/* Bit 1: 0, reg_mcdi_motionreflpfmode. + * Mv and (8 x repeat flg) 's lpf mode of motion refinement, + * 0: no lpf, 1: [1 2 1], 2: [1 2 2 2 1], default = 1 + */ +#define MCDI_REL_COL_REF_RT ((0x2f55)) +/* Bit 31: 8, reserved */ +/* Bit 7: 0, reg_mcdi_relcolrefrt. + * ratio for column cofidence level against column number, + * for refinement, default = 135 + */ +#define MCDI_PD22_CHK_THD_RT ((0x2f56)) +/* Bit 31:27, reserved */ +/* Bit 26:16, reg_mcdi_pd22chkfltcntrt. + * ratio for flat count of field pulldown 22 check, normalized 2048 as '1', + * 2047 is set to 2048, default = 1 + */ +/* Bit 15: 8, reg_mcdi_pd22chkcntrt. ratio of pulldown 22 check count, + * normalized 256 as '1', 255 is set to 256, default = 100 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_pd22chkcntthd. + * thd (>=) for pd22 count before locked, 1~31, default = 4 + */ +#define MCDI_CHAR_DET_DIF_THD ((0x2f57)) +/* Bit 31:24, reserved */ +/* Bit 23:16, reg_mcdi_chardetminmaxdifthd. + * thd (>=) for dif between min and max value, default = 64 + */ +/* Bit 15: 8, reg_mcdi_chardetmaxdifthd. + * thd (<) for dif between max value, default = 17 + */ +/* Bit 7: 0, reg_mcdi_chardetmindifthd. + * thd (<) for dif between min value, default = 17 + */ +#define MCDI_CHAR_DET_CNT_THD ((0x2f58)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_chardettotcntthd. + * thd (>=) for total count, 0~21, default = 18 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_chardetmaxcntthd. + * thd (>=) for max count, 0~21, default = 1 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_chardetmincntthd. + * thd (>=) for min count, 0~21, default = 1 + */ +#define MCDI_FIELD_MV ((0x2f60)) +/* Bit 31:24, reg_mcdi_pd22chkcnt */ +/* Bit 23:16, reg_mcdi_fieldgmvcnt */ +/* Bit 15, reg_mcdi_pd22chkflg */ +/* Bit 14, reg_mcdi_fieldgmvlock */ +/* Bit 13: 8, reg_mcdi_fieldrptmv. last field rpt mv */ +/* Bit 7: 6, reserved */ +/* Bit 5: 0, reg_mcdi_fieldgmv. last field gmv */ +#define MCDI_FIELD_HVF_PRDX_CNT ((0x2f61)) +/* Bit 31:24, reg_mcdi_motionparadoxcnt. */ +/* Bit 23:17, reserved */ +/* Bit 16, reg_mcdi_motionparadoxflg. */ +/* Bit 15: 8, reg_mcdi_highvertfrqcnt. */ +/* Bit 7: 4, reserved */ +/* Bit 3: 2, reg_mcdi_highvertfrqphase. */ +/* Bit 1, reserved */ +/* Bit 0, reg_mcdi_highvertfrqflg. */ +#define MCDI_FIELD_LUMA_AVG_SUM_0 ((0x2f62)) +/* Bit 31: 0, reg_mcdi_fld_luma_avg_sum0. */ +#define MCDI_FIELD_LUMA_AVG_SUM_1 ((0x2f63)) +/* Bit 31: 0, reg_mcdi_fld_luma_avg_sum1. */ +#define MCDI_YCBCR_BLEND_CRTL ((0x2f64)) +/* Bit 31:16, reserved */ +/* Bit 15: 8, reg_mcdi_ycbcrblendgain. + * ycbcr blending gain for cbcr in ycbcr. default = 0 + */ +/* Bit 7: 2, reserved. */ +/* Bit 1: 0, reg_mcdi_ycbcrblendmode. + * 0:y+cmb(cb,cr), 1:med(r,g,b), 2:max(r,g,b), default = 2 + */ +#define MCDI_MCVECWR_CANVAS_SIZE ((0x2f65)) +#define MCDI_MCVECRD_CANVAS_SIZE ((0x2f66)) +#define MCDI_MCINFOWR_CANVAS_SIZE ((0x2f67)) +#define MCDI_MCINFORD_CANVAS_SIZE ((0x2f68)) +#define MCDI_LMVLCKSTEXT_0 ((0x2f69)) +#define MCDI_LMVLCKSTEXT_1 ((0x2f6a)) +#define MCDI_LMVLCKEDEXT_0 ((0x2f6b)) +#define MCDI_LMVLCKEDEXT_1 ((0x2f6c)) +#define MCDI_MCVECWR_X ((0x2f92)) +#define MCDI_MCVECWR_Y ((0x2f93)) +#define MCDI_MCVECWR_CTRL ((0x2f94)) +#define MCDI_MCVECRD_X ((0x2f95)) +#define MCDI_MCVECRD_Y ((0x2f96)) +#define MCDI_MCVECRD_CTRL ((0x2f97)) +#define MCDI_MCINFOWR_X ((0x2f98)) +#define MCDI_MCINFOWR_Y ((0x2f99)) +#define MCDI_MCINFOWR_CTRL ((0x2f9a)) +#define MCDI_MCINFORD_X ((0x2f9b)) +#define MCDI_MCINFORD_Y ((0x2f9c)) +#define MCDI_MCINFORD_CTRL ((0x2f9d)) +/* === MC registers ============================================ */ +#define MCDI_MC_CRTL ((0x2f70)) +/* Bit 31: 9, reserved */ +/* Bit 8, reg_mcdi_mcpreflg. + * flag to use previous field for MC, 0:forward field, + * 1: previous field, default = 1 + */ +/* Bit 7, reg_mcdi_mcrelrefbycolcfden. + * enable rel refinement by column cofidence in mc blending, default = 1 + */ +/* Bit 6: 5, reg_mcdi_mclpfen. + * enable mc pixles/rel lpf, 0:disable, 1: lpf rel, + * 2: lpf mc pxls, 3: lpf both rel and mc pxls, default = 0 + */ +/* Bit 4: 2, reg_mcdi_mcdebugmode. + * enable mc debug mode, 0:disable, 1: split left/right, + * 2: split top/bottom, 3: debug mv, 4: debug rel, default = 0 + */ +/* Bit 1: 0, reg_mcdi_mcen. + * mcdi enable mode, 0:disable, 1: blend with ma, 2: full mc, default = 1 + */ +#define MCDI_MC_LPF_MSK_0 ((0x2f71)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_mclpfmsk02. + * mc lpf coef. 2 for pixel 0 of current block,normalized 16 as '1', default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_mclpfmsk01. + * mc lpf coef. 1 for pixel 0 of current block,normalized 16 as '1', default = 9 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_mclpfmsk00. + * mc lpf coef. 0 for pixel 0 of current block,normalized 16 as '1', default = 7 + */ +#define MCDI_MC_LPF_MSK_1 ((0x2f72)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_mclpfmsk12. + * mc lpf coef. 2 for pixel 1 of current block, + * 0~16, normalized 16 as '1', default = 0 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_mclpfmsk11. + * mc lpf coef. 1 for pixel 1 of current block, 0~16, + * normalized 16 as '1', default = 11 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_mclpfmsk10. + * mc lpf coef. 0 for pixel 1 of current block, 0~16, + * normalized 16 as '1', default = 5 + */ +#define MCDI_MC_LPF_MSK_2 ((0x2f73)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_mclpfmsk22. + * mc lpf coef. 2 for pixel 2 of current block, 0~16, + * normalized 16 as '1', default = 1 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_mclpfmsk21. + * mc lpf coef. 1 for pixel 2 of current block, 0~16, + * normalized 16 as '1', default = 14 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_mclpfmsk20. + * mc lpf coef. 0 for pixel 2 of current block, 0~16, + * normalized 16 as '1', default = 1 + */ +#define MCDI_MC_LPF_MSK_3 ((0x2f74)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_mclpfmsk32. + * mc lpf coef. 2 for pixel 3 of current block, 0~16, + * normalized 16 as '1', default = 5 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_mclpfmsk31. + * mc lpf coef. 1 for pixel 3 of current block, 0~16, + * normalized 16 as '1', default = 11 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_mclpfmsk30. + * mc lpf coef. 0 for pixel 3 of current block, 0~16, + * normalized 16 as '1', default = 0 + */ +#define MCDI_MC_LPF_MSK_4 ((0x2f75)) +/* Bit 31:21, reserved */ +/* Bit 20:16, reg_mcdi_mclpfmsk42. + * mc lpf coef. 2 for pixel 4 of current block, 0~16, + * normalized 16 as '1', default = 7 + */ +/* Bit 15:13, reserved */ +/* Bit 12: 8, reg_mcdi_mclpfmsk41. + * mc lpf coef. 1 for pixel 4 of current block, 0~16, + * normalized 16 as '1', default = 9 + */ +/* Bit 7: 5, reserved */ +/* Bit 4: 0, reg_mcdi_mclpfmsk40. + * mc lpf coef. 0 for pixel 4 of current block, 0~16, + * normalized 16 as '1', default = 0 + */ +#define MCDI_MC_REL_GAIN_OFFST_0 ((0x2f76)) +/* Bit 31:26, reserved */ +/* Bit 25, reg_mcdi_mcmotionparadoxflg. + * flag of motion paradox, initial with 0 and read from software, default = 0 + */ +/* Bit 24, reg_mcdi_mchighvertfrqflg. + * flag of high vert frq, initial with 0 and read from software, default = 0 + */ +/* Bit 23:16, reg_mcdi_mcmotionparadoxoffst. + * offset (rel + offset) for rel (MC blending coef.) + * refinement if motion paradox + * detected before MC blending before MC blending, default = 128 + */ +/* Bit 15:12, reserved */ +/* Bit 11: 8, reg_mcdi_mcmotionparadoxgain. + * gain for rel (MC blending coef.) + * refinement if motion paradox detected before MC + * blending, normalized 8 as '1', set 15 to 16, default = 8 + */ +/* Bit 7: 4, reg_mcdi_mchighvertfrqoffst. minus offset + * (alpha - offset) for motion (MA blending coef.) refinement if high vertical + * frequency detected before MA blending, default = 15 + */ +/* Bit 3: 0, reg_mcdi_mchighvertfrqgain. + * gain for motion (MA blending coef.) refinement if high vertical frequency + * detected before MA blending, normalized 8 as '1', set 15 to 16, default = 8 + */ +#define MCDI_MC_REL_GAIN_OFFST_1 ((0x2f77)) +/* Bit 31:24, reg_mcdi_mcoutofboundrayoffst. + * offset (rel + offset) for rel (MC blending coef.) refinement + * if MC pointed out + * of boundray before MC blending before MC blending, default = 255 + */ +/* Bit 23:20, reserved*/ +/* Bit 19:16, reg_mcdi_mcoutofboundraygain. + * gain for rel (MC blending coef.) refinement + * if MC pointed out of boundray before + * MC blending, normalized 8 as '1', set 15 to 16, default = 8 + */ +/* Bit 15: 8, reg_mcdi_mcrelrefbycolcfdoffst. + * offset (rel + offset) for rel (MC blending coef.) refinement + * if motion paradox + * detected before MC blending before MC blending, default = 255 + */ +/* Bit 7: 4, reserved. */ +/* Bit 3: 0, reg_mcdi_mcrelrefbycolcfdgain. + * gain for rel (MC blending coef.) refinement + * if column cofidence failed before MC + * blending, normalized 8 as '1', set 15 to 16, default = 8 + */ +#define MCDI_MC_COL_CFD_0 ((0x2f78)) +/* Bit 31: 0, mcdi_mc_col_cfd_0. + * column cofidence value 0 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_1 ((0x2f79)) +/* Bit 31: 0, mcdi_mc_col_cfd_1. + * column cofidence value 1 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_2 ((0x2f7a)) +/* Bit 31: 0, mcdi_mc_col_cfd_2. + * column cofidence value 2 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_3 ((0x2f7b)) +/* Bit 31: 0, mcdi_mc_col_cfd_3. + * column cofidence value 3 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_4 ((0x2f7c)) +/* Bit 31: 0, mcdi_mc_col_cfd_4. + * column cofidence value 4 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_5 ((0x2f7d)) +/* Bit 31: 0, mcdi_mc_col_cfd_5. + * column cofidence value 5 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_6 ((0x2f7e)) +/* Bit 31: 0, mcdi_mc_col_cfd_6. + * column cofidence value 6 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_7 ((0x2f7f)) +/* Bit 31: 0, mcdi_mc_col_cfd_7. + * column cofidence value 7 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_8 ((0x2f80)) +/* Bit 31: 0, mcdi_mc_col_cfd_8. + * column cofidence value 8 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_9 ((0x2f81)) +/* Bit 31: 0, mcdi_mc_col_cfd_9. + * column cofidence value 9 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_10 ((0x2f82)) +/* Bit 31: 0, mcdi_mc_col_cfd_10. + * column cofidence value 10 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_11 ((0x2f83)) +/* Bit 31: 0, mcdi_mc_col_cfd_11. + * column cofidence value 11 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_12 ((0x2f84)) +/* Bit 31: 0, mcdi_mc_col_cfd_12. + * column cofidence value 12 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_13 ((0x2f85)) +/* Bit 31: 0, mcdi_mc_col_cfd_13. + * column cofidence value 13 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_14 ((0x2f86)) +/* Bit 31: 0, mcdi_mc_col_cfd_14. + * column cofidence value 14 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_15 ((0x2f87)) +/* Bit 31: 0, mcdi_mc_col_cfd_15. + * column cofidence value 15 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_16 ((0x2f88)) +/* Bit 31: 0, mcdi_mc_col_cfd_16. + * column cofidence value 16 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_17 ((0x2f89)) +/* Bit 31: 0, mcdi_mc_col_cfd_17. + * column cofidence value 17 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_18 ((0x2f8a)) +/* Bit 31: 0, mcdi_mc_col_cfd_18. + * column cofidence value 18 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_19 ((0x2f8b)) +/* Bit 31: 0, mcdi_mc_col_cfd_19. + * column cofidence value 19 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_20 ((0x2f8c)) +/* Bit 31: 0, mcdi_mc_col_cfd_20. + * column cofidence value 20 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_21 ((0x2f8d)) +/* Bit 31: 0, mcdi_mc_col_cfd_21. + * column cofidence value 21 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_22 ((0x2f8e)) +/* Bit 31: 0, mcdi_mc_col_cfd_22. + * column cofidence value 22 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_23 ((0x2f8f)) +/* Bit 31: 0, mcdi_mc_col_cfd_23. + * column cofidence value 23 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_24 ((0x2f90)) +/* Bit 31: 0, mcdi_mc_col_cfd_24. + * column cofidence value 24 read from software. initial = 0 + */ +#define MCDI_MC_COL_CFD_25 ((0x2f91)) +/* Bit 31: 0, mcdi_mc_col_cfd_25. + * column cofidence value 25 read from software. initial = 0 + */ +/* ======= PRE RO Registers ==================================== */ +#define MCDI_RO_FLD_LUMA_AVG_SUM ((0x2fa0)) +/* Bit 31: 0, ro_mcdi_fldlumaavgsum. + * block's luma avg sum of current filed (block based). initial = 0 + */ +#define MCDI_RO_GMV_VLD_CNT ((0x2fa1)) +/* Bit 31: 0, ro_mcdi_gmvvldcnt. + * valid gmv's count of pre one filed (block based). initial = 0 + */ +#define MCDI_RO_RPT_FLG_CNT ((0x2fa2)) +/* Bit 31: 0, ro_mcdi_rptflgcnt. + * repeat mv's count of pre one filed (block based). initial = 0 + */ +#define MCDI_RO_FLD_BAD_SAD_CNT ((0x2fa3)) +/* Bit 31: 0, ro_mcdi_fldbadsadcnt. + * bad sad count of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_FLD_BAD_BADW_CNT ((0x2fa4)) +/* Bit 31: 0, ro_mcdi_fldbadbadwcnt. + * bad badw count of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_FLD_BAD_REL_CNT ((0x2fa5)) +/* Bit 31: 0, ro_mcdi_fldbadrelcnt. + * bad rel count of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_FLD_MTN_CNT ((0x2fa6)) +/* Bit 31: 0, ro_mcdi_fldmtncnt. + * motion count of whole pre one field (pixel based). initial = 0 + */ +#define MCDI_RO_FLD_VLD_CNT ((0x2fa7)) +/* Bit 31: 0, ro_mcdi_fldvldcnt. + * valid motion count of whole pre one field (pixel based). initial = 0 + */ +#define MCDI_RO_FLD_PD_22_PRE_CNT ((0x2fa8)) +/* Bit 31: 0, ro_mcdi_fldpd22precnt. + * prevoius pd22 check count of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_FLD_PD_22_FOR_CNT ((0x2fa9)) +/* Bit 31: 0, ro_mcdi_fldpd22forcnt. + * forward pd22 check count of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_FLD_PD_22_FLT_CNT ((0x2faa)) +/* Bit 31: 0, ro_mcdi_fldpd22fltcnt. + * flat count (for pd22 check) of whole pre one field (block based). initial = 0 + */ +#define MCDI_RO_HIGH_VERT_FRQ_FLG ((0x2fab)) +/* Bit 31:16, reserved. */ +/* Bit 15: 8, ro_mcdi_highvertfrqcnt. + * high vertical frequency count till prevoius one field. initial = 0 + */ +/* Bit 7: 3, reserved. */ +/* Bit 2: 1, ro_mcdi_highvertfrqphase. + * high vertical frequency phase of prevoius one field. initial = 2 + */ +/* Bit 0, ro_mcdi_highvertfrqflg. + * high vertical frequency flag of prevoius one field. initial = 0 + */ +#define MCDI_RO_GMV_LOCK_FLG ((0x2fac)) +/* Bit 31:16, reserved. */ +/* Bit 15: 8, ro_mcdi_gmvlckcnt. + * global mv lock count till prevoius one field. initial = 0 + */ +/* Bit 7: 2, ro_mcdi_gmv. + * global mv of prevoius one field. -31~31, initial = 32 (invalid value) + */ +/* Bit 1, ro_mcdi_zerogmvlckflg. + * zero global mv lock flag of prevoius one field. initial = 0 + */ +/* Bit 0, ro_mcdi_gmvlckflg. + * global mv lock flag of prevoius one field. initial = 0 + */ +#define MCDI_RO_RPT_MV ((0x2fad)) +/* Bit 5: 0, ro_mcdi_rptmv. + * repeate mv of prevoius one field. -31~31, initial = 32 (invalid value) + */ +#define MCDI_RO_MOTION_PARADOX_FLG ((0x2fae)) +/* Bit 31:16, reserved. */ +/* Bit 15: 8, ro_mcdi_motionparadoxcnt. + * motion paradox count till prevoius one field. initial = 0 + */ +/* Bit 7: 1, reserved. */ +/* Bit 0, ro_mcdi_motionparadoxflg. + * motion paradox flag of prevoius one field. initial = 0 + */ +#define MCDI_RO_PD_22_FLG ((0x2faf)) +/* Bit 31:16, reserved. */ +/* Bit 15: 8, ro_mcdi_pd22cnt. + * pull down 22 count till prevoius one field. initial = 0 + */ +/* Bit 7: 1, reserved. */ +/* Bit 0, ro_mcdi_pd22flg. + * pull down 22 flag of prevoius one field. initial = 0 + */ +#define MCDI_RO_COL_CFD_0 ((0x2fb0)) +/* Bit 31: 0, ro_mcdi_col_cfd_0. + * column cofidence value 0. initial = 0 + */ +#define MCDI_RO_COL_CFD_1 ((0x2fb1)) +/* Bit 31: 0, ro_mcdi_col_cfd_1. + * column cofidence value 1. initial = 0 + */ +#define MCDI_RO_COL_CFD_2 ((0x2fb2)) +/* Bit 31: 0, ro_mcdi_col_cfd_2. + * column cofidence value 2. initial = 0 + */ +#define MCDI_RO_COL_CFD_3 ((0x2fb3)) +/* Bit 31: 0, ro_mcdi_col_cfd_3. + * column cofidence value 3. initial = 0 + */ +#define MCDI_RO_COL_CFD_4 ((0x2fb4)) +/* Bit 31: 0, ro_mcdi_col_cfd_4. + * column cofidence value 4. initial = 0 + */ +#define MCDI_RO_COL_CFD_5 ((0x2fb5)) +/* Bit 31: 0, ro_mcdi_col_cfd_5. + * column cofidence value 5. initial = 0 + */ +#define MCDI_RO_COL_CFD_6 ((0x2fb6)) +/* Bit 31: 0, ro_mcdi_col_cfd_6. column cofidence value 6. initial = 0 */ +#define MCDI_RO_COL_CFD_7 ((0x2fb7)) +/* Bit 31: 0, ro_mcdi_col_cfd_7. column cofidence value 7. initial = 0 */ +#define MCDI_RO_COL_CFD_8 ((0x2fb8)) +/* Bit 31: 0, ro_mcdi_col_cfd_8. column cofidence value 8. initial = 0 */ +#define MCDI_RO_COL_CFD_9 ((0x2fb9)) +/* Bit 31: 0, ro_mcdi_col_cfd_9. column cofidence value 9. initial = 0 */ +#define MCDI_RO_COL_CFD_10 ((0x2fba)) +/* Bit 31: 0, ro_mcdi_col_cfd_10. column cofidence value 10. initial = 0 */ +#define MCDI_RO_COL_CFD_11 ((0x2fbb)) +/* Bit 31: 0, ro_mcdi_col_cfd_11. column cofidence value 11. initial = 0 */ +#define MCDI_RO_COL_CFD_12 ((0x2fbc)) +/* Bit 31: 0, ro_mcdi_col_cfd_12. column cofidence value 12. initial = 0 */ +#define MCDI_RO_COL_CFD_13 ((0x2fbd)) +/* Bit 31: 0, ro_mcdi_col_cfd_13. column cofidence value 13. initial = 0 */ +#define MCDI_RO_COL_CFD_14 ((0x2fbe)) +/* Bit 31: 0, ro_mcdi_col_cfd_14. column cofidence value 14. initial = 0 */ +#define MCDI_RO_COL_CFD_15 ((0x2fbf)) +/* Bit 31: 0, ro_mcdi_col_cfd_15. column cofidence value 15. initial = 0 */ +#define MCDI_RO_COL_CFD_16 ((0x2fc0)) +/* Bit 31: 0, ro_mcdi_col_cfd_16. column cofidence value 16. initial = 0 */ +#define MCDI_RO_COL_CFD_17 ((0x2fc1)) +/* Bit 31: 0, ro_mcdi_col_cfd_17. column cofidence value 17. initial = 0 */ +#define MCDI_RO_COL_CFD_18 ((0x2fc2)) +/* Bit 31: 0, ro_mcdi_col_cfd_18. column cofidence value 18. initial = 0 */ +#define MCDI_RO_COL_CFD_19 ((0x2fc3)) +/* Bit 31: 0, ro_mcdi_col_cfd_19. column cofidence value 19. initial = 0 */ +#define MCDI_RO_COL_CFD_20 ((0x2fc4)) +/* Bit 31: 0, ro_mcdi_col_cfd_20. column cofidence value 20. initial = 0 */ +#define MCDI_RO_COL_CFD_21 ((0x2fc5)) +/* Bit 31: 0, ro_mcdi_col_cfd_21. column cofidence value 21. initial = 0 */ +#define MCDI_RO_COL_CFD_22 ((0x2fc6)) +/* Bit 31: 0, ro_mcdi_col_cfd_22. column cofidence value 22. initial = 0 */ +#define MCDI_RO_COL_CFD_23 ((0x2fc7)) +/* Bit 31: 0, ro_mcdi_col_cfd_23. column cofidence value 23. initial = 0 */ +#define MCDI_RO_COL_CFD_24 ((0x2fc8)) +/* Bit 31: 0, ro_mcdi_col_cfd_24. column cofidence value 24. initial = 0 */ +#define MCDI_RO_COL_CFD_25 ((0x2fc9)) +/* Bit 31: 0, ro_mcdi_col_cfd_25. column cofidence value 25. initial = 0 */ + +#define DIPD_COMB_CTRL0 0x2fd0 +/* Bit 31: 24, cmb_v_dif_min */ +/* Bit 23: 16, cmb_v_dif_max */ +/* Bit 15: 8, cmb_crg_mi */ +/* Bit 7: 0, cmb_crg_max */ +#define DIPD_COMB_CTRL1 0x2fd1 +/* Bit 31: 31, pd_check_en */ +/* Bit 29: 24, cmb_wv_min3 */ +/* Bit 21: 16, cmb_wv_min2 */ +/* Bit 13: 8, cmb_wv_min1 */ +/* Bit 5: 0, cmb_wv_min0 */ +#define DIPD_COMB_CTRL2 0x2fd2 +/* Bit 31: 28, cmb_wnd_cnt1 */ +/* Bit 25: 20, ccnt_cmmin1 */ +/* Bit 19: 16, ccnt_mtmin */ +/* Bit 13: 8, ccnt_cmmin */ +/* Bit 5: 0, cmb_wv_min4 */ +#define DIPD_COMB_CTRL3 0x2fd3 +/* Bit 31: 31, cmb32spcl */ +/* Bit 17: 12, cmb_wnd_mthd */ +/* Bit 11: 4, cmb_abs_nocmb */ +/* Bit 3: 0, cnt_minlen */ +#define DIPD_COMB_CTRL4 0x2fd4 +/* Bit 30: 30, flm_stamtn_en */ +/* Bit 29: 28, in_horflt */ +/* Bit 27: 20, alpha */ +/* Bit 19: 16, thtran_ctmtd */ +/* Bit 15: 8, htran_mnth1 */ +/* Bit 7: 0, htran_mnth0 */ +#define DIPD_COMB_CTRL5 0x2fd5 +/* Bit 31: 24, fld_mindif */ +/* Bit 23: 16, frm_mindif */ +/* Bit 13: 8, flm_smp_mtn_cnt */ +/* Bit 7: 0, flm_smp_mtn_thd */ +#define DIPD_RO_COMB_0 0x2fd6 +#define DIPD_RO_COMB_1 0x2fd7 +#define DIPD_RO_COMB_2 0x2fd8 +#define DIPD_RO_COMB_3 0x2fd9 +#define DIPD_RO_COMB_4 0x2fda +#define DIPD_RO_COMB_5 0x2fdb +#define DIPD_RO_COMB_6 0x2fdc +#define DIPD_RO_COMB_7 0x2fdd +#define DIPD_RO_COMB_8 0x2fde +#define DIPD_RO_COMB_9 0x2fdf +#define DIPD_RO_COMB_10 0x2fe0 +#define DIPD_RO_COMB_11 0x2fe1 +#define DIPD_RO_COMB_12 0x2fe2 +#define DIPD_RO_COMB_13 0x2fe3 +#define DIPD_RO_COMB_14 0x2fe4 +#define DIPD_RO_COMB_15 0x2fe5 +#define DIPD_RO_COMB_16 0x2fe6 +#define DIPD_RO_COMB_17 0x2fe7 +#define DIPD_RO_COMB_18 0x2fe8 +#define DIPD_RO_COMB_19 0x2fe9 +#define DIPD_RO_COMB_20 0x2fea +#define DIPD_COMB_CTRL6 0x2feb +/* nr3 */ +#define NR3_MODE 0x2ff0 + /* d010bfc0 */ +#define NR3_COOP_PARA 0x2ff1 +#define NR3_CNOOP_GAIN 0x2ff2 +#define NR3_YMOT_PARA 0x2ff3 +#define NR3_CMOT_PARA 0x2ff4 +#define NR3_SUREMOT_YGAIN 0x2ff5 +#define NR3_SUREMOT_CGAIN 0x2ff6 + +#endif diff --git a/drivers/amlogic/media/di_multi/register_nr4.h b/drivers/amlogic/media/di_multi/register_nr4.h new file mode 100644 index 000000000000..71d3ace160b0 --- /dev/null +++ b/drivers/amlogic/media/di_multi/register_nr4.h @@ -0,0 +1,149 @@ +/* + * drivers/amlogic/media/di_multi/register_nr4.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#define NR4_DRT_CTRL ((0x2da4)) +#define NR4_DRT_YSAD_GAIN ((0x2da5)) +#define NR4_DRT_CSAD_GAIN ((0x2da6)) +#define NR4_DRT_SAD_ALP_CORE ((0x2da7)) +#define NR4_DRT_ALP_MINMAX ((0x2da8)) +#define NR4_SNR_CTRL_REG ((0x2da9)) +#define NR4_SNR_ALPHA0_MAX_MIN ((0x2daa)) +#define NR4_ALP0C_ERR2CURV_LIMIT0 ((0x2dab)) +#define NR4_ALP0C_ERR2CURV_LIMIT1 ((0x2dac)) +#define NR4_ALP0Y_ERR2CURV_LIMIT0 ((0x2dad)) +#define NR4_ALP0Y_ERR2CURV_LIMIT1 ((0x2dae)) +#define NR4_SNR_ALPA1_RATE_AND_OFST ((0x2daf)) +#define NR4_SNR_ALPHA1_MAX_MIN ((0x2db0)) +#define NR4_ALP1C_ERR2CURV_LIMIT0 ((0x2db1)) +#define NR4_ALP1C_ERR2CURV_LIMIT1 ((0x2db2)) +#define NR4_ALP1Y_ERR2CURV_LIMIT0 ((0x2db3)) +#define NR4_ALP1Y_ERR2CURV_LIMIT1 ((0x2db4)) +#define NR4_MTN_CTRL ((0x2db5)) +#define NR4_MTN_REF_PAR0 ((0x2db6)) +#define NR4_MTN_REF_PAR1 ((0x2db7)) +#define NR4_MCNR_LUMA_ENH_CTRL ((0x2db8)) +#define NR4_MCNR_LUMA_STAT_LIMTX ((0x2db9)) +#define NR4_MCNR_LUMA_STAT_LIMTY ((0x2dba)) +#define NR4_MCNR_LUMA_DIF_CALC ((0x2dbb)) +#define NR4_MCNR_LUMAPRE_CAL_PRAM ((0x2dbc)) +#define NR4_MCNR_LUMACUR_CAL_PRAM ((0x2dbd)) +#define NR4_MCNR_MV_CTRL_REG ((0x2dbe)) +#define NR4_MCNR_MV_GAIN0 ((0x2dbf)) +#define NR4_MCNR_LMV_PARM ((0x2dc0)) +#define NR4_MCNR_ALP0_REG (0x2dc1) +#define NR4_MCNR_ALP1_AND_BET0_REG (0x2dc2) +#define NR4_MCNR_BET1_AND_BET2_REG (0x2dc3) +#define NR4_MCNR_AC_DC_CRTL (0x2dc4) +#define NR4_MCNR_CM_CTRL0 (0x2dc5) +#define NR4_MCNR_CM_PRAM (0x2dc6) +#define NR4_MCNR_CM_RSHFT_ALP0 (0x2dc7) +#define NR4_MCNR_BLUE_CENT (0x2dc8) +#define NR4_MCNR_BLUE_GAIN_PAR0 (0x2dc9) +#define NR4_MCNR_BLUE_GAIN_PAR1 (0x2dca) +#define NR4_MCNR_CM_BLUE_CLIP0 (0x2dcb) +#define NR4_MCNR_CM_BLUE_CLIP1 (0x2dcc) +#define NR4_MCNR_GREEN_CENT (0x2dcd) +#define NR4_MCNR_GREEN_GAIN_PAR0 (0x2dce) +#define NR4_MCNR_GREEN_GAIN_PAR1 (0x2dcf) +#define NR4_MCNR_GREEN_CLIP0 (0x2dd0) +#define NR4_MCNR_GREEN_CLIP2 (0x2dd1) +#define NR4_MCNR_SKIN_CENT (0x2dd2) +#define NR4_MCNR_SKIN_GAIN_PAR0 (0x2dd3) +#define NR4_MCNR_SKIN_GAIN_PAR1 (0x2dd4) +#define NR4_MCNR_SKIN_CLIP0 (0x2dd5) +#define NR4_MCNR_SKIN_CLIP1 (0x2dd6) +#define NR4_MCNR_ALP1_GLB_CTRL (0x2dd7) +#define NR4_MCNR_DC2NORM_LUT0 (0x2dd8) +#define NR4_MCNR_DC2NORM_LUT1 (0x2dd9) +#define NR4_MCNR_DC2NORM_LUT2 (0x2dda) +#define NR4_MCNR_AC2NORM_LUT0 (0x2ddb) +#define NR4_MCNR_AC2NORM_LUT1 (0x2ddc) +#define NR4_MCNR_AC2NORM_LUT2 (0x2ddd) +#define NR4_MCNR_SAD2ALP0_LUT0 (0x2dde) +#define NR4_MCNR_SAD2ALP0_LUT1 (0x2ddf) +#define NR4_MCNR_SAD2ALP0_LUT2 (0x2de0) +#define NR4_MCNR_SAD2ALP0_LUT3 (0x2de1) +#define NR4_MCNR_SAD2ALP1_LUT0 (0x2de2) +#define NR4_MCNR_SAD2ALP1_LUT1 (0x2de3) +#define NR4_MCNR_SAD2ALP1_LUT2 (0x2de4) +#define NR4_MCNR_SAD2ALP1_LUT3 (0x2de5) +#define NR4_MCNR_SAD2BET0_LUT0 (0x2de6) +#define NR4_MCNR_SAD2BET0_LUT1 (0x2de7) +#define NR4_MCNR_SAD2BET0_LUT2 (0x2de8) +#define NR4_MCNR_SAD2BET0_LUT3 (0x2de9) +#define NR4_MCNR_SAD2BET1_LUT0 (0x2dea) +#define NR4_MCNR_SAD2BET1_LUT1 (0x2deb) +#define NR4_MCNR_SAD2BET1_LUT2 (0x2dec) +#define NR4_MCNR_SAD2BET1_LUT3 (0x2ded) +#define NR4_MCNR_SAD2BET2_LUT0 (0x2dee) +#define NR4_MCNR_SAD2BET2_LUT1 (0x2def) +#define NR4_MCNR_SAD2BET2_LUT2 (0x2df0) +#define NR4_MCNR_SAD2BET2_LUT3 (0x2df1) +#define NR4_MCNR_RO_U_SUM (0x2df2) +#define NR4_MCNR_RO_V_SUM (0x2df3) +#define NR4_MCNR_RO_GRDU_SUM (0x2df4) +#define NR4_MCNR_RO_GRDV_SUM (0x2df5) +#define NR4_TOP_CTRL (0x2dff) +#define NR4_MCNR_SAD_GAIN (0x3700) +#define NR4_MCNR_LPF_CTRL (0x3701) +#define NR4_MCNR_BLD_VS3LUT0 (0x3702) +#define NR4_MCNR_BLD_VS3LUT1 (0x3703) +#define NR4_MCNR_BLD_VS3LUT2 (0x3704) +#define NR4_MCNR_BLD_VS2LUT0 (0x3705) +#define NR4_MCNR_BLD_VS2LUT1 (0x3706) +#define NR4_COEFBLT_LUT10 (0x3707) +#define NR4_COEFBLT_LUT11 (0x3708) +#define NR4_COEFBLT_LUT12 (0x3709) +#define NR4_COEFBLT_LUT20 (0x370a) +#define NR4_COEFBLT_LUT21 (0x370b) +#define NR4_COEFBLT_LUT22 (0x370c) +#define NR4_COEFBLT_LUT30 (0x370d) +#define NR4_COEFBLT_LUT31 (0x370e) +#define NR4_COEFBLT_LUT32 (0x370f) +#define NR4_COEFBLT_CONV (0x3710) +#define NR4_DBGWIN_YX0 (0x3711) +#define NR4_DBGWIN_YX1 (0x3712) +#define NR4_NM_X_CFG (0x3713) +#define NR4_NM_Y_CFG (0x3714) +#define NR4_NM_SAD_THD (0x3715) +#define NR4_MCNR_BANDSPLIT_PRAM (0x3716) +#define NR4_MCNR_ALP1_SGN_COR (0x3717) +#define NR4_MCNR_ALP1_SGN_PRAM (0x3718) +#define NR4_MCNR_ALP1_MVX_LUT1 (0x3719) +#define NR4_MCNR_ALP1_MVX_LUT2 (0x371a) +#define NR4_MCNR_ALP1_MVX_LUT3 (0x371b) +#define NR4_MCNR_ALP1_LP_PRAM (0x371c) +#define NR4_MCNR_ALP1_SGN_LUT1 (0x371d) +#define NR4_MCNR_ALP1_SGN_LUT2 (0x371e) +#define NR4_RO_NM_SAD_SUM (0x371f) +#define NR4_RO_NM_SAD_CNT (0x3720) +#define NR4_RO_NM_VAR_SUM (0x3721) +#define NR4_RO_NM_VAR_SCNT (0x3722) +#define NR4_RO_NM_VAR_MIN_MAX (0x3723) +#define NR4_RO_NR4_DBGPIX_NUM (0x3724) +#define NR4_RO_NR4_BLDVS2_SUM (0x3725) +#define NR4_BLDVS3_SUM (0x3726) +#define NR4_COEF12_SUM (0x3727) +#define NR4_COEF123_SUM (0x3728) +#define NR_DB_FLT_CTRL (0x3738) +#define NR_DB_FLT_YC_THRD (0x3739) +#define NR_DB_FLT_RANDLUT (0x373a) +#define NR_DB_FLT_PXI_THRD (0x373b) +#define NR_DB_FLT_SEED_Y (0x373c) +#define NR_DB_FLT_SEED_V (0x373e) +#define NR_DB_FLT_SEED3 (0x373f) +#define LBUF_TOP_CTRL (0x2fff) diff --git a/drivers/amlogic/media/dtv_demod/amlfrontend.c b/drivers/amlogic/media/dtv_demod/amlfrontend.c index 0de2f3101cf5..4b49646e9293 100644 --- a/drivers/amlogic/media/dtv_demod/amlfrontend.c +++ b/drivers/amlogic/media/dtv_demod/amlfrontend.c @@ -1204,23 +1204,23 @@ static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode) sys.demod_clk = Demod_Clk_200M; demod_status.tmp = Adc_mode; } else { - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; sys.demod_clk = Demod_Clk_72M; demod_status.tmp = Cry_mode; } if (is_ic_ver(IC_VER_TL1)) { - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; /*for timeshift mosaic issue,already fixed with tm2*/ sys.demod_clk = Demod_Clk_167M; demod_status.tmp = Cry_mode; } else if (is_ic_ver(IC_VER_TM2)) { - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; sys.demod_clk = Demod_Clk_250M; demod_status.tmp = Cry_mode; } - demod_status.ch_if = Si2176_5M_If * 1000; + demod_status.ch_if = SI2176_5M_IF * 1000; PR_DBG("[%s]adc_clk is %d,demod_clk is %d\n", __func__, sys.adc_clk, sys.demod_clk); autoFlagsTrig = 0; @@ -1404,9 +1404,9 @@ int Gxtv_Demod_Dvbt_Init(void) /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ demod_status.dvb_mode = Gxtv_Dvbt_Isdbt; - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; sys.demod_clk = Demod_Clk_60M; - demod_status.ch_if = Si2176_5M_If * 1000; + demod_status.ch_if = SI2176_5M_IF * 1000; demod_set_sys(&demod_status, &sys); demod_mode_para = AML_DVBT; @@ -1742,7 +1742,7 @@ static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe) else atsc_write_reg_v4(ATSC_DEMOD_REG_0X56, 0x0); - if (demod_status.adc_freq == Adc_Clk_24M) { + if (demod_status.adc_freq == ADC_CLK_24M) { atsc_write_reg_v4(ATSC_DEMOD_REG_0X54, 0x1aaaaa); @@ -2184,7 +2184,7 @@ int Gxtv_Demod_Atsc_Init(void/*struct aml_fe_dev *dev*/) memset(&demod_status, 0, sizeof(demod_status)); /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/ demod_status.dvb_mode = Gxtv_Atsc; - sys.adc_clk = Adc_Clk_24M; /*Adc_Clk_26M;*/ + sys.adc_clk = ADC_CLK_24M; /*Adc_Clk_26M;*/ if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) sys.demod_clk = Demod_Clk_250M; else @@ -2551,6 +2551,11 @@ static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe) struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct aml_demod_dtmb param; int times; + /*[0]: specturm inverse(1),normal(0); [1]:if_frequency*/ + unsigned int tuner_freq[2] = {0}; + + if (!demod_thread) + return 0; times = 2; PR_DBG("gxtv_demod_dtmb_set_frontend,freq is %d\n", c->frequency); @@ -2563,6 +2568,17 @@ static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe) msleep(100); /* demod_power_switch(PWR_ON); */ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency(fe, tuner_freq); + if (tuner_freq[0] == 0) + demod_status.spectrum = 0; + else if (tuner_freq[0] == 1) + demod_status.spectrum = 1; + else + pr_err("wrong specturm val get from tuner\n"); + } + dtmb_set_ch(&demod_status, /*&demod_i2c,*/ ¶m); return 0; @@ -2596,10 +2612,10 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev) sys.adc_clk = Adc_Clk_25M; sys.demod_clk = Demod_Clk_225M; } else if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) { - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; sys.demod_clk = Demod_Clk_250M; } else { - sys.adc_clk = Adc_Clk_24M; + sys.adc_clk = ADC_CLK_24M; sys.demod_clk = Demod_Clk_225M; } } else { @@ -2607,7 +2623,7 @@ int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev) return -1; } - demod_status.ch_if = Si2176_5M_If; + demod_status.ch_if = SI2176_5M_IF; demod_status.tmp = Adc_mode; demod_status.spectrum = dev->spectrum; /*demod_set_sys(&demod_status, &i2c, &sys);*/ diff --git a/drivers/amlogic/media/dtv_demod/atsc_func.c b/drivers/amlogic/media/dtv_demod/atsc_func.c index 1c1159624189..885223a22d12 100644 --- a/drivers/amlogic/media/dtv_demod/atsc_func.c +++ b/drivers/amlogic/media/dtv_demod/atsc_func.c @@ -827,15 +827,14 @@ int cci_run(void) int cfo_run(void) { - int crRate0, crRate1, crRate2, crRate; - int Fcent, Fs; - int cfo_sta, cr_peak_sta; - int i, j; + int cr_rate0, cr_rate1, cr_rate2, cr_rate; + int f_cent = SI2176_5M_IF * 1000;/* if */ + int fs = ADC_CLK_24M;/* crystal */ + int cfo_sta = UNLOCK, cr_peak_sta = UNLOCK; + unsigned int i, j; int sys_state; - int table_count; int max_count; int freq_table[] = {0, -50, 50, -100, 100, -150, 150}; - int scan_range; int Offset; int detec_cfo_times = 3; @@ -846,34 +845,35 @@ int cfo_run(void) max_count = 5; else max_count = 7; - /*for field test do 3 times*/ + + /* for field test do 3 times */ if (field_test_version) { max_count = 1; detec_cfo_times = 20; } - Fcent = Si2176_5M_If*1000;/*if*/ - Fs = Adc_Clk_24M;/*crystal*/ - cfo_sta = 0; - cr_peak_sta = 0; - table_count = 0; - scan_range = 10; - Offset = freq_table[table_count]; - PR_ATSC("Fcent[%d], Fs[%d]\n", Fcent, Fs); - for (i = -(scan_range-1); i <= scan_range+1; i++) { + + PR_ATSC("Fcent[%d], Fs[%d]\n", f_cent, fs); + + for (i = 0; i < 7; i++) { + if (i > (max_count - 1)) + return CFO_FAIL; + + Offset = freq_table[i]; atsc_reset(); - cfo_sta = UnLock; - cr_peak_sta = UnLock; - crRate = (1<<10)*(Fcent+Offset)/Fs; - crRate *= (1<<13); - crRate0 = crRate&0xff; - crRate1 = (crRate>>8)&0xff; - crRate2 = (crRate>>16)&0xff; + cfo_sta = UNLOCK; + cr_peak_sta = UNLOCK; + cr_rate = (1 << 10) * (f_cent + Offset) / fs; + cr_rate *= (1 << 13); + cr_rate0 = cr_rate & 0xff; + cr_rate1 = (cr_rate >> 8) & 0xff; + cr_rate2 = (cr_rate >> 16) & 0xff; /*set ddc init*/ - atsc_write_reg(0x70e, crRate0); - atsc_write_reg(0x70d, crRate1); - atsc_write_reg(0x70c, crRate2); + atsc_write_reg(0x70e, cr_rate0); + atsc_write_reg(0x70d, cr_rate1); + atsc_write_reg(0x70c, cr_rate2); PR_ATSC("[autoscan]crRate is %x, Offset is %dkhz\n ", - crRate, Offset); + cr_rate, Offset); + /*detec cfo signal*/ for (j = 0; j < detec_cfo_times; j++) { sys_state = read_atsc_fsm(); @@ -886,18 +886,18 @@ int cfo_run(void) } msleep(20); } - PR_ATSC("fsm[%x]cfo_sta is %d\n", - read_atsc_fsm(), cfo_sta); + PR_ATSC("fsm[%x]cfo_sta is %d\n", read_atsc_fsm(), cfo_sta); + /*detec cr peak signal*/ if (cfo_sta == Lock) { for (j = 0; j < cfo_times; j++) { sys_state = read_atsc_fsm(); - PR_ATSC("fsm[%x]in CR LOCK\n", read_atsc_fsm()); + PR_ATSC("fsm[%x]in CR LOCK\n", + read_atsc_fsm()); /*sys_state = (sys_state >> 4) & 0x0f;*/ if (sys_state >= CR_Peak_Lock) { cr_peak_sta = Lock; - PR_ATSC( - "fsm[%x][autoscan]cr peak lock\n", + PR_ATSC("fsm[0x%x]cr peak lock\n", read_atsc_fsm()); break; } else if (sys_state <= 20) { @@ -906,13 +906,9 @@ int cfo_run(void) } msleep(20); } - } else { - if (table_count >= (max_count-1)) - break; - table_count++; - Offset = freq_table[table_count]; + } else continue; - } + /*reset*/ if (cr_peak_sta == Lock) { /*atsc_reset();*/ @@ -920,17 +916,9 @@ int cfo_run(void) read_atsc_fsm()); return Cfo_Ok; - } else { - if (table_count >= (max_count-1)) { - PR_ATSC("cfo not lock,will try again\n"); - return Cfo_Fail; - - } - table_count++; - Offset = freq_table[table_count]; - } } + return 0; } @@ -1124,7 +1112,7 @@ void atsc_thread(void) time_table[1] = (time[2] - time[1]); PR_ATSC("fsm[%x][atsc_time]cfo done,cost %d ms,\n", read_atsc_fsm(), time_table[1]); - if (ret == Cfo_Fail) + if (ret == CFO_FAIL) return; if (cci_enable) ret = cci_run(); diff --git a/drivers/amlogic/media/dtv_demod/demod_func.c b/drivers/amlogic/media/dtv_demod/demod_func.c index 361bd32cf9dc..7f815e5536e3 100644 --- a/drivers/amlogic/media/dtv_demod/demod_func.c +++ b/drivers/amlogic/media/dtv_demod/demod_func.c @@ -133,7 +133,7 @@ void adc_dpll_setup(int clk_a, int clk_b, int clk_sys, int dvb_mode) int sts_pll; if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) { - if (clk_b == Adc_Clk_24M) { + if (clk_b == ADC_CLK_24M) { dtvpll_init_flag(1); return; } else if (clk_b == Adc_Clk_25M) { diff --git a/drivers/amlogic/media/dtv_demod/dtmb_func.c b/drivers/amlogic/media/dtv_demod/dtmb_func.c index 0dae73207618..746ec98acace 100644 --- a/drivers/amlogic/media/dtv_demod/dtmb_func.c +++ b/drivers/amlogic/media/dtv_demod/dtmb_func.c @@ -94,9 +94,87 @@ void dtmb_clk_set(unsigned int adc_clk) } #endif +static void dtmb_24m_coeff(void) +{ + #if 0 + dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0xf230ee02); + dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x0be241ed); + dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x0306031d); + dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x051d191c); + dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x171a0308); + dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x0b071d); + dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x3d333703); + dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x33030f0a); + dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x140f3c2f); + dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x292d04); + dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x041c177c); + dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x247c5e64); + dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x2b); + dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xc8d104); + dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x0431fc); + dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x51); + dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x392004); + dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x372); + dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x1187fc); + dtmb_write_reg(DTMB_FRONT_ACF_BYPASS, + ((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff) + | 0x2af236)); + #else + dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0xebd2530d); + dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x04dad364); + dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x181e0508); + dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x080a031a); + dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x0217161f); + dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x000c0c); + dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x0e3f3334); + dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x2e330310); + dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x08160f3c); + dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x352731); + dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x70101f11); + dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x2d126b5c); + dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x1f); + dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xd4c8ef); + dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x04e013); + dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x46); + dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x3883ee); + dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x37e); + dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x123013); + dtmb_write_reg(DTMB_FRONT_ACF_BYPASS, + ((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff) + | 0x29922b)); + #endif +} + +static void dtmb_25m_coeff(void) +{ + dtmb_write_reg(DTMB_FRONT_COEF_SET19, 0x242fde12); + dtmb_write_reg(DTMB_FRONT_COEF_SET18, 0x451dce); + dtmb_write_reg(DTMB_FRONT_COEF_SET17, 0x051f1a1b); + dtmb_write_reg(DTMB_FRONT_COEF_SET16, 0x181c0307); + dtmb_write_reg(DTMB_FRONT_COEF_SET15, 0x0809031b); + dtmb_write_reg(DTMB_FRONT_COEF_SET14, 0x15161f); + dtmb_write_reg(DTMB_FRONT_COEF_SET13, 0x060e0a3e); + dtmb_write_reg(DTMB_FRONT_COEF_SET12, 0x06363038); + dtmb_write_reg(DTMB_FRONT_COEF_SET11, 0x2d3e0f12); + dtmb_write_reg(DTMB_FRONT_COEF_SET10, 0x133c2b); + dtmb_write_reg(DTMB_FRONT_COEF_SET9, 0x5f700c1b); + dtmb_write_reg(DTMB_FRONT_COEF_SET8, 0x23270b6a); + dtmb_write_reg(DTMB_FRONT_COEF_SET7, 0x7e); + dtmb_write_reg(DTMB_FRONT_COEF_SET6, 0xf3cbd4); + dtmb_write_reg(DTMB_FRONT_COEF_SET5, 0x04f031); + dtmb_write_reg(DTMB_FRONT_COEF_SET4, 0x29); + dtmb_write_reg(DTMB_FRONT_COEF_SET3, 0x37f3cc); + dtmb_write_reg(DTMB_FRONT_COEF_SET2, 0x396); + dtmb_write_reg(DTMB_FRONT_COEF_SET1, 0x131036); + dtmb_write_reg(DTMB_FRONT_ACF_BYPASS, + ((dtmb_read_reg(DTMB_FRONT_ACF_BYPASS) & ~0xffffff) + | 0x274217)); +} + void dtmb_all_reset(void) { int temp_data = 0; + unsigned int reg_val; if (is_ic_ver(IC_VER_TXL)) { /*fix bug 139044: DTMB lost sync*/ @@ -139,22 +217,41 @@ void dtmb_all_reset(void) /*fix agc problem,skip warm_up status*/ dtmb_write_reg(DTMB_FRONT_46_CONFIG, 0x1a000f0f); dtmb_write_reg(DTMB_FRONT_ST_FREQ, 0xf2400000); - dtmb_clk_set(Adc_Clk_24M); + dtmb_clk_set(ADC_CLK_24M); } else if (is_ic_ver(IC_VER_TL1) || is_ic_ver(IC_VER_TM2)) { - if (demod_get_adc_clk() == Adc_Clk_24M) { + if (demod_get_adc_clk() == ADC_CLK_24M) { dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, 0x6aaaaa); dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, 0x13196596); dtmb_write_reg(0x5b << 2, 0x50a30a25); + dtmb_24m_coeff(); } else if (demod_get_adc_clk() == Adc_Clk_25M) { dtmb_write_reg(DTMB_FRONT_DDC_BYPASS, 0x62c1a5); dtmb_write_reg(DTMB_FRONT_SRC_CONFIG1, 0x131a747d); dtmb_write_reg(0x5b << 2, 0x4d6a0a25); + dtmb_25m_coeff(); } - /*for timeshift mosaic issue*/ - dtmb_write_reg(0x4e << 2, 0x256cf604); - /*delay fec lock to prevent eq is confused by signal*/ - dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x5680000); + /*for timeshift mosaic issue + *bit 30:ts_sync_sel,0=ts_sync,1=searched ts_sync + */ + dtmb_write_reg(DTMB_FRONT_4e_CONFIG, 0x656cf604); + + /*delay fec lock & make fec lost faster + *to prevent eq is confused by signal + */ + dtmb_write_reg(DTMB_FRONT_DEBUG_CFG, 0x5480000); + /*reduce fec lost timeout*/ + dtmb_write_reg(DTMB_FRONT_19_CONFIG, 0x30); + + reg_val = dtmb_read_reg(DTMB_TOP_CTRL_TPS); + /* for Task 19:Switch mode and modulation parameters test + * dtmb_spectrum: 0=normal, 1=inverted + */ + if (dtmb_spectrum == 0) + reg_val |= 0x4; + else if (dtmb_spectrum == 1) + reg_val &= ~0x4; + dtmb_write_reg(DTMB_TOP_CTRL_TPS, reg_val); } else { dtmb_write_reg(DTMB_FRONT_AGC_CONFIG1, 0x10127); dtmb_write_reg(DTMB_CHE_IBDFE_CONFIG6, 0x943228cc); diff --git a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_front.h b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_front.h index d8cd73976919..196af755fda9 100644 --- a/drivers/amlogic/media/dtv_demod/include/addr_dtmb_front.h +++ b/drivers/amlogic/media/dtv_demod/include/addr_dtmb_front.h @@ -22,47 +22,48 @@ #define DTMB_FRONT_ADDR(x) (DTMB_DEMOD_BASE + (x << 2)) -#define DTMB_FRONT_AFIFO_ADC DTMB_FRONT_ADDR(0x20) -#define DTMB_FRONT_AGC_CONFIG1 DTMB_FRONT_ADDR(0x21) -#define DTMB_FRONT_AGC_CONFIG2 DTMB_FRONT_ADDR(0x22) -#define DTMB_FRONT_AGC_CONFIG3 DTMB_FRONT_ADDR(0x23) -#define DTMB_FRONT_AGC_CONFIG4 DTMB_FRONT_ADDR(0x24) -#define DTMB_FRONT_DDC_BYPASS DTMB_FRONT_ADDR(0x25) -#define DTMB_FRONT_DC_HOLD DTMB_FRONT_ADDR(0x28) -#define DTMB_FRONT_DAGC_TARGET_POWER DTMB_FRONT_ADDR(0x29) -#define DTMB_FRONT_ACF_BYPASS DTMB_FRONT_ADDR(0x2a) -#define DTMB_FRONT_COEF_SET1 DTMB_FRONT_ADDR(0x2b) -#define DTMB_FRONT_COEF_SET2 DTMB_FRONT_ADDR(0x2c) -#define DTMB_FRONT_COEF_SET3 DTMB_FRONT_ADDR(0x2d) -#define DTMB_FRONT_COEF_SET4 DTMB_FRONT_ADDR(0x2e) -#define DTMB_FRONT_COEF_SET5 DTMB_FRONT_ADDR(0x2f) -#define DTMB_FRONT_COEF_SET6 DTMB_FRONT_ADDR(0x30) -#define DTMB_FRONT_COEF_SET7 DTMB_FRONT_ADDR(0x31) -#define DTMB_FRONT_COEF_SET8 DTMB_FRONT_ADDR(0x32) -#define DTMB_FRONT_COEF_SET9 DTMB_FRONT_ADDR(0x33) -#define DTMB_FRONT_COEF_SET10 DTMB_FRONT_ADDR(0x34) -#define DTMB_FRONT_COEF_SET11 DTMB_FRONT_ADDR(0x35) -#define DTMB_FRONT_COEF_SET12 DTMB_FRONT_ADDR(0x36) -#define DTMB_FRONT_COEF_SET13 DTMB_FRONT_ADDR(0x37) -#define DTMB_FRONT_COEF_SET14 DTMB_FRONT_ADDR(0x38) -#define DTMB_FRONT_COEF_SET15 DTMB_FRONT_ADDR(0x39) -#define DTMB_FRONT_COEF_SET16 DTMB_FRONT_ADDR(0x3a) -#define DTMB_FRONT_COEF_SET17 DTMB_FRONT_ADDR(0x3b) -#define DTMB_FRONT_COEF_SET18 DTMB_FRONT_ADDR(0x3c) -#define DTMB_FRONT_COEF_SET19 DTMB_FRONT_ADDR(0x3d) -#define DTMB_FRONT_SRC_CONFIG1 DTMB_FRONT_ADDR(0x3e) -#define DTMB_FRONT_SRC_CONFIG2 DTMB_FRONT_ADDR(0x3f) -#define DTMB_FRONT_SFIFO_OUT_LEN DTMB_FRONT_ADDR(0x40) -#define DTMB_FRONT_DAGC_GAIN DTMB_FRONT_ADDR(0x41) -#define DTMB_FRONT_IQIB_STEP DTMB_FRONT_ADDR(0x42) -#define DTMB_FRONT_IQIB_CONFIG DTMB_FRONT_ADDR(0x43) -#define DTMB_FRONT_ST_CONFIG DTMB_FRONT_ADDR(0x44) -#define DTMB_FRONT_ST_FREQ DTMB_FRONT_ADDR(0x45) -#define DTMB_FRONT_46_CONFIG DTMB_FRONT_ADDR(0x46) -#define DTMB_FRONT_47_CONFIG DTMB_FRONT_ADDR(0x47) -#define DTMB_FRONT_DEBUG_CFG DTMB_FRONT_ADDR(0x48) -#define DTMB_FRONT_MEM_ADDR DTMB_FRONT_ADDR(0x49) -#define DTMB_FRONT_19_CONFIG DTMB_FRONT_ADDR(0x19) -#define DTMB_FRONT_4d_CONFIG DTMB_FRONT_ADDR(0x4d) +#define DTMB_FRONT_19_CONFIG DTMB_FRONT_ADDR(0x19) +#define DTMB_FRONT_AFIFO_ADC DTMB_FRONT_ADDR(0x20) +#define DTMB_FRONT_AGC_CONFIG1 DTMB_FRONT_ADDR(0x21) +#define DTMB_FRONT_AGC_CONFIG2 DTMB_FRONT_ADDR(0x22) +#define DTMB_FRONT_AGC_CONFIG3 DTMB_FRONT_ADDR(0x23) +#define DTMB_FRONT_AGC_CONFIG4 DTMB_FRONT_ADDR(0x24) +#define DTMB_FRONT_DDC_BYPASS DTMB_FRONT_ADDR(0x25) +#define DTMB_FRONT_DC_HOLD DTMB_FRONT_ADDR(0x28) +#define DTMB_FRONT_DAGC_TARGET_POWER DTMB_FRONT_ADDR(0x29) +#define DTMB_FRONT_ACF_BYPASS DTMB_FRONT_ADDR(0x2a) +#define DTMB_FRONT_COEF_SET1 DTMB_FRONT_ADDR(0x2b) +#define DTMB_FRONT_COEF_SET2 DTMB_FRONT_ADDR(0x2c) +#define DTMB_FRONT_COEF_SET3 DTMB_FRONT_ADDR(0x2d) +#define DTMB_FRONT_COEF_SET4 DTMB_FRONT_ADDR(0x2e) +#define DTMB_FRONT_COEF_SET5 DTMB_FRONT_ADDR(0x2f) +#define DTMB_FRONT_COEF_SET6 DTMB_FRONT_ADDR(0x30) +#define DTMB_FRONT_COEF_SET7 DTMB_FRONT_ADDR(0x31) +#define DTMB_FRONT_COEF_SET8 DTMB_FRONT_ADDR(0x32) +#define DTMB_FRONT_COEF_SET9 DTMB_FRONT_ADDR(0x33) +#define DTMB_FRONT_COEF_SET10 DTMB_FRONT_ADDR(0x34) +#define DTMB_FRONT_COEF_SET11 DTMB_FRONT_ADDR(0x35) +#define DTMB_FRONT_COEF_SET12 DTMB_FRONT_ADDR(0x36) +#define DTMB_FRONT_COEF_SET13 DTMB_FRONT_ADDR(0x37) +#define DTMB_FRONT_COEF_SET14 DTMB_FRONT_ADDR(0x38) +#define DTMB_FRONT_COEF_SET15 DTMB_FRONT_ADDR(0x39) +#define DTMB_FRONT_COEF_SET16 DTMB_FRONT_ADDR(0x3a) +#define DTMB_FRONT_COEF_SET17 DTMB_FRONT_ADDR(0x3b) +#define DTMB_FRONT_COEF_SET18 DTMB_FRONT_ADDR(0x3c) +#define DTMB_FRONT_COEF_SET19 DTMB_FRONT_ADDR(0x3d) +#define DTMB_FRONT_SRC_CONFIG1 DTMB_FRONT_ADDR(0x3e) +#define DTMB_FRONT_SRC_CONFIG2 DTMB_FRONT_ADDR(0x3f) +#define DTMB_FRONT_SFIFO_OUT_LEN DTMB_FRONT_ADDR(0x40) +#define DTMB_FRONT_DAGC_GAIN DTMB_FRONT_ADDR(0x41) +#define DTMB_FRONT_IQIB_STEP DTMB_FRONT_ADDR(0x42) +#define DTMB_FRONT_IQIB_CONFIG DTMB_FRONT_ADDR(0x43) +#define DTMB_FRONT_ST_CONFIG DTMB_FRONT_ADDR(0x44) +#define DTMB_FRONT_ST_FREQ DTMB_FRONT_ADDR(0x45) +#define DTMB_FRONT_46_CONFIG DTMB_FRONT_ADDR(0x46) +#define DTMB_FRONT_47_CONFIG DTMB_FRONT_ADDR(0x47) +#define DTMB_FRONT_DEBUG_CFG DTMB_FRONT_ADDR(0x48) +#define DTMB_FRONT_MEM_ADDR DTMB_FRONT_ADDR(0x49) +#define DTMB_FRONT_4d_CONFIG DTMB_FRONT_ADDR(0x4d) +#define DTMB_FRONT_4e_CONFIG DTMB_FRONT_ADDR(0x4e) #endif diff --git a/drivers/amlogic/media/dtv_demod/include/amlfrontend.h b/drivers/amlogic/media/dtv_demod/include/amlfrontend.h index 701532d573c9..affdaa3acc1a 100644 --- a/drivers/amlogic/media/dtv_demod/include/amlfrontend.h +++ b/drivers/amlogic/media/dtv_demod/include/amlfrontend.h @@ -29,8 +29,8 @@ struct amlfe_config { int tuner_addr; }; enum Gxtv_Demod_Tuner_If { - Si2176_5M_If = 5, - Si2176_6M_If = 6 + SI2176_5M_IF = 5, + SI2176_6M_IF = 6 }; /* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC */ enum Gxtv_Demod_Dvb_Mode { @@ -54,7 +54,7 @@ enum demod_md { #define Adc_Clk_35M 35714 /* adc clk dvbc */ #define Demod_Clk_71M 71428 /* demod clk */ -#define Adc_Clk_24M 24000 +#define ADC_CLK_24M 24000 #define Demod_Clk_72M 72000 #define Demod_Clk_60M 60000 diff --git a/drivers/amlogic/media/dtv_demod/include/atsc_func.h b/drivers/amlogic/media/dtv_demod/include/atsc_func.h index 5ead9ab63cb9..7d084743d5ed 100644 --- a/drivers/amlogic/media/dtv_demod/include/atsc_func.h +++ b/drivers/amlogic/media/dtv_demod/include/atsc_func.h @@ -36,9 +36,9 @@ enum atsc_performance { }; #define Lock 1 -#define UnLock 0 +#define UNLOCK 0 #define Cfo_Ok 1 -#define Cfo_Fail 0 +#define CFO_FAIL 0 #define Dagc_Open 1 #define Dagc_Close 0 #define Atsc_BandWidth (6000) diff --git a/drivers/amlogic/media/frame_sync/ptsserv.c b/drivers/amlogic/media/frame_sync/ptsserv.c index 7571ccbd8c2c..615a408c59b0 100644 --- a/drivers/amlogic/media/frame_sync/ptsserv.c +++ b/drivers/amlogic/media/frame_sync/ptsserv.c @@ -503,6 +503,7 @@ static int pts_checkin_offset_inline(u8 type, u32 offset, u32 val, u64 uS64) #ifdef CALC_CACHED_TIME pts_checkin_offset_calc_cached(offset, val, pTable); #endif + timestamp_clac_pts_latency(type, val); list_move_tail(&rec->list, &pTable->valid_list); @@ -515,7 +516,7 @@ static int pts_checkin_offset_inline(u8 type, u32 offset, u32 val, u64 uS64) if (tsync_get_debug_apts() && (type == PTS_TYPE_AUDIO)) pr_info("init apts[%d] at 0x%x\n", type, val); - if (type == PTS_TYPE_VIDEO) + if (type == PTS_TYPE_VIDEO && !tsync_get_tunnel_mode()) timestamp_vpts_set(val); else if (type == PTS_TYPE_AUDIO) timestamp_apts_set(val); @@ -566,7 +567,8 @@ int pts_checkin_wrptr(u8 type, u32 ptr, u32 val) get_wrpage_offset(type, &page, &cur_offset); page_no = (offset > cur_offset) ? (page - 1) : page; - + if (type == PTS_TYPE_VIDEO) + val += tsync_get_vpts_adjust(); return pts_checkin_offset(type, pts_table[type].buf_size * page_no + offset, val); diff --git a/drivers/amlogic/media/frame_sync/timestamp.c b/drivers/amlogic/media/frame_sync/timestamp.c index 25db7ce19224..f21bab7087bc 100644 --- a/drivers/amlogic/media/frame_sync/timestamp.c +++ b/drivers/amlogic/media/frame_sync/timestamp.c @@ -43,6 +43,8 @@ static u32 first_apts; static u32 pcrscr_lantcy = 200*90; static u32 video_pts; static u32 audio_pts; +static u32 last_apts_gap; +static u32 last_vpts_gap; static u32 system_time_scale_base = 1; static u32 system_time_scale_remainder; @@ -123,7 +125,7 @@ EXPORT_SYMBOL(timestamp_apts_started); u32 timestamp_pcrscr_get(void) { - if (tsync_get_mode() == TSYNC_MODE_AMASTER) + if (tsync_get_mode() != TSYNC_MODE_PCRMASTER) return system_time; if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb()) { @@ -150,6 +152,8 @@ void timestamp_set_pcrlatency(u32 latency) { if (latency < 500 * 90) pcrscr_lantcy = latency; + else + pcrscr_lantcy = 500 * 90; } EXPORT_SYMBOL(timestamp_set_pcrlatency); @@ -159,6 +163,102 @@ u32 timestamp_get_pcrlatency(void) } EXPORT_SYMBOL(timestamp_get_pcrlatency); +void timestamp_clac_pts_latency(u8 type, u32 pts) +{ + u32 demux_pcr = 0; + u32 t1, t2, pts_diff; + + if (tsync_get_mode() != TSYNC_MODE_PCRMASTER) + return; + if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() + && tsync_pcr_demux_pcr_used()) { + if (tsdemux_pcrscr_get_cb) + demux_pcr = tsdemux_pcrscr_get_cb(); + else + return; + if (demux_pcr == 0 || + demux_pcr == 0xffffffff) { + last_apts_gap = 0; + last_vpts_gap = 0; + return; + } + if (type == 0) { + if (demux_pcr > pts) { + last_vpts_gap = 0; + return; + } + pts_diff = pts - demux_pcr; + if (pts_diff > 500 * 90) + return; + t1 = ((last_vpts_gap >> 16) & 0xff); + if (t1 > 5) + t1 = 0; + t2 = (last_vpts_gap & 0xffff); + if (t2 == 0) { + last_vpts_gap = pts_diff; + return; + } + if (abs(t2 - pts_diff) < 30 * 90) { + last_vpts_gap = t2; + return; + } + t1++; + if (t1 >= 5) + last_vpts_gap = pts_diff; + else + last_vpts_gap = ((t1 << 16) | t2); + } else if (type == 1) { + if (demux_pcr > pts) { + last_apts_gap = 0; + return; + } + pts_diff = pts - demux_pcr; + if (pts_diff > 500 * 90) + return; + t1 = ((last_apts_gap >> 16) & 0xff); + if (t1 > 5) + t1 = 0; + t2 = (last_apts_gap & 0xffff); + if (t2 == 0) { + last_apts_gap = pts_diff; + return; + } + if (abs(t2 - pts_diff) < 30 * 90) { + last_apts_gap = t2; + return; + } + t1++; + if (t1 >= 5) + last_apts_gap = pts_diff; + else + last_apts_gap = ((t1 << 16) | t2); + } + } else { + last_apts_gap = 0; + last_vpts_gap = 0; + } +} +EXPORT_SYMBOL(timestamp_clac_pts_latency); + +u32 timestamp_get_pts_latency(u8 type) +{ + if (type == 0) + return (last_vpts_gap & 0xffff); + else if (type == 1) + return (last_apts_gap & 0xffff); + return 0; +} +EXPORT_SYMBOL(timestamp_get_pts_latency); + +void timestamp_clean_pts_latency(u8 type) +{ + if (type == 0) + last_vpts_gap = 0; + else if (type == 1) + last_apts_gap = 0; +} +EXPORT_SYMBOL(timestamp_clean_pts_latency); + u32 timestamp_tsdemux_pcr_get(void) { if (tsdemux_pcrscr_get_cb) @@ -193,6 +293,7 @@ void timestamp_checkin_firstvpts_set(u32 pts) { first_checkin_vpts = pts; pr_info("video first checkin pts = %x\n", first_checkin_vpts); + timestamp_clean_pts_latency(0); } EXPORT_SYMBOL(timestamp_checkin_firstvpts_set); @@ -200,6 +301,7 @@ void timestamp_checkin_firstapts_set(u32 pts) { first_checkin_apts = pts; pr_info("audio first checkin pts =%x\n", first_checkin_apts); + timestamp_clean_pts_latency(1); } EXPORT_SYMBOL(timestamp_checkin_firstapts_set); diff --git a/drivers/amlogic/media/frame_sync/tsync.c b/drivers/amlogic/media/frame_sync/tsync.c index 64fc4641f0da..998e78701f21 100644 --- a/drivers/amlogic/media/frame_sync/tsync.c +++ b/drivers/amlogic/media/frame_sync/tsync.c @@ -214,6 +214,7 @@ static int tsync_dec_reset_flag; static int tsync_dec_reset_video_start; static int tsync_automute_on; static int tsync_video_started; +static int is_tunnel_mode; static int debug_pts_checkin; static int debug_pts_checkout; @@ -745,6 +746,7 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) switch (event) { case VIDEO_START: tsync_video_started = 1; + tsync_set_av_state(0, 2); //set tsync mode to vmaster to avoid video block caused // by avpts-diff too much @@ -802,6 +804,7 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) case VIDEO_STOP: tsync_stat = TSYNC_STAT_PCRSCR_SETUP_NONE; + tsync_set_av_state(0, 3); timestamp_vpts_set(0); timestamp_pcrscr_set(0); timestamp_pcrscr_enable(0); @@ -947,6 +950,7 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) break; case AUDIO_START: /* reset discontinue var */ + tsync_set_av_state(1, AUDIO_START); tsync_set_sync_adiscont(0); tsync_set_sync_adiscont_diff(0); tsync_set_sync_vdiscont(0); @@ -1009,6 +1013,7 @@ void tsync_avevent_locked(enum avevent_e event, u32 param) break; case AUDIO_STOP: + tsync_set_av_state(1, AUDIO_STOP); timestamp_apts_enable(0); timestamp_apts_set(-1); tsync_abreak = 0; @@ -1201,6 +1206,11 @@ int tsync_set_apts(unsigned int pts) unsigned int oldpts = timestamp_apts_get(); int oldmod = tsync_mode; + if (tsync_mode == TSYNC_MODE_PCRMASTER) { + tsync_pcr_set_apts(pts); + return 0; + } + if (tsync_abreak) tsync_abreak = 0; if (!tsync_enable) { @@ -1238,7 +1248,7 @@ int tsync_set_apts(unsigned int pts) t = timestamp_pcrscr_get(); if (tsync_mode == TSYNC_MODE_AMASTER) { - /* special used for Dolby Certification AVSync test */ + /* special used for Dobly Certification AVSync test */ if (dobly_avsync_test) { if (get_vsync_pts_inc_mode() && @@ -1432,6 +1442,18 @@ int tsync_set_startsync_mode(int mode) } EXPORT_SYMBOL(tsync_set_startsync_mode); +int tsync_set_tunnel_mode(int mode) +{ + return is_tunnel_mode = mode; +} +EXPORT_SYMBOL(tsync_set_tunnel_mode); + +int tsync_get_tunnel_mode(void) +{ + return is_tunnel_mode; +} +EXPORT_SYMBOL(tsync_get_tunnel_mode); + bool tsync_check_vpts_discontinuity(unsigned int vpts) { unsigned int systemtime; @@ -1731,11 +1753,8 @@ static ssize_t show_discontinue(struct class *class, { pts_discontinue = vpts_discontinue || apts_discontinue; if (pts_discontinue) { - sprintf(buf, "1: pts_discontinue, "); - sprintf(buf, "%sapts_discontinue_diff=%d, ", - buf, apts_discontinue_diff); - return sprintf(buf, "%svpts_discontinue_diff=%d,\n", - buf, vpts_discontinue_diff); + return sprintf(buf, "apts diff %d, vpts diff=%d\n", + apts_discontinue_diff, vpts_discontinue_diff); } return sprintf(buf, "0: pts_continue\n"); diff --git a/drivers/amlogic/media/frame_sync/tsync_pcr.c b/drivers/amlogic/media/frame_sync/tsync_pcr.c index 695a0bb6ebea..63cb9407ab6a 100644 --- a/drivers/amlogic/media/frame_sync/tsync_pcr.c +++ b/drivers/amlogic/media/frame_sync/tsync_pcr.c @@ -197,6 +197,20 @@ static u32 tsync_demux_last_pcr; static u32 tsync_demux_pcr_discontinue_count; static u32 tsync_demux_pcr_continue_count; +static int tsync_vpts_adjust; +static u32 tsync_disable_demux_pcr; +static u32 tsync_audio_mode; +static u32 tsync_audio_state; +static u32 tsync_video_state; +static int tsync_audio_discontinue; +static int tsync_audio_continue_count; +static u32 tsync_video_continue_count; +static u32 last_discontinue_checkin_apts; +static u32 last_pcr_checkin_apts; +static u32 last_pcr_checkin_vpts; +static u32 last_pcr_checkin_apts_count; +static u32 last_pcr_checkin_vpts_count; + static DEFINE_SPINLOCK(tsync_pcr_lock); @@ -326,6 +340,36 @@ u32 tsync_pcr_get_min_checkinpts(void) } EXPORT_SYMBOL(tsync_pcr_get_min_checkinpts); +static void tsync_set_pcr_mode(int mode, u32 param) +{ + if (tsync_pcr_debug & 0x03) { + pr_info("tsync_use_demux_pcr: %d to %d\n", + tsync_use_demux_pcr, mode); + } + if (mode == 0) { + tsync_use_demux_pcr = 0; + timestamp_pcrscr_set(param); + timestamp_pcrscr_enable(1); + timestamp_vpts_set(param); + } else if (mode == 1) { + tsync_use_demux_pcr = 1; + timestamp_pcrscr_enable(0); + } +} + +void tsync_set_av_state(u8 type, int state) +{ + if (type == 0) { + tsync_video_state = state; + return; + } else if (type == 1) { + tsync_audio_state = state; + if ((tsync_pcr_debug & 0x01) && state == AUDIO_STOP) + pr_info("audio stopped!\n"); + } +} +EXPORT_SYMBOL(tsync_set_av_state); + void tsync_pcr_pcrscr_set(void) { u32 first_pcr = 0, first_vpts = 0, first_apts = 0; @@ -343,6 +387,10 @@ void tsync_pcr_pcrscr_set(void) first_pcr = tsdemux_first_pcrscr_get_cb(); first_apts = timestamp_firstapts_get(); first_vpts = timestamp_firstvpts_get(); + if (!first_apts) + first_apts = timestamp_checkin_firstapts_get(); + if (!first_vpts) + first_vpts = timestamp_checkin_firstvpts_get(); cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); min_checkinpts = tsync_pcr_get_min_checkinpts(); @@ -361,66 +409,81 @@ void tsync_pcr_pcrscr_set(void) pr_info("now and the cur_checkin_apts is %x\n ", cur_checkin_apts); } - + if ((!cur_checkin_vpts || cur_checkin_vpts == 0xffffffff) && + first_vpts) + cur_checkin_vpts = first_vpts; + if ((!cur_checkin_apts || cur_checkin_apts == 0xffffffff) && + first_apts) + cur_checkin_apts = first_apts; + if (tsync_pcr_debug & 0x01) { + pr_info("check first_pcr=%x,first_apts=%x,first_vpts %x\n", + first_pcr, first_apts, first_vpts); + pr_info("cur_pcr=%x,checkin_apts=%x,checkin_vpts=%x\n", + cur_pcr, cur_checkin_apts, cur_checkin_vpts); + pr_info("gap_pa=%d,gap_pv=%d,gap_av=%d\n", + (int)(cur_pcr - cur_checkin_apts) / 90, + (int)(cur_pcr - cur_checkin_vpts) / 90, + (int)(cur_checkin_apts - cur_checkin_vpts) / 90); + pr_info("alevel=%d vlevel=%d\n", + abuf_level, vbuf_level); + } /* check the valid of the pcr */ if (cur_pcr && cur_checkin_vpts && cur_checkin_apts && cur_checkin_vpts != 0xffffffff && - cur_checkin_apts != 0xffffffff) { + cur_checkin_apts != 0xffffffff && + !(tsync_pcr_inited_flag & complete_init_flag)) { u32 gap_pa, gap_pv, gap_av; gap_pa = abs(cur_pcr - cur_checkin_apts); gap_av = abs(cur_checkin_apts - cur_checkin_vpts); gap_pv = abs(cur_pcr - cur_checkin_vpts); - if ((gap_pa > MAX_GAP) && (gap_pv > MAX_GAP)) - cur_pcr = 0; + if ((gap_pa > MAX_GAP) && (gap_pv > MAX_GAP)) { + if (gap_av > MAX_GAP) + ref_pcr = cur_checkin_vpts; + else + ref_pcr = min_checkinpts - + tsync_pcr_ref_latency; + tsync_set_pcr_mode(0, ref_pcr); + tsync_pcr_inited_mode = + INIT_PRIORITY_VIDEO; + tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_VPTS; + pr_info("tsync_set:pcrsrc %x,vpts %x, mode %d\n", + timestamp_pcrscr_get(), timestamp_vpts_get(), + tsync_use_demux_pcr); + return; + } } /* decide use which para to init */ if (cur_pcr && !(tsync_pcr_inited_flag & complete_init_flag) && (min_checkinpts != 0)) { tsync_pcr_inited_flag |= TSYNC_PCR_INITCHECK_PCR; - if (tsync_pcr_debug&0x02) - pr_info("cur_pcr=%x min_checkinpts=%x\n", - cur_pcr, min_checkinpts); - if ((abs(cur_pcr - min_checkinpts) > + if ((abs(cur_pcr - cur_checkin_vpts) > PLAY_PCR_INVALID_THRESHOLD) && - min_checkinpts != 0xffffffff) { - ref_pcr = min_checkinpts; - tsync_use_demux_pcr = 0; - tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; - if (tsync_pcr_debug&0x01) { - pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ", - first_pcr, first_apts); - pr_info("first_vpts=0x%x, cur_pcr = 0x%x, checkin_vpts=0x%x, ", - first_vpts, cur_pcr, cur_checkin_vpts); - pr_info("checkin_apts=0x%x alevel=%d vlevel=%d\n", - cur_checkin_apts, abuf_level, vbuf_level); - pr_info("[%d]init by pcr. pcr=%x usepcr=%d\n", - __LINE__, ref_pcr, tsync_pcr_usepcr); - } - } else { - ref_pcr = timestamp_pcrscr_get(); - ref_pcr = timestamp_pcrscr_get(); - if (cur_pcr > min_checkinpts) { - ref_pcr = min_checkinpts - + cur_checkin_vpts != 0xffffffff) { + ref_pcr = cur_checkin_vpts - tsync_pcr_ref_latency; - timestamp_pcrscr_set(ref_pcr); - timestamp_pcrscr_enable(1); - tsync_use_demux_pcr = 0; - if (cur_checkin_vpts == 0xffffffff) - tsync_pcr_inited_mode = - INIT_PRIORITY_AUDIO; - else - tsync_pcr_inited_mode = - INIT_PRIORITY_VIDEO; - } else { - tsync_use_demux_pcr = 1; - tsync_pcr_inited_mode = INIT_PRIORITY_PCR; - } + tsync_set_pcr_mode(0, ref_pcr); + tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; + } else if (((cur_pcr > min_checkinpts) && + (cur_pcr - min_checkinpts) > 500 * 90) || + tsync_disable_demux_pcr == 1) { + if (abs(cur_checkin_apts - cur_checkin_vpts) + > MAX_GAP) + ref_pcr = cur_checkin_vpts - + tsync_pcr_ref_latency; + else + ref_pcr = min_checkinpts; + tsync_set_pcr_mode(0, ref_pcr); + tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; + } else { + tsync_set_pcr_mode(1, ref_pcr); + tsync_pcr_inited_mode = INIT_PRIORITY_PCR; } - pr_info("tsync set:pcrsrc %x,vpts %x,mode %d\n", + pr_info("tsync_set:pcrsrc %x,vpts %x,mode-%d\n", timestamp_pcrscr_get(), timestamp_firstvpts_get(), tsync_use_demux_pcr); if (tsdemux_pcrscr_get_cb) init_check_first_demuxpcr = tsdemux_pcrscr_get_cb(); + return; } if (first_apts && !(tsync_pcr_inited_flag & complete_init_flag) @@ -455,8 +518,9 @@ void tsync_pcr_pcrscr_set(void) timestamp_firstvpts_get()); } } - timestamp_pcrscr_set(ref_pcr); - timestamp_pcrscr_enable(1); + ref_pcr = tsync_pcr_get_min_checkinpts(); + tsync_set_pcr_mode(0, ref_pcr); + tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; init_check_first_systemtime = ref_pcr; if (tsdemux_pcrscr_get_cb) init_check_first_demuxpcr = tsdemux_pcrscr_get_cb(); @@ -497,8 +561,9 @@ void tsync_pcr_pcrscr_set(void) timestamp_firstvpts_get()); } } - timestamp_pcrscr_set(ref_pcr); - timestamp_pcrscr_enable(1); + ref_pcr = tsync_pcr_get_min_checkinpts(); + tsync_set_pcr_mode(0, ref_pcr); + tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; } } @@ -601,29 +666,13 @@ static u8 tsync_process_checkspeed(void) return tsync_last_play_mode; } -static void tsync_set_pcr_mode(int mode, u32 param) -{ - if (tsync_pcr_debug & 0x03) { - pr_info("tsync_use_demux_pcr: %d to %d\n", - tsync_use_demux_pcr, mode); - } - if (mode == 0) { - tsync_use_demux_pcr = 0; - timestamp_pcrscr_set(param); - timestamp_pcrscr_enable(1); - timestamp_vpts_set(param); - } else if (mode == 1) { - tsync_use_demux_pcr = 1; - timestamp_pcrscr_enable(0); - } -} - static void tsync_process_discontinue(void) { u32 cur_vpts = timestamp_vpts_get(); u32 cur_tsdemuxpcr = 0; u32 ref_pcr = 0, tsdemux_pcr_diff; u32 cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); + u32 cur_checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); if (tsdemux_pcrscr_get_cb && (tsync_demux_last_pcr == 0 || tsync_demux_last_pcr == 0xffffffff)) @@ -637,7 +686,12 @@ static void tsync_process_discontinue(void) if (tsync_pcr_inited_mode != INIT_PRIORITY_PCR) { if ((tsync_pcr_tsdemuxpcr_discontinue & VIDEO_DISCONTINUE) == VIDEO_DISCONTINUE) { - cur_checkin_vpts -= tsync_pcr_ref_latency; + if (abs(cur_checkin_apts - cur_checkin_vpts) + > MAX_GAP) + ref_pcr = cur_checkin_vpts - + tsync_pcr_ref_latency; + else + ref_pcr = tsync_pcr_get_min_checkinpts(); tsync_set_pcr_mode(0, cur_checkin_vpts); tsync_pcr_tsdemuxpcr_discontinue = 0; } @@ -690,6 +744,10 @@ static void tsync_process_discontinue(void) tsync_pcr_demux_pcr_used() == 0) { tsync_set_pcr_mode(1, cur_vpts); tsync_pcr_tsdemuxpcr_discontinue = 0; + } else if (tsync_pcr_demux_pcr_used() == 0 && + tsync_video_continue_count > 100) { + tsync_pcr_tsdemuxpcr_discontinue = 0; + tsync_set_pcr_mode(1, cur_checkin_vpts); } else { tsync_pcr_tsdemuxpcr_discontinue = 0; return; @@ -715,59 +773,111 @@ static void tsync_process_discontinue(void) } } -static u32 last_pcr_checkin_apts; -static u32 last_pcr_checkin_vpts; -static u32 last_pcr_checkin_apts_count; -static u32 last_pcr_checkin_vpts_count; - void tsync_pcr_check_checinpts(void) { u32 checkin_vpts = 0; u32 checkin_apts = 0; + int max_gap; - checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); - checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); - - if (tsync_pcr_vstart_flag == 0 && tsync_pcr_astart_flag == 0) - return; - - if (checkin_vpts == 0xffffffff) - return; - - if (tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb() - && (checkin_apts == 0xffffffff)) - return; - - if (last_pcr_checkin_apts == 0 || last_pcr_checkin_vpts == 0) { - last_pcr_checkin_apts = checkin_apts; - last_pcr_checkin_vpts = checkin_vpts; - return; + if (tsync_pcr_astart_flag == 1) { + checkin_apts = get_last_checkin_pts(PTS_TYPE_AUDIO); + if ((checkin_apts != 0xffffffff) && + (last_pcr_checkin_apts != 0) && + (last_pcr_checkin_apts != 0xffffffff)) { + if (abs(last_pcr_checkin_apts - checkin_apts) + > 2 * 90000) { + tsync_pcr_tsdemuxpcr_discontinue |= + AUDIO_DISCONTINUE; + tsync_audio_discontinue = 1; + last_discontinue_checkin_apts = 0; + tsync_audio_continue_count = 0; + if (tsync_pcr_debug & 0x03) { + pr_info("a_discontinue,last %x,cur %x\n", + last_pcr_checkin_apts, + checkin_apts); + } + } + if (last_pcr_checkin_apts == checkin_apts) { + if (tsync_pcr_demux_pcr_used() == 1) + max_gap = 40; + else + max_gap = 100; + last_pcr_checkin_apts_count++; + if (last_pcr_checkin_apts_count > max_gap) { + tsync_pcr_tsdemuxpcr_discontinue |= + AUDIO_DISCONTINUE; + tsync_audio_discontinue = 1; + last_discontinue_checkin_apts = 0; + tsync_audio_continue_count = 0; + if (tsync_pcr_debug & 0x03) + pr_info("a_discontinue,count\n"); + } + } else { + if (tsync_audio_discontinue == 1 && + checkin_apts != 0xffffffff && + last_discontinue_checkin_apts == 0 && + checkin_apts > last_pcr_checkin_apts && + ((checkin_apts - last_pcr_checkin_apts) + < 500 * 90)) { + last_discontinue_checkin_apts = + last_pcr_checkin_apts; + tsync_audio_continue_count = 1; + } + last_pcr_checkin_apts = checkin_apts; + last_pcr_checkin_apts_count = 0; + } + if (tsync_audio_continue_count) + tsync_audio_continue_count++; + if (tsync_audio_continue_count > 50 && + tsync_audio_discontinue && + last_discontinue_checkin_apts) { + tsync_audio_discontinue = 0; + if (tsync_pcr_debug & 0x03) + pr_info("a_continued,resumed\n"); + } + } else { + last_pcr_checkin_apts = checkin_apts; + } } - if (last_pcr_checkin_apts > checkin_apts) - tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE; - - if (abs(last_pcr_checkin_vpts - checkin_vpts) > 2 * 90000) - tsync_pcr_tsdemuxpcr_discontinue |= VIDEO_DISCONTINUE; - - if (last_pcr_checkin_apts == checkin_apts) { - last_pcr_checkin_apts_count++; - if (last_pcr_checkin_apts_count > 100) - tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE; - } else { - last_pcr_checkin_apts = checkin_apts; - last_pcr_checkin_apts_count = 0; + if (tsync_pcr_vstart_flag == 1) { + checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO); + if ((checkin_vpts != 0xffffffff) && + (last_pcr_checkin_vpts != 0) && + (last_pcr_checkin_vpts != 0xffffffff)) { + if (abs(last_pcr_checkin_vpts - checkin_vpts) + > 2 * 90000) { + tsync_pcr_tsdemuxpcr_discontinue |= + VIDEO_DISCONTINUE; + tsync_video_continue_count = 0; + if (tsync_pcr_debug & 0x03) { + pr_info("v_discontinue,last %x,cur %x\n", + last_pcr_checkin_vpts, + checkin_vpts); + } + } else + tsync_video_continue_count++; + if (last_pcr_checkin_vpts == checkin_vpts) { + if (tsync_pcr_demux_pcr_used() == 1) + max_gap = 50; + else + max_gap = 100; + last_pcr_checkin_vpts_count++; + if (last_pcr_checkin_vpts_count > max_gap) { + tsync_pcr_tsdemuxpcr_discontinue |= + VIDEO_DISCONTINUE; + tsync_video_continue_count = 0; + if (tsync_pcr_debug & 0x03) + pr_info("v_discontinue,count\n"); + } + } else { + last_pcr_checkin_vpts = checkin_vpts; + last_pcr_checkin_vpts_count = 0; + } + } else { + last_pcr_checkin_vpts = checkin_vpts; + } } - - if (last_pcr_checkin_vpts == checkin_vpts) { - last_pcr_checkin_vpts_count++; - if (last_pcr_checkin_vpts_count > 100) - tsync_pcr_tsdemuxpcr_discontinue |= VIDEO_DISCONTINUE; - } else { - last_pcr_checkin_vpts = checkin_vpts; - last_pcr_checkin_vpts_count = 0; - } - } EXPORT_SYMBOL(tsync_pcr_pcrscr_set); @@ -784,7 +894,7 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) pr_info("video start! param=%x cur_pcr=%x\n", param, timestamp_pcrscr_get()); } - + tsync_set_av_state(0, 2); /*tsync_pcr_inited_mode = INIT_MODE_VIDEO;*/ tsync_pcr_pcrscr_set(); @@ -798,7 +908,7 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) timestamp_firstapts_set(0); timestamp_vpts_set(0); /* tsync_pcr_debug_pcrscr=100; */ - + tsync_set_av_state(0, 3); tsync_pcr_vpause_flag = 0; tsync_pcr_vstart_flag = 0; tsync_pcr_inited_flag = 0; @@ -866,6 +976,7 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) break; case AUDIO_START: + tsync_set_av_state(1, AUDIO_START); timestamp_apts_set(param); timestamp_apts_enable(1); timestamp_apts_start(1); @@ -883,6 +994,7 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param) break; case AUDIO_STOP: + tsync_set_av_state(1, AUDIO_STOP); timestamp_apts_enable(0); timestamp_apts_set(-1); timestamp_firstapts_set(0); @@ -1039,7 +1151,8 @@ static unsigned long tsync_pcr_check(void) if ((!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_VPTS)) && (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_PCR)) && (!(tsync_pcr_inited_flag & TSYNC_PCR_INITCHECK_APTS))) { - u64 cur_system_time = (jiffies * TIME_UNIT90K) / HZ; + u64 cur_system_time = + div64_u64((u64)jiffies * TIME_UNIT90K, HZ); if (cur_system_time - first_time_record < 270000) { } else { tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO; @@ -1120,8 +1233,6 @@ static void tsync_pcr_param_reset(void) tsync_pcr_reset_flag = 0; tsync_pcr_asynccheck_cnt = 0; tsync_pcr_vsynccheck_cnt = 0; - pr_info("wait_pcr_count = 0\n"); - tsync_pcr_last_tsdemuxpcr = 0; tsync_pcr_discontinue_local_point = 0; tsync_pcr_discontinue_point = 0; @@ -1146,6 +1257,11 @@ static void tsync_pcr_param_reset(void) tsync_pcr_first_jiffes = 0; tsync_pcr_first_systime = 0; speed_check_count = 0; + tsync_audio_discontinue = 0; + tsync_audio_continue_count = 0; + tsync_video_continue_count = 0; + last_discontinue_checkin_apts = 0; + tsync_vpts_adjust = 0; } @@ -1157,6 +1273,12 @@ int tsync_pcr_set_apts(unsigned int pts) } EXPORT_SYMBOL(tsync_pcr_set_apts); +int tsync_get_vpts_adjust(void) +{ + return tsync_vpts_adjust * 90; +} +EXPORT_SYMBOL(tsync_get_vpts_adjust); + int tsync_pcr_start(void) { timestamp_pcrscr_enable(0); @@ -1170,9 +1292,11 @@ int tsync_pcr_start(void) tsync_pcr_check_timer.function = tsync_pcr_check_timer_func; tsync_pcr_check_timer.expires = (unsigned long)jiffies; - first_time_record = (jiffies * TIME_UNIT90K) / HZ; + first_time_record = div64_u64((u64)jiffies * TIME_UNIT90K, HZ); tsync_pcr_started = 1; - if (tsdemux_pcrscr_valid_cb && tsdemux_pcrscr_valid_cb() == 0) { + if ((tsdemux_pcrscr_valid_cb && + tsdemux_pcrscr_valid_cb() == 0) || + tsync_disable_demux_pcr == 1) { tsync_use_demux_pcr = 0; tsync_pcr_inited_mode = INIT_PRIORITY_AUDIO; } else { @@ -1180,8 +1304,6 @@ int tsync_pcr_start(void) tsync_pcr_inited_mode = INIT_PRIORITY_PCR; } tsync_pcr_read_cnt = 0; - pr_info("[tsync_pcr_start]usepcr=%d tsync_pcr_inited_mode=%d\n", - tsync_pcr_usepcr, tsync_pcr_inited_mode); add_timer(&tsync_pcr_check_timer); } abuf_fatal_error = 0; @@ -1189,6 +1311,8 @@ int tsync_pcr_start(void) tsync_demux_last_pcr = 0; tsync_demux_pcr_discontinue_count = 0; tsync_demux_pcr_continue_count = 0; + tsync_audio_state = 1; + tsync_video_state = 1; return 0; } EXPORT_SYMBOL(tsync_pcr_start); @@ -1207,6 +1331,10 @@ void tsync_pcr_stop(void) } tsync_pcr_freerun_mode = 0; tsync_pcr_started = 0; + tsync_audio_state = 0; + tsync_video_state = 0; + timestamp_vpts_set(0); + timestamp_pcrscr_set(0); } EXPORT_SYMBOL(tsync_pcr_stop); @@ -1277,30 +1405,112 @@ static ssize_t store_tsync_pcr_audio_resample_type(struct class *class, return size; } -static ssize_t tsync_pcr_freerun_mode_show(struct class *cla, +static ssize_t tsync_pcr_mode_show(struct class *cla, struct class_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", tsync_pcr_freerun_mode); + return sprintf(buf, "%d\n", tsync_use_demux_pcr); } -static ssize_t tsync_pcr_freerun_mode_store(struct class *cla, +static ssize_t tsync_audio_mode_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tsync_audio_mode); +} + +static ssize_t tsync_audio_state_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tsync_audio_state); +} + +static ssize_t tsync_video_state_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tsync_video_state); +} + +static ssize_t tsync_audio_mode_store(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { size_t r; - /*r = sscanf(buf, "%d", &tsync_pcr_freerun_mode);*/ - r = kstrtoint(buf, 0, &tsync_pcr_freerun_mode); - - pr_info("%s(%d)\n", __func__, tsync_pcr_freerun_mode); - + r = kstrtoint(buf, 0, &tsync_audio_mode); if (r != 0) return -EINVAL; - return count; } +static ssize_t tsync_disable_pcr_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tsync_disable_demux_pcr); +} + +static ssize_t tsync_disable_pcr_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + size_t r; + + r = kstrtoint(buf, 0, &tsync_disable_demux_pcr); + if (r != 0) + return -EINVAL; + return count; +} + +static ssize_t tsync_vpts_adjust_store(struct class *cla, + struct class_attribute *attr, + const char *buf, size_t count) +{ + size_t r; + + r = kstrtoint(buf, 0, &tsync_vpts_adjust); + if (r != 0) + return -EINVAL; + return count; +} + +static ssize_t tsync_vpts_adjust_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tsync_vpts_adjust); +} + +static ssize_t tsync_audio_level_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 audio_level; + + audio_level = tsync_audio_discontinue & 0xff; + return sprintf(buf, "%d\n", audio_level); +} + +static ssize_t tsync_pcr_apts_diff_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + u32 t1, apts_diff; + + t1 = timestamp_get_pts_latency(1); + apts_diff = t1 & 0xffff; + return sprintf(buf, "%d\n", apts_diff); +} + +static ssize_t tsync_last_checkin_apts_show(struct class *cla, + struct class_attribute *attr, + char *buf) +{ + return sprintf(buf, "0x%x\n", last_discontinue_checkin_apts); +} + static ssize_t show_reset_flag(struct class *class, struct class_attribute *attr, char *buf) { @@ -1450,8 +1660,26 @@ static struct class_attribute tsync_pcr_class_attrs[] = { show_tsync_pcr_dispoint, store_tsync_pcr_dispoint), __ATTR(audio_resample_type, 0644, NULL, store_tsync_pcr_audio_resample_type), - __ATTR(tsync_pcr_freerun_mode, 0644, - tsync_pcr_freerun_mode_show, tsync_pcr_freerun_mode_store), + __ATTR(tsync_pcr_mode, 0644, + tsync_pcr_mode_show, NULL), + __ATTR(tsync_audio_mode, 0644, + tsync_audio_mode_show, tsync_audio_mode_store), + __ATTR(tsync_audio_state, 0644, + tsync_audio_state_show, NULL), + __ATTR(tsync_video_state, 0644, + tsync_video_state_show, NULL), + __ATTR(tsync_disable_demux_pcr, 0644, + tsync_disable_pcr_show, tsync_disable_pcr_store), + + __ATTR(tsync_vpts_adjust, 0644, + tsync_vpts_adjust_show, tsync_vpts_adjust_store), + + __ATTR(tsync_audio_level, 0644, + tsync_audio_level_show, NULL), + __ATTR(tsync_pcr_apts_diff, 0644, + tsync_pcr_apts_diff_show, NULL), + __ATTR(tsync_last_discontinue_checkin_apts, 0644, + tsync_last_checkin_apts_show, NULL), __ATTR(tsync_pcr_reset_flag, 0664, show_reset_flag, NULL), __ATTR(tsync_pcr_apause_flag, 0664, @@ -1494,6 +1722,8 @@ int tsync_pcr_init(void) timestamp_pcrscr_set(0); wait_pcr_count = 0; tsync_pcr_debug = 0; + tsync_audio_mode = 0; + tsync_disable_demux_pcr = 0; pr_info("[tsync_pcr_init]init success.\n"); return 0; } diff --git a/drivers/amlogic/media/gdc/Makefile b/drivers/amlogic/media/gdc/Makefile index d0d4b2725e5d..0d1b3a639d2f 100644 --- a/drivers/amlogic/media/gdc/Makefile +++ b/drivers/amlogic/media/gdc/Makefile @@ -2,7 +2,8 @@ FW_SRC := src/fw_lib/acamera_gdc.c \ src/platform/system_gdc_io.c \ app/gdc_main.c \ app/gdc_module.c \ - app/gdc_dmabuf.c + app/gdc_dmabuf.c \ + app/gdc_wq.c FW_SRC_OBJ := $(FW_SRC:.c=.o) diff --git a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c index 216a09e7f40f..2c0426cf59e1 100644 --- a/drivers/amlogic/media/gdc/app/gdc_dmabuf.c +++ b/drivers/amlogic/media/gdc/app/gdc_dmabuf.c @@ -36,18 +36,65 @@ #include "gdc_dmabuf.h" static void clear_dma_buffer(struct aml_dma_buffer *buffer, int index); + +static void *aml_mm_vmap(phys_addr_t phys, unsigned long size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + int i; + + offset = offset_in_page(phys); + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /* pgprot = pgprot_writecombine(PAGE_KERNEL); */ + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + gdc_log(LOG_DEBUG, "[HIGH-MEM-MAP] pa(%lx) to va(%p), size: %d\n", + (unsigned long)phys, vaddr, npages << PAGE_SHIFT); + return vaddr; +} + +static void *aml_map_phyaddr_to_virt(dma_addr_t phys, unsigned long size) +{ + void *vaddr = NULL; + + if (!PageHighMem(phys_to_page(phys))) + return phys_to_virt(phys); + vaddr = aml_mm_vmap(phys, size); + return vaddr; +} + /* dma free*/ static void aml_dma_put(void *buf_priv) { struct aml_dma_buf *buf = buf_priv; struct page *cma_pages = NULL; + void *vaddr = (void *)(PAGE_MASK & (ulong)buf->vaddr); if (!atomic_dec_and_test(&buf->refcount)) { - gdc_log(LOG_INFO, "gdc aml_dma_put, refcont=%d\n", + gdc_log(LOG_DEBUG, "gdc aml_dma_put, refcont=%d\n", atomic_read(&buf->refcount)); return; } - cma_pages = virt_to_page(buf->vaddr); + cma_pages = phys_to_page(buf->dma_addr); + if (is_vmalloc_or_module_addr(vaddr)) + vunmap(vaddr); if (!dma_release_from_contiguous(buf->dev, cma_pages, buf->size >> PAGE_SHIFT)) { pr_err("failed to release cma buffer\n"); @@ -55,9 +102,10 @@ static void aml_dma_put(void *buf_priv) buf->vaddr = NULL; clear_dma_buffer((struct aml_dma_buffer *)buf->priv, buf->index); put_device(buf->dev); - kfree(buf); - gdc_log(LOG_INFO, "gdc free:aml_dma_buf=0x%p,buf->index=%d\n", + + gdc_log(LOG_DEBUG, "gdc free:aml_dma_buf=0x%p,buf->index=%d\n", buf, buf->index); + kfree(buf); } static void *aml_dma_alloc(struct device *dev, unsigned long attrs, @@ -82,16 +130,17 @@ static void *aml_dma_alloc(struct device *dev, unsigned long attrs, if (cma_pages) { paddr = page_to_phys(cma_pages); } else { + kfree(buf); pr_err("failed to alloc cma pages.\n"); return NULL; } - buf->vaddr = phys_to_virt(paddr); + buf->vaddr = aml_map_phyaddr_to_virt(paddr, size); buf->dev = get_device(dev); buf->size = size; buf->dma_dir = dma_dir; buf->dma_addr = paddr; atomic_inc(&buf->refcount); - gdc_log(LOG_INFO, "aml_dma_buf=0x%p, refcont=%d\n", + gdc_log(LOG_DEBUG, "aml_dma_buf=0x%p, refcont=%d\n", buf, atomic_read(&buf->refcount)); return buf; @@ -101,7 +150,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) { struct aml_dma_buf *buf = buf_priv; unsigned long pfn = 0; - unsigned long vsize = vma->vm_end - vma->vm_start; + unsigned long vsize; int ret = -1; if (!buf || !vma) { @@ -109,7 +158,9 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) return -EINVAL; } - pfn = virt_to_phys(buf->vaddr) >> PAGE_SHIFT; + vsize = vma->vm_end - vma->vm_start; + + pfn = buf->dma_addr >> PAGE_SHIFT; ret = remap_pfn_range(vma, vma->vm_start, pfn, vsize, vma->vm_page_prot); if (ret) { @@ -118,7 +169,7 @@ static int aml_dma_mmap(void *buf_priv, struct vm_area_struct *vma) } vma->vm_flags |= VM_DONTEXPAND; - gdc_log(LOG_INFO, "mapped dma addr 0x%08lx at 0x%08lx, size %d\n", + gdc_log(LOG_DEBUG, "mapped dma addr 0x%08lx at 0x%08lx, size %d\n", (unsigned long)buf->dma_addr, vma->vm_start, buf->size); return 0; @@ -140,7 +191,7 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE; struct sg_table *sgt; struct scatterlist *sg; - void *vaddr = buf->vaddr; + phys_addr_t phys = buf->dma_addr; unsigned int i; int ret; @@ -158,15 +209,10 @@ static int aml_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev, return -ENOMEM; } for_each_sg(sgt->sgl, sg, sgt->nents, i) { - struct page *page = virt_to_page(vaddr); + struct page *page = phys_to_page(phys); - if (!page) { - sg_free_table(sgt); - kfree(attach); - return -ENOMEM; - } sg_set_page(sg, page, PAGE_SIZE, 0); - vaddr += PAGE_SIZE; + phys += PAGE_SIZE; } attach->dma_dir = DMA_NONE; @@ -299,7 +345,7 @@ static struct dma_buf *get_dmabuf(void *buf_priv, unsigned long flags) /* dmabuf keeps reference to vb2 buffer */ atomic_inc(&buf->refcount); - gdc_log(LOG_INFO, "get_dmabuf, refcount=%d\n", + gdc_log(LOG_DEBUG, "get_dmabuf, refcount=%d\n", atomic_read(&buf->refcount)); return dbuf; @@ -315,7 +361,7 @@ static int find_empty_dma_buffer(struct aml_dma_buffer *buffer) if (buffer->gd_buffer[i].alloc) continue; else { - gdc_log(LOG_INFO, "find_empty_dma_buffer i=%d\n", i); + gdc_log(LOG_DEBUG, "find_empty_dma_buffer i=%d\n", i); found = 1; break; } @@ -457,7 +503,7 @@ int gdc_dma_buffer_export(struct aml_dma_buffer *buffer, dma_buf_put(dbuf); return ret; } - gdc_log(LOG_INFO, "buffer %d,exported as %d descriptor\n", + gdc_log(LOG_DEBUG, "buffer %d,exported as %d descriptor\n", index, ret); buffer->gd_buffer[index].fd = ret; buffer->gd_buffer[index].dbuf = dbuf; @@ -516,7 +562,7 @@ int gdc_dma_buffer_map(struct aml_dma_cfg *cfg) cfg->attach = d_att; cfg->vaddr = vaddr; cfg->sg = sg; - gdc_log(LOG_INFO, "gdc_dma_buffer_map, dbuf=0x%p\n", dbuf); + gdc_log(LOG_DEBUG, "gdc_dma_buffer_map, dbuf=0x%p\n", dbuf); return ret; @@ -574,7 +620,7 @@ int gdc_dma_buffer_get_phys(struct aml_dma_buffer *buffer, } ret = gdc_dma_buffer_get_phys_internal(buffer, cfg, addr); if (ret < 0) { - gdc_log(LOG_INFO, "get_phys(fd=%d) failed.\n", cfg->fd); + gdc_log(LOG_DEBUG, "get_phys(fd=%d) failed.\n", cfg->fd); ret = gdc_dma_buffer_map(cfg); if (ret < 0) { pr_err("gdc_dma_buffer_map failed\n"); @@ -645,7 +691,7 @@ void gdc_dma_buffer_unmap(struct aml_dma_cfg *cfg) dma_buf_detach(dbuf, d_att); dma_buf_put(dbuf); - gdc_log(LOG_INFO, "gdc_dma_buffer_unmap, dbuf=0x%p\n", dbuf); + gdc_log(LOG_DEBUG, "gdc_dma_buffer_unmap, dbuf=0x%p\n", dbuf); } void gdc_dma_buffer_dma_flush(struct device *dev, int fd) @@ -653,7 +699,7 @@ void gdc_dma_buffer_dma_flush(struct device *dev, int fd) struct dma_buf *dmabuf; struct aml_dma_buf *buf; - gdc_log(LOG_INFO, "gdc_dma_buffer_dma_flush fd=%d\n", fd); + gdc_log(LOG_DEBUG, "gdc_dma_buffer_dma_flush fd=%d\n", fd); dmabuf = dma_buf_get(fd); if (IS_ERR(dmabuf)) { pr_err("dma_buf_get failed\n"); @@ -675,7 +721,7 @@ void gdc_dma_buffer_cache_flush(struct device *dev, int fd) struct dma_buf *dmabuf; struct aml_dma_buf *buf; - gdc_log(LOG_INFO, "gdc_dma_buffer_cache_flush fd=%d\n", fd); + gdc_log(LOG_DEBUG, "gdc_dma_buffer_cache_flush fd=%d\n", fd); dmabuf = dma_buf_get(fd); if (IS_ERR(dmabuf)) { pr_err("dma_buf_get failed\n"); diff --git a/drivers/amlogic/media/gdc/app/gdc_main.c b/drivers/amlogic/media/gdc/app/gdc_main.c index 538416dd9bb0..ed3c67238d59 100644 --- a/drivers/amlogic/media/gdc/app/gdc_main.c +++ b/drivers/amlogic/media/gdc/app/gdc_main.c @@ -22,22 +22,12 @@ //gdc api functions #include "gdc_api.h" -irqreturn_t interrupt_handler_next(int irq, void *param) -{ - //handle the start of frame with gdc_process - struct gdc_cmd_s *gdc_cmd = (struct gdc_cmd_s *)param; - - gdc_get_frame(gdc_cmd); - - return IRQ_HANDLED; -} - int gdc_run(struct gdc_cmd_s *g) { gdc_stop(g); - gdc_log(LOG_INFO, "Done gdc load..\n"); + gdc_log(LOG_DEBUG, "Done gdc load..\n"); //initialise the gdc by the first configuration if (gdc_init(g) != 0) { @@ -45,7 +35,7 @@ int gdc_run(struct gdc_cmd_s *g) return -1; } - gdc_log(LOG_INFO, "Done gdc config..\n"); + gdc_log(LOG_DEBUG, "Done gdc config..\n"); switch (g->gdc_config.format) { case NV12: diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 219109673a9d..ddbd172464a4 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -46,15 +46,15 @@ //gdc configuration sequence #include "gdc_config.h" #include "gdc_dmabuf.h" +#include "gdc_wq.h" -unsigned int gdc_log_level; -unsigned int gdc_reg_store_mode; +int gdc_log_level; struct gdc_manager_s gdc_manager; -static int trace_mode_enable; -static char *config_out_file; -static int config_out_path_defined; +unsigned int gdc_reg_store_mode; +int trace_mode_enable; +char *config_out_file; +int config_out_path_defined; -#define WAIT_THRESHOLD 1000 #define CONFIG_PATH_LENG 128 #define CORE_CLK_RATE 800000000 #define AXI_CLK_RATE 800000000 @@ -71,142 +71,132 @@ static void meson_gdc_cache_flush(struct device *dev, ////// static int meson_gdc_open(struct inode *inode, struct file *file) { - struct meson_gdc_dev_t *gdc_dev = gdc_manager.gdc_dev; - struct mgdc_fh_s *fh = NULL; - char ion_client_name[32]; - int rc = 0; + struct gdc_context_s *context = NULL; - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (fh == NULL) { - gdc_log(LOG_DEBUG, "devm alloc failed\n"); - return -ENOMEM; + /* we create one gdc workqueue for this file handler. */ + context = create_gdc_work_queue(); + if (!context) { + gdc_log(LOG_ERR, "can't create work queue\n"); + return -1; } - get_task_comm(fh->task_comm, current); - gdc_log(LOG_DEBUG, "%s, %d, call from %s\n", - __func__, __LINE__, fh->task_comm); - - file->private_data = fh; - snprintf(ion_client_name, sizeof(fh->task_comm), - "gdc-%s", fh->task_comm); - if (!fh->ion_client) - fh->ion_client = meson_ion_client_create(-1, ion_client_name); - - fh->gdev = gdc_dev; + file->private_data = context; gdc_log(LOG_INFO, "Success open\n"); - return rc; + return 0; } static int meson_gdc_release(struct inode *inode, struct file *file) { - struct mgdc_fh_s *fh = file->private_data; + struct gdc_context_s *context = NULL; struct page *cma_pages = NULL; bool rc = false; int ret = 0; + struct device *dev = &gdc_manager.gdc_dev->pdev->dev; - if (fh->ion_client) { - ion_client_destroy(fh->ion_client); - fh->ion_client = NULL; + context = (struct gdc_context_s *)file->private_data; + if (!context) { + gdc_log(LOG_ERR, "context is null,release work queue error\n"); + return -1; } - if (fh->i_kaddr != 0 && fh->i_len != 0) { - cma_pages = virt_to_page(fh->i_kaddr); - rc = dma_release_from_contiguous(&fh->gdev->pdev->dev, + if (context->i_kaddr != 0 && context->i_len != 0) { + cma_pages = virt_to_page(context->i_kaddr); + rc = dma_release_from_contiguous(dev, cma_pages, - fh->i_len >> PAGE_SHIFT); + context->i_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; gdc_log(LOG_ERR, "Failed to release input buff\n"); } - - fh->i_kaddr = NULL; - fh->i_paddr = 0; - fh->i_len = 0; + mutex_lock(&context->d_mutext); + context->i_kaddr = NULL; + context->i_paddr = 0; + context->i_len = 0; + mutex_unlock(&context->d_mutext); } - if (fh->o_kaddr != 0 && fh->o_len != 0) { - cma_pages = virt_to_page(fh->o_kaddr); - rc = dma_release_from_contiguous(&fh->gdev->pdev->dev, + if (context->o_kaddr != 0 && context->o_len != 0) { + cma_pages = virt_to_page(context->o_kaddr); + rc = dma_release_from_contiguous(dev, cma_pages, - fh->o_len >> PAGE_SHIFT); + context->o_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; gdc_log(LOG_ERR, "Failed to release output buff\n"); } - - fh->o_kaddr = NULL; - fh->o_paddr = 0; - fh->o_len = 0; + mutex_lock(&context->d_mutext); + context->o_kaddr = NULL; + context->o_paddr = 0; + context->o_len = 0; + mutex_unlock(&context->d_mutext); } - if (fh->c_kaddr != 0 && fh->c_len != 0) { - cma_pages = virt_to_page(fh->c_kaddr); - rc = dma_release_from_contiguous(&fh->gdev->pdev->dev, + if (context->c_kaddr != 0 && context->c_len != 0) { + cma_pages = virt_to_page(context->c_kaddr); + rc = dma_release_from_contiguous(dev, cma_pages, - fh->c_len >> PAGE_SHIFT); + context->c_len >> PAGE_SHIFT); if (rc == false) { ret = ret - 1; gdc_log(LOG_ERR, "Failed to release config buff\n"); } - - fh->c_kaddr = NULL; - fh->c_paddr = 0; - fh->c_len = 0; + mutex_lock(&context->d_mutext); + context->c_kaddr = NULL; + context->c_paddr = 0; + context->c_len = 0; + mutex_unlock(&context->d_mutext); } - - kfree(fh); - fh = NULL; - - if (ret == 0) - gdc_log(LOG_INFO, "Success release\n"); - else - gdc_log(LOG_ERR, "Error release\n"); + if (destroy_gdc_work_queue(context) == 0) + gdc_log(LOG_INFO, "release one gdc device\n"); return ret; } -static long meson_gdc_set_buff(void *f_fh, +static long meson_gdc_set_buff(struct gdc_context_s *context, struct page *cma_pages, unsigned long len) { int ret = 0; - struct mgdc_fh_s *fh = NULL; - if (f_fh == NULL || cma_pages == NULL || len == 0) { + if (context == NULL || cma_pages == NULL || len == 0) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } - fh = f_fh; - - switch (fh->mmap_type) { + switch (context->mmap_type) { case INPUT_BUFF_TYPE: - if (fh->i_paddr != 0 && fh->i_kaddr != NULL) + if (context->i_paddr != 0 && context->i_kaddr != NULL) return -EAGAIN; - fh->i_paddr = page_to_phys(cma_pages); - fh->i_kaddr = phys_to_virt(fh->i_paddr); - fh->i_len = len; + mutex_lock(&context->d_mutext); + context->i_paddr = page_to_phys(cma_pages); + context->i_kaddr = phys_to_virt(context->i_paddr); + context->i_len = len; + mutex_unlock(&context->d_mutext); break; case OUTPUT_BUFF_TYPE: - if (fh->o_paddr != 0 && fh->o_kaddr != NULL) + if (context->o_paddr != 0 && context->o_kaddr != NULL) return -EAGAIN; - fh->o_paddr = page_to_phys(cma_pages); - fh->o_kaddr = phys_to_virt(fh->o_paddr); - fh->o_len = len; - meson_gdc_cache_flush(&fh->gdev->pdev->dev, - fh->o_paddr, fh->o_len); + mutex_lock(&context->d_mutext); + context->o_paddr = page_to_phys(cma_pages); + context->o_kaddr = phys_to_virt(context->o_paddr); + context->o_len = len; + mutex_unlock(&context->d_mutext); + meson_gdc_cache_flush(&gdc_manager.gdc_dev->pdev->dev, + context->o_paddr, context->o_len); break; case CONFIG_BUFF_TYPE: - if (fh->c_paddr != 0 && fh->c_kaddr != NULL) + if (context->c_paddr != 0 && context->c_kaddr != NULL) return -EAGAIN; - fh->c_paddr = page_to_phys(cma_pages); - fh->c_kaddr = phys_to_virt(fh->c_paddr); - fh->c_len = len; + mutex_lock(&context->d_mutext); + context->c_paddr = page_to_phys(cma_pages); + context->c_kaddr = phys_to_virt(context->c_paddr); + context->c_len = len; + mutex_unlock(&context->d_mutext); break; default: - gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", context->mmap_type); ret = -EINVAL; break; } @@ -399,25 +389,26 @@ static void meson_gdc_dma_unmap(struct gdc_dma_cfg *cfg) dma_buf_put(dbuf); } -static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, +static long meson_gdc_init_dma_addr( + struct gdc_context_s *context, struct gdc_settings *gs) { long ret = -1; struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_cmd_s *gdc_cmd = &context->cmd; struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (fh == NULL || gs == NULL) { + if (context == NULL || gs == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } switch (gc->format) { case NV12: - dma_cfg = &fh->y_dma_cfg; + dma_cfg = &context->y_dma_cfg; memset(dma_cfg, 0, sizeof(*dma_cfg)); dma_cfg->dir = DMA_TO_DEVICE; - dma_cfg->dev = &fh->gdev->pdev->dev; + dma_cfg->dev = &gdc_manager.gdc_dev->pdev->dev; dma_cfg->fd = gs->y_base_fd; ret = meson_gdc_dma_map(dma_cfg); @@ -428,10 +419,10 @@ static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, gdc_cmd->y_base_addr = virt_to_phys(dma_cfg->vaddr); - dma_cfg = &fh->uv_dma_cfg; + dma_cfg = &context->uv_dma_cfg; memset(dma_cfg, 0, sizeof(*dma_cfg)); dma_cfg->dir = DMA_TO_DEVICE; - dma_cfg->dev = &fh->gdev->pdev->dev; + dma_cfg->dev = &gdc_manager.gdc_dev->pdev->dev; dma_cfg->fd = gs->uv_base_fd; ret = meson_gdc_dma_map(dma_cfg); @@ -443,10 +434,10 @@ static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, gdc_cmd->uv_base_addr = virt_to_phys(dma_cfg->vaddr); break; case Y_GREY: - dma_cfg = &fh->y_dma_cfg; + dma_cfg = &context->y_dma_cfg; memset(dma_cfg, 0, sizeof(*dma_cfg)); dma_cfg->dir = DMA_TO_DEVICE; - dma_cfg->dev = &fh->gdev->pdev->dev; + dma_cfg->dev = &gdc_manager.gdc_dev->pdev->dev; dma_cfg->fd = gs->y_base_fd; ret = meson_gdc_dma_map(dma_cfg); @@ -465,27 +456,27 @@ static long meson_gdc_init_dma_addr(struct mgdc_fh_s *fh, return ret; } -static void meson_gdc_deinit_dma_addr(struct mgdc_fh_s *fh) +static void meson_gdc_deinit_dma_addr(struct gdc_context_s *context) { struct gdc_dma_cfg *dma_cfg = NULL; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_cmd_s *gdc_cmd = &context->cmd; struct gdc_config_s *gc = &gdc_cmd->gdc_config; - if (fh == NULL) { + if (context == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return; } switch (gc->format) { case NV12: - dma_cfg = &fh->y_dma_cfg; + dma_cfg = &context->y_dma_cfg; meson_gdc_dma_unmap(dma_cfg); - dma_cfg = &fh->uv_dma_cfg; + dma_cfg = &context->uv_dma_cfg; meson_gdc_dma_unmap(dma_cfg); break; case Y_GREY: - dma_cfg = &fh->y_dma_cfg; + dma_cfg = &context->y_dma_cfg; meson_gdc_dma_unmap(dma_cfg); break; default: @@ -535,21 +526,165 @@ static int gdc_buffer_get_phys(struct aml_dma_cfg *cfg, unsigned long *addr) return gdc_dma_buffer_get_phys(gdc_manager.buffer, cfg, addr); } -static int gdc_buffer_unmap(struct aml_dma_cfg *cfg) +static int gdc_get_buffer_fd(int plane_id, struct gdc_buffer_info *buf_info) { - return gdc_dma_buffer_unmap_info(gdc_manager.buffer, cfg); + int fd; + + switch (plane_id) { + case 0: + fd = buf_info->y_base_fd; + break; + case 1: + fd = buf_info->uv_base_fd; + break; + case 2: + fd = buf_info->v_base_fd; + break; + default: + gdc_log(LOG_ERR, "Error plane id\n"); + return -EINVAL; + } + return fd; } -static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, +static int gdc_set_output_addr(int plane_id, + uint32_t addr, + struct gdc_cmd_s *gdc_cmd) +{ + switch (plane_id) { + case 0: + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = addr; + break; + case 1: + gdc_cmd->uv_out_base_addr = addr; + break; + case 2: + gdc_cmd->v_out_base_addr = addr; + break; + default: + gdc_log(LOG_ERR, "Error plane id\n"); + return -EINVAL; + } + return 0; +} + +static long gdc_set_input_addr(int plane_id, + uint32_t addr, + struct gdc_cmd_s *gdc_cmd) +{ + struct gdc_config_s *gc = NULL; + long size; + + if (gdc_cmd == NULL || addr == 0) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + gc = &gdc_cmd->gdc_config; + + switch (gc->format) { + case NV12: + if (plane_id == 0) { + gdc_cmd->y_base_addr = addr; + size = gc->input_y_stride * gc->input_height; + } else if (plane_id == 1) { + gdc_cmd->uv_base_addr = addr; + size = gc->input_y_stride * gc->input_height / 2; + } else + gdc_log(LOG_ERR, + "plane_id=%d is invalid for NV12\n", + plane_id); + break; + case YV12: + if (plane_id == 0) { + gdc_cmd->y_base_addr = addr; + size = gc->input_y_stride * gc->input_height; + } else if (plane_id == 1) { + gdc_cmd->u_base_addr = addr; + size = gc->input_c_stride * gc->input_height / 2; + } else if (plane_id == 2) { + gdc_cmd->v_base_addr = addr; + size = gc->input_c_stride * gc->input_height / 2; + } else + gdc_log(LOG_ERR, + "plane_id=%d is invalid for YV12\n", + plane_id); + break; + case Y_GREY: + if (plane_id == 0) { + gdc_cmd->y_base_addr = addr; + gdc_cmd->u_base_addr = 0; + gdc_cmd->v_base_addr = 0; + size = gc->input_y_stride * gc->input_height; + } else + gdc_log(LOG_ERR, + "plane_id=%d is invalid for Y_GREY\n", + plane_id); + break; + case YUV444_P: + case RGB444_P: + size = gc->input_y_stride * gc->input_height; + if (plane_id == 0) + gdc_cmd->y_base_addr = addr; + else if (plane_id == 1) + gdc_cmd->u_base_addr = addr; + else if (plane_id == 2) + gdc_cmd->v_base_addr = addr; + else + gdc_log(LOG_ERR, + "plane_id=%d is invalid for format=%d\n", + plane_id, gc->format); + break; + default: + gdc_log(LOG_ERR, "Error config format=%d\n", gc->format); + return -EINVAL; + } + return 0; +} + +static long gdc_get_input_size(struct gdc_cmd_s *gdc_cmd) +{ + struct gdc_config_s *gc = NULL; + long size; + + if (gdc_cmd == NULL) { + gdc_log(LOG_ERR, "Error input param\n"); + return -EINVAL; + } + + gc = &gdc_cmd->gdc_config; + + switch (gc->format) { + case NV12: + case YV12: + size = gc->input_y_stride * gc->input_height * 3 / 2; + break; + case Y_GREY: + size = gc->input_y_stride * gc->input_height; + break; + case YUV444_P: + case RGB444_P: + size = gc->input_y_stride * gc->input_height * 3; + break; + default: + gdc_log(LOG_ERR, "Error config format\n"); + return -EINVAL; + } + return 0; +} + +static long gdc_process_input_dma_info(struct gdc_context_s *context, struct gdc_settings_ex *gs_ex) { long ret = -1; unsigned long addr; + long size; struct aml_dma_cfg *cfg = NULL; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; - struct gdc_config_s *gc = &gdc_cmd->gdc_config; + struct gdc_cmd_s *gdc_cmd = &context->cmd; + int i, plane_number; - if (fh == NULL || gs_ex == NULL) { + if (context == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } @@ -560,159 +695,69 @@ static long gdc_process_input_dma_info(struct mgdc_fh_s *fh, return -EINVAL; } - switch (gc->format) { - case NV12: - if (gs_ex->input_buffer.plane_number == 1) { - cfg = &fh->dma_cfg.input_cfg_plane1; - cfg->fd = gs_ex->input_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr err\n"); - return -EINVAL; - } - gdc_log(LOG_INFO, "1 plane get input addr=%x\n", - gdc_cmd->y_base_addr); - } else if (gs_ex->input_buffer.plane_number == 2) { - cfg = &fh->dma_cfg.input_cfg_plane1; - cfg->fd = gs_ex->input_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->y_base_addr = addr; - cfg = &fh->dma_cfg.input_cfg_plane2; - cfg->fd = gs_ex->input_buffer.uv_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.uv_base_fd); - return -EINVAL; - } - gdc_cmd->uv_base_addr = addr; - gdc_log(LOG_INFO, "2 plane get input y_addr=%x\n", - gdc_cmd->y_base_addr); - gdc_log(LOG_INFO, "2 plane get input uv_addr=%x\n", - gdc_cmd->uv_base_addr); - } - break; - case YV12: - case YUV444_P: - if (gs_ex->input_buffer.plane_number == 1) { - cfg = &fh->dma_cfg.input_cfg_plane1; - cfg->fd = gs_ex->input_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr err\n"); - return -EINVAL; - } - gdc_log(LOG_INFO, "1 plane get input addr=%x\n", - gdc_cmd->y_base_addr); - } else if (gs_ex->input_buffer.plane_number == 3) { - cfg = &fh->dma_cfg.input_cfg_plane1; - cfg->fd = gs_ex->input_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->y_base_addr = addr; - cfg = &fh->dma_cfg.input_cfg_plane2; - cfg->fd = gs_ex->input_buffer.u_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->u_base_addr = addr; - cfg = &fh->dma_cfg.input_cfg_plane3; - cfg->fd = gs_ex->input_buffer.v_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_TO_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import input fd %d err\n", - gs_ex->input_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->v_base_addr = addr; - gdc_log(LOG_INFO, "3 plane get input y_addr=%x\n", - gdc_cmd->y_base_addr); - gdc_log(LOG_INFO, "3 plane get input u_addr=%x\n", - gdc_cmd->u_base_addr); - gdc_log(LOG_INFO, "3 plane get input v_addr=%x\n", - gdc_cmd->v_base_addr); - } - break; - case Y_GREY: - case RGB444_P: - cfg = &fh->dma_cfg.input_cfg_plane1; - cfg->fd = gs_ex->input_buffer.y_base_fd; - cfg->dev = &(fh->gdev->pdev->dev); + plane_number = gs_ex->input_buffer.plane_number; + for (i = 0; i < plane_number; i++) { + context->dma_cfg.input_cfg[i].dma_used = 1; + cfg = &context->dma_cfg.input_cfg[i].dma_cfg; + cfg->fd = gdc_get_buffer_fd(i, &gs_ex->input_buffer); + cfg->dev = &gdc_manager.gdc_dev->pdev->dev; cfg->dir = DMA_TO_DEVICE; ret = gdc_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, - "dma import input fd %d failed\n", - gs_ex->input_buffer.shared_fd); + "dma import input fd %d err\n", + cfg->fd); return -EINVAL; } - gdc_cmd->y_base_addr = addr; - gdc_cmd->uv_base_addr = 0; - break; - default: - gdc_log(LOG_ERR, "Error image format"); - break; + if (plane_number == 1) { + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + goto dma_buf_unmap; + } + } else { + size = gdc_set_input_addr(i, addr, gdc_cmd); + if (size < 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + goto dma_buf_unmap; + } + + } + gdc_log(LOG_DEBUG, "plane[%d] get input addr=%lx\n", + i, addr); + if (plane_number == 1) { + size = gdc_get_input_size(gdc_cmd); + if (size < 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + ret = -EINVAL; + goto dma_buf_unmap; + } + } + meson_gdc_dma_flush(&gdc_manager.gdc_dev->pdev->dev, + addr, size); } return 0; + +dma_buf_unmap: + while (i >= 0) { + cfg = &context->dma_cfg.input_cfg[i].dma_cfg; + gdc_dma_buffer_unmap(cfg); + context->dma_cfg.input_cfg[i].dma_used = 0; + i--; + } + return ret; } -static long gdc_process_input_ion_info(struct mgdc_fh_s *fh, +static long gdc_process_input_ion_info(struct gdc_context_s *context, struct gdc_settings_ex *gs_ex) { long ret = -1; unsigned long addr; size_t len; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; - struct gdc_config_s *gc = &gdc_cmd->gdc_config; + struct gdc_cmd_s *gdc_cmd = &context->cmd; + int i, plane_number, fd; - if (fh == NULL || gs_ex == NULL) { + if (context == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } @@ -723,139 +768,46 @@ static long gdc_process_input_ion_info(struct mgdc_fh_s *fh, return -EINVAL; } - switch (gc->format) { - case NV12: - if (gs_ex->input_buffer.plane_number == 1) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.shared_fd); - return -EINVAL; - } - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr err\n"); - return -EINVAL; - } - - gdc_log(LOG_INFO, "1 plane get input addr=%x\n", - gdc_cmd->y_base_addr); - } else if (gs_ex->input_buffer.plane_number == 2) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.y_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->y_base_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.uv_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.uv_base_fd); - return -EINVAL; - } - gdc_cmd->uv_base_addr = addr; - gdc_log(LOG_INFO, "2 plane get input y_addr=%x\n", - gdc_cmd->y_base_addr); - gdc_log(LOG_INFO, "2 plane get input uv_addr=%x\n", - gdc_cmd->uv_base_addr); - } - break; - case YV12: - case YUV444_P: - if (gs_ex->input_buffer.plane_number == 1) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.shared_fd); - return -EINVAL; - } - - ret = meson_gdc_set_input_addr(addr, gdc_cmd); - if (ret != 0) { - gdc_log(LOG_ERR, "set input addr err\n"); - return -EINVAL; - } - gdc_log(LOG_INFO, "1 plane get input addr=%x\n", - gdc_cmd->y_base_addr); - } else if (gs_ex->input_buffer.plane_number == 3) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.y_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->y_base_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.u_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->u_base_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.v_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.v_base_fd); - return -EINVAL; - } - gdc_cmd->v_base_addr = addr; - - gdc_log(LOG_INFO, "3 plane get input y_addr=%x\n", - gdc_cmd->y_base_addr); - gdc_log(LOG_INFO, "3 plane get input u_addr=%x\n", - gdc_cmd->u_base_addr); - gdc_log(LOG_INFO, "3 plane get input v_addr=%x\n", - gdc_cmd->v_base_addr); - } - break; - case Y_GREY: - case RGB444_P: - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->input_buffer.y_base_fd, - (ion_phys_addr_t *)&addr, &len); + plane_number = gs_ex->input_buffer.plane_number; + for (i = 0; i < plane_number; i++) { + fd = gdc_get_buffer_fd(i, &gs_ex->input_buffer); + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, + fd, (ion_phys_addr_t *)&addr, &len); if (ret < 0) { - gdc_log(LOG_ERR, "ion import input fd %d err\n", - gs_ex->input_buffer.y_base_fd); + gdc_log(LOG_ERR, "ion import input fd %d err\n", fd); return -EINVAL; } - gdc_cmd->y_base_addr = addr; - gdc_cmd->uv_base_addr = 0; - break; - default: - gdc_log(LOG_ERR, "Error image format"); - break; + + if (plane_number == 1) { + ret = meson_gdc_set_input_addr(addr, gdc_cmd); + if (ret != 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + } else { + ret = gdc_set_input_addr(i, addr, gdc_cmd); + if (ret < 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + + } + gdc_log(LOG_DEBUG, "plane[%d] get input addr=%lx\n", + i, addr); } return 0; } -static long gdc_process_output_dma_info(struct mgdc_fh_s *fh, +static long gdc_process_output_dma_info(struct gdc_context_s *context, struct gdc_settings_ex *gs_ex) { long ret = -1; unsigned long addr; struct aml_dma_cfg *cfg = NULL; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; - struct gdc_config_s *gc = &gdc_cmd->gdc_config; + struct gdc_cmd_s *gdc_cmd = &context->cmd; + int i, plane_number; - if (fh == NULL || gs_ex == NULL) { + if (context == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error output param\n"); return -EINVAL; } @@ -866,159 +818,59 @@ static long gdc_process_output_dma_info(struct mgdc_fh_s *fh, __func__, gs_ex->output_buffer.plane_number); } - switch (gc->format) { - case NV12: - if (gs_ex->output_buffer.plane_number == 1) { - cfg = &fh->dma_cfg.output_cfg_plane1; - cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = gdc_cmd->buffer_addr; - gdc_log(LOG_INFO, "1 plane get output addr=%x\n", - gdc_cmd->current_addr); - } else if (gs_ex->output_buffer.plane_number == 2) { - cfg = &fh->dma_cfg.output_cfg_plane1; - cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - - cfg = &fh->dma_cfg.output_cfg_plane2; - cfg->fd = gs_ex->output_buffer.uv_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.uv_base_fd); - return -EINVAL; - } - gdc_cmd->uv_out_base_addr = addr; - - gdc_log(LOG_INFO, "2 plane get output y_addr=%x\n", - gdc_cmd->current_addr); - gdc_log(LOG_INFO, "2 plane get output uv_addr=%x\n", - gdc_cmd->uv_out_base_addr); - } - break; - case YV12: - case YUV444_P: - case RGB444_P: - if (gs_ex->output_buffer.plane_number == 1) { - cfg = &fh->dma_cfg.output_cfg_plane1; - cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - gdc_log(LOG_INFO, "1 plane get output addr=%x\n", - gdc_cmd->current_addr); - } else if (gs_ex->output_buffer.plane_number == 3) { - cfg = &fh->dma_cfg.output_cfg_plane1; - cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - - cfg = &fh->dma_cfg.output_cfg_plane2; - cfg->fd = gs_ex->output_buffer.u_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->u_out_base_addr = addr; - - cfg = &fh->dma_cfg.output_cfg_plane3; - cfg->fd = gs_ex->output_buffer.v_base_fd; - cfg->dev = &fh->gdev->pdev->dev; - cfg->dir = DMA_FROM_DEVICE; - ret = gdc_buffer_get_phys(cfg, &addr); - if (ret < 0) { - gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->v_out_base_addr = addr; - - gdc_log(LOG_INFO, "3 plane get output y_addr=%x\n", - gdc_cmd->current_addr); - gdc_log(LOG_INFO, "3 plane get output u_addr=%x\n", - gdc_cmd->u_out_base_addr); - gdc_log(LOG_INFO, "3 plane get output v_addr=%x\n", - gdc_cmd->v_out_base_addr); - } - break; - case Y_GREY: - cfg = &fh->dma_cfg.output_cfg_plane1; - cfg->fd = gs_ex->output_buffer.y_base_fd; - cfg->dev = &(fh->gdev->pdev->dev); - cfg->dir = DMA_FROM_DEVICE; + plane_number = gs_ex->output_buffer.plane_number; + for (i = 0; i < plane_number; i++) { + context->dma_cfg.output_cfg[i].dma_used = 1; + cfg = &context->dma_cfg.output_cfg[i].dma_cfg; + cfg->fd = gdc_get_buffer_fd(i, &gs_ex->output_buffer); + cfg->dev = &gdc_manager.gdc_dev->pdev->dev; + cfg->dir = DMA_TO_DEVICE; ret = gdc_buffer_get_phys(cfg, &addr); if (ret < 0) { gdc_log(LOG_ERR, - "dma import output fd %d err\n", - gs_ex->output_buffer.y_base_fd); + "dma import input fd %d err\n", + cfg->fd); return -EINVAL; } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - break; - default: - gdc_log(LOG_ERR, "Error image format"); - break; + if (plane_number == 1) { + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + } else { + ret = gdc_set_output_addr(i, addr, gdc_cmd); + if (ret < 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + ret = -EINVAL; + goto dma_buf_unmap; + } + } + gdc_log(LOG_DEBUG, "plane[%d] get output addr=%lx\n", + i, addr); } + return 0; + +dma_buf_unmap: + while (i >= 0) { + cfg = &context->dma_cfg.output_cfg[i].dma_cfg; + gdc_dma_buffer_unmap(cfg); + context->dma_cfg.output_cfg[i].dma_used = 0; + i--; + } + + return ret; + } -static long gdc_process_output_ion_info(struct mgdc_fh_s *fh, +static long gdc_process_output_ion_info(struct gdc_context_s *context, struct gdc_settings_ex *gs_ex) { long ret = -1; unsigned long addr; size_t len; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; - struct gdc_config_s *gc = &gdc_cmd->gdc_config; + struct gdc_cmd_s *gdc_cmd = &context->cmd; + int i, plane_number, fd; - if (fh == NULL || gs_ex == NULL) { + if (context == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error output param\n"); return -EINVAL; } @@ -1029,162 +881,86 @@ static long gdc_process_output_ion_info(struct mgdc_fh_s *fh, __func__, gs_ex->output_buffer.plane_number); } - switch (gc->format) { - case NV12: - if (gs_ex->output_buffer.plane_number == 1) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.shared_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = gdc_cmd->buffer_addr; - gdc_log(LOG_INFO, "1 plane get output addr=%x\n", - gdc_cmd->current_addr); - } else if (gs_ex->output_buffer.plane_number == 2) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.y_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.uv_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.uv_base_fd); - return -EINVAL; - } - gdc_cmd->uv_out_base_addr = addr; - gdc_log(LOG_INFO, "2 plane get output y_addr=%x\n", - gdc_cmd->current_addr); - gdc_log(LOG_INFO, "2 plane get output uv_addr=%x\n", - gdc_cmd->uv_out_base_addr); - } - break; - case YV12: - case YUV444_P: - case RGB444_P: - if (gs_ex->output_buffer.plane_number == 1) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.shared_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - gdc_log(LOG_INFO, "1 plane get output addr=%x\n", - gdc_cmd->current_addr); - } else if (gs_ex->output_buffer.plane_number == 3) { - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.y_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.y_base_fd); - return -EINVAL; - } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.u_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.u_base_fd); - return -EINVAL; - } - gdc_cmd->u_out_base_addr = addr; - - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.v_base_fd, - (ion_phys_addr_t *)&addr, &len); - if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.v_base_fd); - return -EINVAL; - } - gdc_cmd->v_out_base_addr = addr; - gdc_log(LOG_INFO, "3 plane get output y_addr=%x\n", - gdc_cmd->current_addr); - gdc_log(LOG_INFO, "3 plane get output u_addr=%x\n", - gdc_cmd->u_out_base_addr); - gdc_log(LOG_INFO, "3 plane get output v_addr=%x\n", - gdc_cmd->v_out_base_addr); - } - break; - case Y_GREY: - ret = meson_ion_share_fd_to_phys(fh->ion_client, - gs_ex->output_buffer.shared_fd, - (ion_phys_addr_t *)&addr, &len); + plane_number = gs_ex->output_buffer.plane_number; + for (i = 0; i < plane_number; i++) { + fd = gdc_get_buffer_fd(i, &gs_ex->output_buffer); + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, + fd, (ion_phys_addr_t *)&addr, &len); if (ret < 0) { - gdc_log(LOG_ERR, "ion import out fd %d err\n", - gs_ex->output_buffer.shared_fd); + gdc_log(LOG_ERR, "ion import out fd %d err\n", fd); return -EINVAL; } - gdc_cmd->buffer_addr = addr; - gdc_cmd->current_addr = addr; - break; - default: - gdc_log(LOG_ERR, "Error image format"); - break; + + if (plane_number == 1) { + gdc_cmd->buffer_addr = addr; + gdc_cmd->current_addr = gdc_cmd->buffer_addr; + } else { + ret = gdc_set_output_addr(i, addr, gdc_cmd); + if (ret < 0) { + gdc_log(LOG_ERR, "set input addr err\n"); + return -EINVAL; + } + } + gdc_log(LOG_DEBUG, "plane[%d] get output addr=%lx\n", + i, addr); } return 0; } -static long gdc_process_ex_info(struct mgdc_fh_s *fh, +static long gdc_process_ex_info(struct gdc_context_s *context, struct gdc_settings_ex *gs_ex) { long ret; unsigned long addr = 0; size_t len; struct aml_dma_cfg *cfg = NULL; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_cmd_s *gdc_cmd = &context->cmd; + struct gdc_queue_item_s *pitem = NULL; + int i; - if (fh == NULL || gs_ex == NULL) { + if (context == NULL || gs_ex == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } + mutex_lock(&context->d_mutext); memcpy(&(gdc_cmd->gdc_config), &(gs_ex->gdc_config), sizeof(struct gdc_config_s)); - gdc_cmd->fh = fh; + for (i = 0; i < MAX_PLANE; i++) { + context->dma_cfg.input_cfg[i].dma_used = 0; + context->dma_cfg.output_cfg[i].dma_used = 0; + } + context->dma_cfg.config_cfg.dma_used = 0; + if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { - ret = gdc_process_output_ion_info(fh, gs_ex); - if (ret < 0) - return -EINVAL; + ret = gdc_process_output_ion_info(context, gs_ex); + if (ret < 0) { + ret = -EINVAL; + goto unlock_return; + } } else if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - ret = gdc_process_output_dma_info(fh, gs_ex); - if (ret < 0) - return -EINVAL; + ret = gdc_process_output_dma_info(context, gs_ex); + if (ret < 0) { + ret = -EINVAL; + goto unlock_return; + } } gdc_cmd->base_gdc = 0; if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = meson_ion_share_fd_to_phys(fh->ion_client, + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, gs_ex->config_buffer.shared_fd, (ion_phys_addr_t *)&addr, &len); if (ret < 0) { gdc_log(LOG_ERR, "ion import config fd %d failed\n", gs_ex->config_buffer.shared_fd); - return -EINVAL; + ret = -EINVAL; + goto unlock_return; } } else if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - cfg = &fh->dma_cfg.config_cfg; + context->dma_cfg.config_cfg.dma_used = 1; + cfg = &context->dma_cfg.config_cfg.dma_cfg; cfg->fd = gs_ex->config_buffer.y_base_fd; cfg->dev = &(gdc_manager.gdc_dev->pdev->dev); cfg->dir = DMA_TO_DEVICE; @@ -1192,22 +968,27 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, if (ret < 0) { gdc_log(LOG_ERR, "dma import config fd %d failed\n", gs_ex->config_buffer.shared_fd); - return -EINVAL; + ret = -EINVAL; + goto unlock_return; } } gdc_cmd->gdc_config.config_addr = addr; - gdc_log(LOG_INFO, "%s, config addr=%lx\n", __func__, addr); + gdc_log(LOG_DEBUG, "%s, config addr=%lx\n", __func__, addr); if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = gdc_process_input_ion_info(fh, gs_ex); - if (ret < 0) - return -EINVAL; + ret = gdc_process_input_ion_info(context, gs_ex); + if (ret < 0) { + ret = -EINVAL; + goto unlock_return; + } } else if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - ret = gdc_process_input_dma_info(fh, gs_ex); - if (ret < 0) - return -EINVAL; + ret = gdc_process_input_dma_info(context, gs_ex); + if (ret < 0) { + ret = -EINVAL; + goto unlock_return; + } } gdc_cmd->outplane = gs_ex->output_buffer.plane_number; if (gdc_cmd->outplane < 1 || gdc_cmd->outplane > 3) { @@ -1215,88 +996,25 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "%s, plane_number=%d invalid\n", __func__, gs_ex->output_buffer.plane_number); } - mutex_lock(&fh->gdev->d_mutext); + /* set block mode */ + context->cmd.wait_done_flag = 1; + pitem = gdc_prepare_item(context); + if (pitem == NULL) { + gdc_log(LOG_ERR, "get item error\n"); + ret = -ENOMEM; + goto unlock_return; + } + mutex_unlock(&context->d_mutext); if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); - gdc_pwr_config(true); - ret = gdc_run(gdc_cmd); - if (ret < 0) - gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); - ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); - if (ret == 0) - gdc_log(LOG_ERR, "gdc timeout\n"); - - gdc_stop(gdc_cmd); - if (!gdc_reg_store_mode) - gdc_pwr_config(false); - mutex_unlock(&fh->gdev->d_mutext); - if (gs_ex->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - gdc_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); - if (gs_ex->input_buffer.plane_number == 2) - gdc_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); - if (gs_ex->input_buffer.plane_number == 3) { - gdc_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); - gdc_buffer_unmap(&fh->dma_cfg.input_cfg_plane3); - } - } - if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) - gdc_buffer_unmap(&fh->dma_cfg.config_cfg); - if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - gdc_buffer_unmap(&fh->dma_cfg.output_cfg_plane1); - if (gs_ex->output_buffer.plane_number == 2) - gdc_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); - if (gs_ex->output_buffer.plane_number == 3) { - gdc_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); - gdc_buffer_unmap(&fh->dma_cfg.output_cfg_plane3); - } - } + gdc_wq_add_work(context, pitem); return 0; -} -u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size) -{ - u32 offset, npages; - struct page **pages = NULL; - pgprot_t pgprot; - u8 __iomem *vaddr; - int i; - - npages = PAGE_ALIGN(total_size) / PAGE_SIZE; - offset = phys & (~PAGE_MASK); - if (offset) - npages++; - pages = vmalloc(sizeof(struct page *) * npages); - if (!pages) - return NULL; - for (i = 0; i < npages; i++) { - pages[i] = phys_to_page(phys); - phys += PAGE_SIZE; - } - /*nocache*/ - pgprot = pgprot_noncached(PAGE_KERNEL); - - vaddr = vmap(pages, npages, VM_MAP, pgprot); - if (!vaddr) { - pr_err("vmaped fail, size: %d\n", - npages << PAGE_SHIFT); - vfree(pages); - return NULL; - } - vfree(pages); - - return vaddr; -} - -void unmap_virt_from_phys(u8 __iomem *vaddr) -{ - if (vaddr) { - /* unmap prevois vaddr */ - vunmap(vaddr); - vaddr = NULL; - } +unlock_return: + mutex_unlock(&context->d_mutext); + return ret; } static void release_config_firmware(struct gdc_settings_with_fw *gs_with_fw) @@ -1395,14 +1113,15 @@ release: return ret; } -static long gdc_process_with_fw(struct mgdc_fh_s *fh, +static long gdc_process_with_fw(struct gdc_context_s *context, struct gdc_settings_with_fw *gs_with_fw) { long ret = -1; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; + struct gdc_cmd_s *gdc_cmd = &context->cmd; char *fw_name = NULL; + struct gdc_queue_item_s *pitem = NULL; - if (fh == NULL || gs_with_fw == NULL) { + if (context == NULL || gs_with_fw == NULL) { gdc_log(LOG_ERR, "Error input param\n"); return -EINVAL; } @@ -1410,19 +1129,17 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, gs_with_fw->fw_info.virt_addr = NULL; gs_with_fw->fw_info.cma_pages = NULL; - memcpy(&(gdc_cmd->gdc_config), &(gs_with_fw->gdc_config), - sizeof(struct gdc_config_s)); - fw_name = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); if (!fw_name) { gdc_log(LOG_ERR, "cannot malloc fw_name!\n"); return -ENOMEM; } - - gdc_cmd->fh = fh; + mutex_lock(&context->d_mutext); + memcpy(&(gdc_cmd->gdc_config), &(gs_with_fw->gdc_config), + sizeof(struct gdc_config_s)); if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = gdc_process_output_ion_info(fh, + ret = gdc_process_output_ion_info(context, (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { ret = -EINVAL; @@ -1431,7 +1148,7 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, } else if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - ret = gdc_process_output_dma_info(fh, + ret = gdc_process_output_dma_info(context, (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { ret = -EINVAL; @@ -1442,17 +1159,23 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_ION) { /* ion alloc */ - ret = gdc_process_input_ion_info(fh, + ret = gdc_process_input_ion_info(context, (struct gdc_settings_ex *)gs_with_fw); if (ret < 0) { ret = -EINVAL; - goto unmap; + goto release_fw_name; } } else if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { /* dma alloc */ - gdc_process_input_dma_info(fh, - (struct gdc_settings_ex *)gs_with_fw); + ret = + gdc_process_input_dma_info(context, + (struct gdc_settings_ex *) + gs_with_fw); + if (ret < 0) { + ret = -EINVAL; + goto release_fw_name; + } } gdc_cmd->outplane = gs_with_fw->output_buffer.plane_number; @@ -1587,96 +1310,41 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, gdc_cmd->gdc_config.config_size = gs_with_fw->gdc_config.config_size; - mutex_lock(&fh->gdev->d_mutext); - gdc_pwr_config(true); - ret = gdc_run(gdc_cmd); - if (ret < 0) - gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); + /* set block mode */ + context->cmd.wait_done_flag = 1; - ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(40)); - if (ret == 0) - gdc_log(LOG_ERR, "gdc timeout\n"); - - gdc_stop(gdc_cmd); - if (!gdc_reg_store_mode) - gdc_pwr_config(false); - mutex_unlock(&fh->gdev->d_mutext); + pitem = gdc_prepare_item(context); + if (pitem == NULL) { + gdc_log(LOG_ERR, "get item error\n"); + ret = -ENOMEM; + goto release_fw; + } + mutex_unlock(&context->d_mutext); + gdc_wq_add_work(context, pitem); + release_config_firmware(gs_with_fw); + kfree(fw_name); + return 0; release_fw: release_config_firmware(gs_with_fw); -unmap: - if (gs_with_fw->input_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane1); - if (gs_with_fw->input_buffer.plane_number == 2) - gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); - if (gs_with_fw->input_buffer.plane_number == 3) { - gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane2); - gdc_dma_buffer_unmap(&fh->dma_cfg.input_cfg_plane3); - } - } - - if (gs_with_fw->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) { - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane1); - if (gs_with_fw->output_buffer.plane_number == 2) - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); - if (gs_with_fw->output_buffer.plane_number == 3) { - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane2); - gdc_dma_buffer_unmap(&fh->dma_cfg.output_cfg_plane3); - } - } - release_fw_name: + mutex_unlock(&context->d_mutext); kfree(fw_name); return ret; } EXPORT_SYMBOL(gdc_process_with_fw); -int write_buf_to_file(char *path, char *buf, int size) -{ - int ret = 0; - struct file *fp = NULL; - mm_segment_t old_fs; - loff_t pos = 0; - int w_size = 0; - - if (!path || !config_out_path_defined) { - gdc_log(LOG_ERR, "please define path first\n"); - return -1; - } - - /* change to KERNEL_DS address limit */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - - /* open file to write */ - fp = filp_open(path, O_WRONLY|O_CREAT, 0640); - if (IS_ERR(fp)) { - gdc_log(LOG_ERR, "open file error\n"); - ret = -1; - } - - /* Write buf to file */ - w_size = vfs_write(fp, buf, size, &pos); - gdc_log(LOG_INFO, "write w_size = %u, size = %u\n", w_size, size); - - vfs_fsync(fp, 0); - filp_close(fp, NULL); - set_fs(old_fs); - - return w_size; -} static long meson_gdc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -1; size_t len; - struct mgdc_fh_s *fh = file->private_data; + struct gdc_context_s *context = NULL; struct gdc_settings gs; - struct gdc_cmd_s *gdc_cmd = &fh->gdc_cmd; - struct gdc_config_s *gc = &gdc_cmd->gdc_config; + struct gdc_cmd_s *gdc_cmd = NULL; + struct gdc_config_s *gc = NULL; struct gdc_buf_cfg buf_cfg; struct page *cma_pages = NULL; struct gdc_settings_ex gs_ex; @@ -1686,12 +1354,12 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, ion_phys_addr_t addr; int index, dma_fd; void __user *argp = (void __user *)arg; - void __iomem *config_virt_addr; - ktime_t start_time, stop_time, diff_time; - int process_time = 0; - int i = 0; + struct gdc_queue_item_s *pitem = NULL; + struct device *dev = NULL; - start_time.tv64 = 0; + context = (struct gdc_context_s *)file->private_data; + gdc_cmd = &context->cmd; + gc = &gdc_cmd->gdc_config; switch (cmd) { case GDC_PROCESS: ret = copy_from_user(&gs, argp, sizeof(gs)); @@ -1704,13 +1372,14 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, sizeof(gs), gs.magic); //configure gdc config, buffer address and resolution - ret = meson_ion_share_fd_to_phys(fh->ion_client, + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, gs.out_fd, &addr, &len); if (ret < 0) { gdc_log(LOG_ERR, "import out fd %d failed\n", gs.out_fd); return -EINVAL; } + mutex_lock(&context->d_mutext); memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, sizeof(struct gdc_config_s)); gdc_cmd->buffer_addr = addr; @@ -1719,247 +1388,122 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gdc_cmd->base_gdc = 0; gdc_cmd->current_addr = gdc_cmd->buffer_addr; - ret = meson_ion_share_fd_to_phys(fh->ion_client, + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, gc->config_addr, &addr, &len); if (ret < 0) { gdc_log(LOG_ERR, "import config fd failed\n"); + mutex_unlock(&context->d_mutext); return -EINVAL; } gc->config_addr = addr; - ret = meson_ion_share_fd_to_phys(fh->ion_client, + ret = meson_ion_share_fd_to_phys(gdc_manager.ion_client, gs.in_fd, &addr, &len); if (ret < 0) { gdc_log(LOG_ERR, "import in fd %d failed\n", gs.in_fd); + mutex_unlock(&context->d_mutext); return -EINVAL; } ret = meson_gdc_set_input_addr(addr, gdc_cmd); if (ret != 0) { gdc_log(LOG_ERR, "set input addr failed\n"); + mutex_unlock(&context->d_mutext); return -EINVAL; } - gdc_cmd->fh = fh; gdc_cmd->outplane = 1; - mutex_lock(&fh->gdev->d_mutext); - - if (trace_mode_enable >= 1) - start_time = ktime_get(); - - gdc_pwr_config(true); - ret = gdc_run(gdc_cmd); - if (ret < 0) - gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret); - - ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(WAIT_THRESHOLD)); - if (ret == 0) - gdc_log(LOG_ERR, "gdc timeout\n"); - - if (ret == 0) { - gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", - gdc_status_read()); - - if (trace_mode_enable >= 2) { - /* dump regs */ - for (i = 0; i <= 0xFF; i += 4) - gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", - i, system_gdc_read_32(i)); - - /* dump config buffer */ - config_virt_addr = - map_virt_from_phys(gc->config_addr, - PAGE_ALIGN(gc->config_size * 4)); - ret = write_buf_to_file(config_out_file, - config_virt_addr, - (gc->config_size * 4)); - if (ret <= 0) - gdc_log(LOG_ERR, - "Failed to read_file_to_buf\n"); - unmap_virt_from_phys(config_virt_addr); - } + /* set block mode */ + context->cmd.wait_done_flag = 1; + pitem = gdc_prepare_item(context); + if (pitem == NULL) { + gdc_log(LOG_ERR, "get item error\n"); + mutex_unlock(&context->d_mutext); + return -ENOMEM; } - - gdc_stop(gdc_cmd); - - if (trace_mode_enable >= 1) { - stop_time = ktime_get(); - diff_time = ktime_sub(stop_time, start_time); - process_time = ktime_to_ms(diff_time); - if (process_time > 50) - gdc_log(LOG_ERR, "gdc process time = %d\n", - process_time); - } - if (!gdc_reg_store_mode) - gdc_pwr_config(false); - mutex_unlock(&fh->gdev->d_mutext); + mutex_unlock(&context->d_mutext); + gdc_wq_add_work(context, pitem); break; case GDC_RUN: ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) gdc_log(LOG_ERR, "copy from user failed\n"); - + mutex_lock(&context->d_mutext); memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, sizeof(struct gdc_config_s)); - gdc_cmd->buffer_addr = fh->o_paddr; - gdc_cmd->buffer_size = fh->o_len; + gdc_cmd->buffer_addr = context->o_paddr; + gdc_cmd->buffer_size = context->o_len; gdc_cmd->base_gdc = 0; gdc_cmd->current_addr = gdc_cmd->buffer_addr; - gc->config_addr = fh->c_paddr; + gc->config_addr = context->c_paddr; - ret = meson_gdc_set_input_addr(fh->i_paddr, gdc_cmd); + ret = meson_gdc_set_input_addr(context->i_paddr, gdc_cmd); if (ret != 0) { gdc_log(LOG_ERR, "set input addr failed\n"); + mutex_unlock(&context->d_mutext); return -EINVAL; } - - gdc_cmd->fh = fh; gdc_cmd->outplane = 1; - mutex_lock(&fh->gdev->d_mutext); - meson_gdc_dma_flush(&fh->gdev->pdev->dev, - fh->i_paddr, fh->i_len); - meson_gdc_dma_flush(&fh->gdev->pdev->dev, - fh->c_paddr, fh->c_len); - - if (trace_mode_enable >= 1) - start_time = ktime_get(); - - gdc_pwr_config(true); - ret = gdc_run(gdc_cmd); - if (ret < 0) - gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); - - ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(WAIT_THRESHOLD)); - if (ret == 0) - gdc_log(LOG_ERR, "gdc timeout\n"); - - if (ret == 0) { - gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", - gdc_status_read()); - - if (trace_mode_enable >= 2) { - /* dump regs */ - for (i = 0; i <= 0xFF; i += 4) - gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", - i, system_gdc_read_32(i)); - - /* dump config buffer */ - config_virt_addr = - map_virt_from_phys(gc->config_addr, - PAGE_ALIGN(gc->config_size * 4)); - ret = write_buf_to_file(config_out_file, - config_virt_addr, - (gc->config_size * 4)); - if (ret <= 0) - gdc_log(LOG_ERR, - "Failed to read_file_to_buf\n"); - unmap_virt_from_phys(config_virt_addr); - } + /* set block mode */ + context->cmd.wait_done_flag = 1; + pitem = gdc_prepare_item(context); + if (pitem == NULL) { + gdc_log(LOG_ERR, "get item error\n"); + mutex_unlock(&context->d_mutext); + return -ENOMEM; } - - gdc_stop(gdc_cmd); - if (trace_mode_enable >= 1) { - stop_time = ktime_get(); - diff_time = ktime_sub(stop_time, start_time); - process_time = ktime_to_ms(diff_time); - if (process_time > 50) - gdc_log(LOG_ERR, "gdc process time = %d\n", - process_time); - } - meson_gdc_cache_flush(&fh->gdev->pdev->dev, - fh->o_paddr, fh->o_len); - - if (!gdc_reg_store_mode) - gdc_pwr_config(false); - mutex_unlock(&fh->gdev->d_mutext); + mutex_unlock(&context->d_mutext); + dev = &gdc_manager.gdc_dev->pdev->dev; + meson_gdc_dma_flush(dev, + context->i_paddr, context->i_len); + meson_gdc_dma_flush(dev, + context->c_paddr, context->c_len); + gdc_wq_add_work(context, pitem); + meson_gdc_cache_flush(dev, + context->o_paddr, context->o_len); break; case GDC_HANDLE: ret = copy_from_user(&gs, argp, sizeof(gs)); if (ret < 0) gdc_log(LOG_ERR, "copy from user failed\n"); - + mutex_lock(&context->d_mutext); memcpy(&gdc_cmd->gdc_config, &gs.gdc_config, sizeof(struct gdc_config_s)); - gdc_cmd->buffer_addr = fh->o_paddr; - gdc_cmd->buffer_size = fh->o_len; + gdc_cmd->buffer_addr = context->o_paddr; + gdc_cmd->buffer_size = context->o_len; gdc_cmd->base_gdc = 0; gdc_cmd->current_addr = gdc_cmd->buffer_addr; - gc->config_addr = fh->c_paddr; + gc->config_addr = context->c_paddr; - gdc_cmd->fh = fh; gdc_cmd->outplane = 1; - mutex_lock(&fh->gdev->d_mutext); - ret = meson_gdc_init_dma_addr(fh, &gs); + /* set block mode */ + context->cmd.wait_done_flag = 1; + ret = meson_gdc_init_dma_addr(context, &gs); if (ret != 0) { - mutex_unlock(&fh->gdev->d_mutext); + mutex_unlock(&context->d_mutext); gdc_log(LOG_ERR, "Failed to init dma addr"); return ret; } - meson_gdc_dma_flush(&fh->gdev->pdev->dev, - fh->c_paddr, fh->c_len); - - - if (trace_mode_enable >= 1) - start_time = ktime_get(); - - gdc_pwr_config(true); - ret = gdc_run(gdc_cmd); - if (ret < 0) - gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); - - ret = wait_for_completion_timeout(&fh->gdev->d_com, - msecs_to_jiffies(WAIT_THRESHOLD)); - if (ret == 0) - gdc_log(LOG_ERR, "gdc timeout\n"); - - if (ret == 0) { - gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", - gdc_status_read()); - - if (trace_mode_enable >= 2) { - /* dump regs */ - for (i = 0; i <= 0xFF; i += 4) - gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", - i, system_gdc_read_32(i)); - - /* dump config buffer */ - config_virt_addr = - map_virt_from_phys(gc->config_addr, - PAGE_ALIGN(gc->config_size * 4)); - ret = write_buf_to_file(config_out_file, - config_virt_addr, - (gc->config_size * 4)); - if (ret <= 0) - gdc_log(LOG_ERR, - "Failed to read_file_to_buf\n"); - unmap_virt_from_phys(config_virt_addr); - } + pitem = gdc_prepare_item(context); + if (pitem == NULL) { + gdc_log(LOG_ERR, "get item error\n"); + mutex_unlock(&context->d_mutext); + return -ENOMEM; } + mutex_unlock(&context->d_mutext); - gdc_stop(gdc_cmd); - - if (trace_mode_enable >= 1) { - stop_time = ktime_get(); - diff_time = ktime_sub(stop_time, start_time); - process_time = ktime_to_ms(diff_time); - if (process_time > 50) - gdc_log(LOG_ERR, "gdc process time = %d\n", - process_time); - } - meson_gdc_cache_flush(&fh->gdev->pdev->dev, - fh->o_paddr, fh->o_len); - meson_gdc_deinit_dma_addr(fh); - - if (!gdc_reg_store_mode) - gdc_pwr_config(false); - mutex_unlock(&fh->gdev->d_mutext); + dev = &gdc_manager.gdc_dev->pdev->dev; + meson_gdc_dma_flush(dev, + context->c_paddr, context->c_len); + gdc_wq_add_work(context, pitem); + meson_gdc_cache_flush(dev, + context->o_paddr, context->o_len); + meson_gdc_deinit_dma_addr(context); break; case GDC_REQUEST_BUFF: ret = copy_from_user(&buf_cfg, argp, sizeof(buf_cfg)); @@ -1969,15 +1513,17 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } buf_cfg.len = PAGE_ALIGN(buf_cfg.len); - - cma_pages = dma_alloc_from_contiguous(&fh->gdev->pdev->dev, + dev = &gdc_manager.gdc_dev->pdev->dev; + cma_pages = dma_alloc_from_contiguous + (dev, buf_cfg.len >> PAGE_SHIFT, 0); if (cma_pages != NULL) { - fh->mmap_type = buf_cfg.type; - ret = meson_gdc_set_buff(fh, cma_pages, buf_cfg.len); + context->mmap_type = buf_cfg.type; + ret = meson_gdc_set_buff(context, + cma_pages, buf_cfg.len); if (ret != 0) { dma_release_from_contiguous( - &fh->gdev->pdev->dev, + dev, cma_pages, buf_cfg.len >> PAGE_SHIFT); gdc_log(LOG_ERR, "Failed to set buff\n"); @@ -1995,15 +1541,13 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gdc_log(LOG_ERR, "copy from user failed\n"); memcpy(&gdc_cmd->gdc_config, &gs_with_fw.gdc_config, sizeof(struct gdc_config_s)); - ret = gdc_process_with_fw(fh, &gs_with_fw); + ret = gdc_process_with_fw(context, &gs_with_fw); break; case GDC_PROCESS_EX: ret = copy_from_user(&gs_ex, argp, sizeof(gs_ex)); if (ret < 0) gdc_log(LOG_ERR, "copy from user failed\n"); - memcpy(&gdc_cmd->gdc_config, &gs_ex.gdc_config, - sizeof(struct gdc_config_s)); - ret = gdc_process_ex_info(fh, &gs_ex); + ret = gdc_process_ex_info(context, &gs_ex); break; case GDC_REQUEST_DMA_BUFF: ret = copy_from_user(&gdc_req_buf, argp, @@ -2070,21 +1614,22 @@ static int meson_gdc_mmap(struct file *file_p, { int ret = -1; unsigned long buf_len = 0; - struct mgdc_fh_s *fh = file_p->private_data; + struct gdc_context_s *context = NULL; buf_len = vma->vm_end - vma->vm_start; + context = (struct gdc_context_s *)file_p->private_data; - switch (fh->mmap_type) { + switch (context->mmap_type) { case INPUT_BUFF_TYPE: ret = remap_pfn_range(vma, vma->vm_start, - fh->i_paddr >> PAGE_SHIFT, + context->i_paddr >> PAGE_SHIFT, buf_len, vma->vm_page_prot); if (ret != 0) gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; case OUTPUT_BUFF_TYPE: ret = remap_pfn_range(vma, vma->vm_start, - fh->o_paddr >> PAGE_SHIFT, + context->o_paddr >> PAGE_SHIFT, buf_len, vma->vm_page_prot); if (ret != 0) gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); @@ -2092,13 +1637,13 @@ static int meson_gdc_mmap(struct file *file_p, break; case CONFIG_BUFF_TYPE: ret = remap_pfn_range(vma, vma->vm_start, - fh->c_paddr >> PAGE_SHIFT, + context->c_paddr >> PAGE_SHIFT, buf_len, vma->vm_page_prot); if (ret != 0) gdc_log(LOG_ERR, "Failed to mmap input buffer\n"); break; default: - gdc_log(LOG_ERR, "Error mmap type:0x%x\n", fh->mmap_type); + gdc_log(LOG_ERR, "Error mmap type:0x%x\n", context->mmap_type); break; } @@ -2244,7 +1789,7 @@ static ssize_t config_out_path_show(struct device *dev, static ssize_t config_out_path_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - if (strlen(buf) >= sizeof(config_out_file)) { + if (strlen(buf) >= CONFIG_PATH_LENG) { pr_info("err: path too long\n"); } else { strncpy(config_out_file, buf, CONFIG_PATH_LENG - 1); @@ -2259,10 +1804,7 @@ static DEVICE_ATTR(config_out_path, 0664, config_out_path_show, irqreturn_t gdc_interrupt_handler(int irq, void *param) { - struct meson_gdc_dev_t *gdc_dev = param; - - complete(&gdc_dev->d_com); - + complete(&gdc_manager.event.d_com); return IRQ_HANDLED; } @@ -2287,7 +1829,9 @@ static int gdc_platform_probe(struct platform_device *pdev) return -ENOMEM; } - of_reserved_mem_device_init(&(pdev->dev)); + rc = of_reserved_mem_device_init(&pdev->dev); + if (rc != 0) + gdc_log(LOG_INFO, "reserve_mem is not used\n"); /* alloc mem to store config out path*/ config_out_file = kzalloc(CONFIG_PATH_LENG, GFP_KERNEL); @@ -2308,7 +1852,6 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_dev->misc_dev.minor = meson_gdc_dev.minor; gdc_dev->misc_dev.name = meson_gdc_dev.name; gdc_dev->misc_dev.fops = meson_gdc_dev.fops; - spin_lock_init(&gdc_dev->slock); gdc_dev->irq = platform_get_irq(pdev, 0); if (gdc_dev->irq < 0) { @@ -2347,17 +1890,14 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_log(LOG_INFO, "gdc axi clk is %d MHZ\n", rc/1000000); } - mutex_init(&gdc_dev->d_mutext); - init_completion(&gdc_dev->d_com); - rc = devm_request_irq(&pdev->dev, gdc_dev->irq, gdc_interrupt_handler, IRQF_SHARED, "gdc", gdc_dev); if (rc != 0) gdc_log(LOG_ERR, "cannot create irq func gdc\n"); - gdc_manager.buffer = gdc_dma_buffer_create(); - gdc_manager.gdc_dev = gdc_dev; + gdc_wq_init(gdc_dev); + rc = misc_register(&gdc_dev->misc_dev); if (rc < 0) { dev_err(&pdev->dev, @@ -2395,11 +1935,9 @@ static int gdc_platform_remove(struct platform_device *pdev) device_remove_file(meson_gdc_dev.this_device, &dev_attr_config_out_path); - gdc_dma_buffer_destroy(gdc_manager.buffer); - gdc_manager.gdc_dev = NULL; - kfree(config_out_file); config_out_file = NULL; + gdc_wq_deinit(); misc_deregister(&meson_gdc_dev); return 0; diff --git a/drivers/amlogic/media/gdc/app/gdc_wq.c b/drivers/amlogic/media/gdc/app/gdc_wq.c new file mode 100644 index 000000000000..e5b53f3713a1 --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_wq.c @@ -0,0 +1,508 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_wq.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "system_log.h" + +#include +#include +#include +#include + +#include "gdc_config.h" +#include "gdc_dmabuf.h" +#include "gdc_wq.h" + +#define WAIT_THRESHOLD 1000 + +u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size) +{ + u32 offset, npages; + struct page **pages = NULL; + pgprot_t pgprot; + u8 __iomem *vaddr; + int i; + + npages = PAGE_ALIGN(total_size) / PAGE_SIZE; + offset = phys & (~PAGE_MASK); + if (offset) + npages++; + pages = vmalloc(sizeof(struct page *) * npages); + if (!pages) + return NULL; + for (i = 0; i < npages; i++) { + pages[i] = phys_to_page(phys); + phys += PAGE_SIZE; + } + /*nocache*/ + pgprot = pgprot_noncached(PAGE_KERNEL); + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("vmaped fail, size: %d\n", + npages << PAGE_SHIFT); + vfree(pages); + return NULL; + } + vfree(pages); + + return vaddr; +} + +void unmap_virt_from_phys(u8 __iomem *vaddr) +{ + if (vaddr) { + /* unmap prevois vaddr */ + vunmap(vaddr); + vaddr = NULL; + } +} + +static int write_buf_to_file(char *path, char *buf, int size) +{ + int ret = 0; + struct file *fp = NULL; + mm_segment_t old_fs; + loff_t pos = 0; + int w_size = 0; + + if (!path || !config_out_path_defined) { + gdc_log(LOG_ERR, "please define path first\n"); + return -1; + } + + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file to write */ + fp = filp_open(path, O_WRONLY|O_CREAT, 0640); + if (IS_ERR(fp)) { + gdc_log(LOG_ERR, "open file error\n"); + ret = -1; + } + + /* Write buf to file */ + w_size = vfs_write(fp, buf, size, &pos); + gdc_log(LOG_INFO, "write w_size = %u, size = %u\n", w_size, size); + + vfs_fsync(fp, 0); + filp_close(fp, NULL); + set_fs(old_fs); + + return w_size; +} + +static void dump_config_file(struct gdc_config_s *gc) +{ + void __iomem *config_virt_addr; + int ret; + + /* dump config buffer */ + config_virt_addr = + map_virt_from_phys(gc->config_addr, + PAGE_ALIGN(gc->config_size * 4)); + ret = write_buf_to_file(config_out_file, + config_virt_addr, + (gc->config_size * 4)); + if (ret <= 0) + gdc_log(LOG_ERR, + "Failed to read_file_to_buf\n"); + unmap_virt_from_phys(config_virt_addr); +} + +static void dump_gdc_regs(void) +{ + int i; + + for (i = 0; i <= 0xFF; i += 4) + gdc_log(LOG_ERR, "reg[0x%x] = 0x%x\n", + i, system_gdc_read_32(i)); + +} + +static int gdc_process_work_queue(struct gdc_context_s *wq) +{ + struct gdc_queue_item_s *pitem; + struct list_head *head = &wq->work_queue, *pos; + int ret = 0, i = 0; + unsigned int block_mode; + int timeout = 0; + ktime_t start_time, stop_time, diff_time; + int process_time = 0; + + if (wq->gdc_request_exit) + goto exit; + gdc_manager.gdc_state = GDC_STATE_RUNNING; + pos = head->next; + if (pos != head) { /* current work queue not empty. */ + if (wq != gdc_manager.last_wq) { /* maybe */ + /* modify the first item . */ + pitem = (struct gdc_queue_item_s *)pos; + if (!pitem) { + gdc_log(LOG_ERR, "can't get pitem\n"); + ret = -1; + goto exit; + } + } else + /* modify the first item . */ + pitem = (struct gdc_queue_item_s *)pos; + + } else { + ret = -1; + goto exit; + } + do { + block_mode = pitem->cmd.wait_done_flag; + if (trace_mode_enable >= 1) + start_time = ktime_get(); + ret = gdc_run(&pitem->cmd); + if (ret < 0) + gdc_log(LOG_ERR, "gdc process failed ret = %d\n", ret); + timeout = wait_for_completion_timeout(&gdc_manager.event.d_com, + msecs_to_jiffies(WAIT_THRESHOLD)); + if (timeout == 0) { + gdc_log(LOG_ERR, "gdc timeout, status = 0x%x\n", + gdc_status_read()); + /*soft_rst(); */ + if (trace_mode_enable >= 2) { + /* dump regs */ + dump_gdc_regs(); + /* dump config buffer */ + dump_config_file(&pitem->cmd.gdc_config); + } + } + gdc_stop(&pitem->cmd); + if (trace_mode_enable >= 1) { + stop_time = ktime_get(); + diff_time = ktime_sub(stop_time, start_time); + process_time = ktime_to_ms(diff_time); + if (process_time > 50) + gdc_log(LOG_ERR, "gdc process time = %d\n", + process_time); + } + + /* if block mode (cmd) */ + if (block_mode) { + pitem->cmd.wait_done_flag = 0; + wake_up_interruptible(&wq->cmd_complete); + } + spin_lock(&wq->lock); + pos = pos->next; + list_move_tail(&pitem->list, &wq->free_queue); + spin_unlock(&wq->lock); + /* if dma buf detach it */ + for (i = 0; i < MAX_PLANE; i++) { + if (pitem->dma_cfg.input_cfg[i].dma_used) { + gdc_dma_buffer_unmap_info(gdc_manager.buffer, + &pitem->dma_cfg.input_cfg[i].dma_cfg); + pitem->dma_cfg.input_cfg[i].dma_used = 0; + } + if (pitem->dma_cfg.output_cfg[i].dma_used) { + gdc_dma_buffer_unmap_info(gdc_manager.buffer, + &pitem->dma_cfg.output_cfg[i].dma_cfg); + pitem->dma_cfg.output_cfg[i].dma_used = 0; + } + } + if (pitem->dma_cfg.config_cfg.dma_used) { + gdc_dma_buffer_unmap_info(gdc_manager.buffer, + &pitem->dma_cfg.config_cfg.dma_cfg); + pitem->dma_cfg.config_cfg.dma_used = 0; + } + pitem = (struct gdc_queue_item_s *)pos; + } while (pos != head); + gdc_manager.last_wq = wq; +exit: + if (wq->gdc_request_exit) + complete(&gdc_manager.event.process_complete); + gdc_manager.gdc_state = GDC_STATE_IDLE; + return ret; +} + +static inline struct gdc_context_s *get_next_gdc_work_queue( + struct gdc_manager_s *manager) +{ + struct gdc_context_s *pcontext; + + spin_lock(&manager->event.sem_lock); + list_for_each_entry(pcontext, &manager->process_queue, list) { + /* not lock maybe delay to next time. */ + if (!list_empty(&pcontext->work_queue)) { + /* move head . */ + list_move(&manager->process_queue, &pcontext->list); + spin_unlock(&manager->event.sem_lock); + return pcontext; + } + } + spin_unlock(&manager->event.sem_lock); + return NULL; +} + +static int gdc_monitor_thread(void *data) +{ + int ret; + struct gdc_manager_s *manager = (struct gdc_manager_s *)data; + + gdc_log(LOG_INFO, "gdc workqueue monitor start\n"); + /* setup current_wq here. */ + while (manager->process_queue_state != GDC_PROCESS_QUEUE_STOP) { + ret = down_interruptible(&manager->event.cmd_in_sem); + gdc_pwr_config(true); + while ((manager->current_wq = + get_next_gdc_work_queue(manager)) != NULL) + gdc_process_work_queue(manager->current_wq); + if (!gdc_reg_store_mode) + gdc_pwr_config(false); + } + gdc_log(LOG_INFO, "exit gdc_monitor_thread\n"); + return 0; +} + +static int gdc_start_monitor(void) +{ + int ret = 0; + + gdc_log(LOG_INFO, "gdc start monitor\n"); + gdc_manager.process_queue_state = GDC_PROCESS_QUEUE_START; + gdc_manager.gdc_thread = kthread_run(gdc_monitor_thread, + &gdc_manager, + "gdc_monitor"); + if (IS_ERR(gdc_manager.gdc_thread)) { + ret = PTR_ERR(gdc_manager.gdc_thread); + gdc_log(LOG_ERR, "failed to start kthread (%d)\n", ret); + } + return ret; +} + +static int gdc_stop_monitor(void) +{ + gdc_log(LOG_INFO, "gdc stop monitor\n"); + if (gdc_manager.gdc_thread) { + gdc_manager.process_queue_state = GDC_PROCESS_QUEUE_STOP; + up(&gdc_manager.event.cmd_in_sem); + kthread_stop(gdc_manager.gdc_thread); + gdc_manager.gdc_thread = NULL; + } + return 0; +} + +static inline int work_queue_no_space(struct gdc_context_s *queue) +{ + return list_empty(&queue->free_queue); +} + +struct gdc_context_s *create_gdc_work_queue(void) +{ + int i; + struct gdc_queue_item_s *p_item; + struct gdc_context_s *gdc_work_queue; + int empty; + + gdc_work_queue = kzalloc(sizeof(struct gdc_context_s), GFP_KERNEL); + if (IS_ERR(gdc_work_queue)) { + gdc_log(LOG_ERR, "can't create work queue\n"); + return NULL; + } + gdc_work_queue->gdc_request_exit = 0; + INIT_LIST_HEAD(&gdc_work_queue->work_queue); + INIT_LIST_HEAD(&gdc_work_queue->free_queue); + init_waitqueue_head(&gdc_work_queue->cmd_complete); + mutex_init(&gdc_work_queue->d_mutext); + spin_lock_init(&gdc_work_queue->lock); /* for process lock. */ + for (i = 0; i < MAX_GDC_CMD; i++) { + p_item = kcalloc(1, + sizeof(struct gdc_queue_item_s), + GFP_KERNEL); + if (IS_ERR(p_item)) { + gdc_log(LOG_ERR, "can't request queue item memory\n"); + goto fail; + } + list_add_tail(&p_item->list, &gdc_work_queue->free_queue); + } + + /* put this process queue into manager queue list. */ + /* maybe process queue is changing . */ + spin_lock(&gdc_manager.event.sem_lock); + empty = list_empty(&gdc_manager.process_queue); + list_add_tail(&gdc_work_queue->list, &gdc_manager.process_queue); + spin_unlock(&gdc_manager.event.sem_lock); + return gdc_work_queue; /* find it */ +fail: + { + struct list_head *head; + struct gdc_queue_item_s *tmp; + + head = &gdc_work_queue->free_queue; + list_for_each_entry_safe(p_item, tmp, head, list) { + if (p_item) { + list_del(&p_item->list); + kfree(p_item); + } + } + return NULL; + } +} +EXPORT_SYMBOL(create_gdc_work_queue); + +int destroy_gdc_work_queue(struct gdc_context_s *gdc_work_queue) +{ + struct gdc_queue_item_s *pitem, *tmp; + struct list_head *head; + int empty, timeout = 0; + + if (gdc_work_queue) { + /* first detatch it from the process queue,then delete it . */ + /* maybe process queue is changing .so we lock it. */ + spin_lock(&gdc_manager.event.sem_lock); + list_del(&gdc_work_queue->list); + empty = list_empty(&gdc_manager.process_queue); + spin_unlock(&gdc_manager.event.sem_lock); + if ((gdc_manager.current_wq == gdc_work_queue) && + (gdc_manager.gdc_state == GDC_STATE_RUNNING)) { + gdc_work_queue->gdc_request_exit = 1; + timeout = wait_for_completion_timeout( + &gdc_manager.event.process_complete, + msecs_to_jiffies(500)); + if (!timeout) + gdc_log(LOG_ERR, "wait timeout\n"); + /* condition so complex ,simplify it . */ + gdc_manager.last_wq = NULL; + } /* else we can delete it safely. */ + + head = &gdc_work_queue->work_queue; + list_for_each_entry_safe(pitem, tmp, head, list) { + if (pitem) { + list_del(&pitem->list); + kfree(pitem); + } + } + head = &gdc_work_queue->free_queue; + list_for_each_entry_safe(pitem, tmp, head, list) { + if (pitem) { + list_del(&pitem->list); + kfree(pitem); + } + } + + kfree(gdc_work_queue); + gdc_work_queue = NULL; + return 0; + } + + return -1; +} +EXPORT_SYMBOL(destroy_gdc_work_queue); + +void *gdc_prepare_item(struct gdc_context_s *wq) +{ + struct gdc_queue_item_s *pitem; + + if (work_queue_no_space(wq)) { + gdc_log(LOG_ERR, "work queue no space\n"); + return NULL; + } + + pitem = list_entry(wq->free_queue.next, struct gdc_queue_item_s, list); + if (IS_ERR(pitem)) + return NULL; + + memcpy(&pitem->cmd, &wq->cmd, sizeof(struct gdc_cmd_s)); + memcpy(&pitem->dma_cfg, &wq->dma_cfg, sizeof(struct gdc_dma_cfg_t)); + return pitem; +} + +int gdc_wq_add_work(struct gdc_context_s *wq, + struct gdc_queue_item_s *pitem) +{ + gdc_log(LOG_DEBUG, "gdc add work\n"); + spin_lock(&wq->lock); + list_move_tail(&pitem->list, &wq->work_queue); + spin_unlock(&wq->lock); + gdc_log(LOG_DEBUG, "gdc add work ok\n"); + /* only read not need lock */ + if (gdc_manager.event.cmd_in_sem.count == 0) + up(&gdc_manager.event.cmd_in_sem);/* new cmd come in */ + /* add block mode if() */ + if (pitem->cmd.wait_done_flag) { + wait_event_interruptible(wq->cmd_complete, + pitem->cmd.wait_done_flag == 0); + /* interruptible_sleep_on(&wq->cmd_complete); */ + } + return 0; +} + +int gdc_wq_init(struct meson_gdc_dev_t *gdc_dev) +{ + gdc_log(LOG_INFO, "init gdc device\n"); + gdc_manager.gdc_dev = gdc_dev; + + /* prepare bottom half */ + spin_lock_init(&gdc_manager.event.sem_lock); + sema_init(&gdc_manager.event.cmd_in_sem, 1); + init_completion(&gdc_manager.event.d_com); + init_completion(&gdc_manager.event.process_complete); + INIT_LIST_HEAD(&gdc_manager.process_queue); + gdc_manager.last_wq = NULL; + gdc_manager.gdc_thread = NULL; + gdc_manager.buffer = gdc_dma_buffer_create(); + if (!gdc_manager.buffer) + return -1; + if (!gdc_manager.ion_client) + gdc_manager.ion_client = + meson_ion_client_create(-1, "meson-gdc"); + + if (gdc_start_monitor()) { + gdc_log(LOG_ERR, "gdc create thread error\n"); + return -1; + } + return 0; +} + +int gdc_wq_deinit(void) +{ + if (gdc_manager.ion_client) { + ion_client_destroy(gdc_manager.ion_client); + gdc_manager.ion_client = NULL; + } + + gdc_stop_monitor(); + gdc_log(LOG_INFO, "deinit gdc device\n"); + + gdc_dma_buffer_destroy(gdc_manager.buffer); + gdc_manager.buffer = NULL; + gdc_manager.gdc_dev = NULL; + return 0; +} diff --git a/drivers/amlogic/media/gdc/app/gdc_wq.h b/drivers/amlogic/media/gdc/app/gdc_wq.h new file mode 100644 index 000000000000..265ac276a5de --- /dev/null +++ b/drivers/amlogic/media/gdc/app/gdc_wq.h @@ -0,0 +1,95 @@ +/* + * drivers/amlogic/media/gdc/app/gdc_wq.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _GDC_WQ_H_ +#define _GDC_WQ_H_ + +#include +#include +#include +#include +#include + +struct gdc_cmd_s; +#define MAX_GDC_CMD 32 /* 64 */ +#define MAX_PLANE 3 +#define GDC_STATE_IDLE 0 +#define GDC_STATE_RUNNING 1 + +#define GDC_PROCESS_QUEUE_START 0 +#define GDC_PROCESS_QUEUE_STOP 1 + +struct gdc_dmabuf_cfg_s { + int dma_used; + struct aml_dma_cfg dma_cfg; +}; + +struct gdc_dma_cfg_t { + struct gdc_dmabuf_cfg_s config_cfg; + struct gdc_dmabuf_cfg_s input_cfg[MAX_PLANE]; + struct gdc_dmabuf_cfg_s output_cfg[MAX_PLANE]; +}; + +struct gdc_queue_item_s { + struct list_head list; + struct gdc_cmd_s cmd; + struct gdc_dma_cfg_t dma_cfg; +}; + +struct gdc_context_s { + /* connect all process in one queue for RR process. */ + struct list_head list; + /* current wq configuration */ + uint32_t mmap_type; + dma_addr_t i_paddr; + dma_addr_t o_paddr; + dma_addr_t c_paddr; + void *i_kaddr; + void *o_kaddr; + void *c_kaddr; + unsigned long i_len; + unsigned long o_len; + unsigned long c_len; + struct gdc_dma_cfg y_dma_cfg; + struct gdc_dma_cfg uv_dma_cfg; + struct gdc_dma_cfg_t dma_cfg; + struct mutex d_mutext; + + struct gdc_cmd_s cmd; + struct list_head work_queue; + struct list_head free_queue; + wait_queue_head_t cmd_complete; + int gdc_request_exit; + spinlock_t lock;/* for get and release item. */ +}; + +extern unsigned int gdc_reg_store_mode; +extern int trace_mode_enable; +extern char *config_out_file; +extern int config_out_path_defined; + +u8 __iomem *map_virt_from_phys(phys_addr_t phys, unsigned long total_size); +void unmap_virt_from_phys(u8 __iomem *vaddr); + +int gdc_wq_init(struct meson_gdc_dev_t *gdc_dev); +int gdc_wq_deinit(void); +void *gdc_prepare_item(struct gdc_context_s *wq); +int gdc_wq_add_work(struct gdc_context_s *wq, + struct gdc_queue_item_s *pitem); +struct gdc_context_s *create_gdc_work_queue(void); +int destroy_gdc_work_queue(struct gdc_context_s *gdc_work_queue); +#endif diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index f0695c2ab148..5aa1c3165dbd 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -21,8 +21,6 @@ #include #include -extern struct gdc_manager_s gdc_manager; - enum gdc_memtype_s { AML_GDC_MEM_ION, AML_GDC_MEM_DMABUF, @@ -216,13 +214,7 @@ struct gdc_cmd_s { }; uint32_t v_base_addr; - //when inititialised this callback will be called - //to update frame buffer addresses and offsets - void (*get_frame_buffer)(uint32_t y_base_addr, - uint32_t uv_base_addr, - uint32_t y_line_offset, - uint32_t uv_line_offset); - void *fh; + unsigned char wait_done_flag; }; /* path: "/vendor/lib/firmware/gdc/" */ diff --git a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h index 1d47b0d249e4..866b2756f7c1 100644 --- a/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h +++ b/drivers/amlogic/media/gdc/inc/gdc/gdc_config.h @@ -26,57 +26,40 @@ #include "system_gdc_io.h" #include "gdc_api.h" #include "gdc_dmabuf.h" -struct gdc_cmd_s; -struct gdc_manager_s { - struct aml_dma_buffer *buffer; - struct meson_gdc_dev_t *gdc_dev; -}; +struct gdc_context_s; struct meson_gdc_dev_t { struct platform_device *pdev; - void *reg_base; + int irq; struct clk *clk_core; struct clk *clk_axi; - spinlock_t slock; - struct mutex d_mutext; - struct completion d_com; - int irq; struct miscdevice misc_dev; }; -struct gdc_dma_cfg_t { - struct aml_dma_cfg config_cfg; - struct aml_dma_cfg input_cfg_plane1; - struct aml_dma_cfg input_cfg_plane2; - struct aml_dma_cfg input_cfg_plane3; - struct aml_dma_cfg output_cfg_plane1; - struct aml_dma_cfg output_cfg_plane2; - struct aml_dma_cfg output_cfg_plane3; +struct gdc_event_s { + struct completion d_com; + struct completion process_complete; + /* for queue switch and create destroy queue. */ + spinlock_t sem_lock; + struct semaphore cmd_in_sem; }; -struct mgdc_fh_s { - struct list_head list; - wait_queue_head_t irq_queue; - struct meson_gdc_dev_t *gdev; - char task_comm[32]; +struct gdc_manager_s { struct ion_client *ion_client; - struct gdc_cmd_s gdc_cmd; - uint32_t mmap_type; - dma_addr_t i_paddr; - dma_addr_t o_paddr; - dma_addr_t c_paddr; - void *i_kaddr; - void *o_kaddr; - void *c_kaddr; - unsigned long i_len; - unsigned long o_len; - unsigned long c_len; - struct gdc_dma_cfg y_dma_cfg; - struct gdc_dma_cfg uv_dma_cfg; - struct gdc_dma_cfg_t dma_cfg; + struct list_head process_queue; + struct gdc_context_s *current_wq; + struct gdc_context_s *last_wq; + struct task_struct *gdc_thread; + struct gdc_event_s event; + struct aml_dma_buffer *buffer; + int gdc_state; + int process_queue_state;//thread running flag + struct meson_gdc_dev_t *gdc_dev; }; +extern struct gdc_manager_s gdc_manager; + irqreturn_t interrupt_handler_next(int irq, void *param); // ----------------------------------- // // Instance 'gdc' of module 'gdc_ip_config' diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h index 53380bd784aa..cee79b4c956a 100644 --- a/drivers/amlogic/media/gdc/inc/sys/system_log.h +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -20,14 +20,13 @@ //changeable logs #include -extern unsigned int gdc_log_level; +extern int gdc_log_level; enum log_level_e { - LOG_NO_THING, LOG_CRIT, - LOG_ERR = 0, + LOG_ERR, + LOG_INFO = 0, LOG_WARNING, - LOG_INFO, LOG_DEBUG, LOG_MAX }; diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c index aabc66b95935..30ead281ff22 100644 --- a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -29,7 +29,6 @@ #include "system_log.h" #include "gdc_config.h" - /** * Configure the output gdc configuration address/size * @@ -462,6 +461,7 @@ int gdc_process_rgb444p(struct gdc_cmd_s *gdc_cmd, return 0; } +#if 0 /** * This function gets the GDC output frame addresses * @@ -507,7 +507,7 @@ int gdc_get_frame(struct gdc_cmd_s *gdc_cmd) //spin_unlock_irqrestore(&gdev->slock, flags); return 0; } - +#endif /** * This function set the GDC power on/off * diff --git a/drivers/amlogic/media/osd/osd_drm.c b/drivers/amlogic/media/osd/osd_drm.c index 6aaf297562e7..662fdbf1dc40 100644 --- a/drivers/amlogic/media/osd/osd_drm.c +++ b/drivers/amlogic/media/osd/osd_drm.c @@ -57,7 +57,6 @@ static int parse_para(const char *para, int para_num, int *result) if (!para) return 0; - params = kstrdup(para, GFP_KERNEL); params_base = params; token = params; @@ -130,18 +129,24 @@ static ssize_t logmodule_write_file( size_t count, loff_t *ppos) { unsigned int log_module; - char buf[128]; + char *buf = NULL; int ret = 0; if (count > sizeof(buf) || count <= 0) return -EINVAL; - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; + } if (buf[count - 1] == '\n') buf[count - 1] = '\0'; ret = kstrtoint(buf, 0, &log_module); osd_log_info("log_level: %d->%d\n", osd_log_module, log_module); osd_log_module = log_module; + kfree(buf); return count; } @@ -191,16 +196,20 @@ static ssize_t osd_display_debug_write_file(struct file *file, { struct seq_file *s = file->private_data; int osd_id = *(int *)s; - char buf[128]; + char *buf = NULL; u32 osd_display_debug_enable; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &osd_display_debug_enable); osd_set_display_debug(osd_id, osd_display_debug_enable); + kfree(buf); return count; } @@ -231,17 +240,21 @@ static ssize_t blank_read_file(struct file *file, char __user *userbuf, static ssize_t blank_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &osd_enable[osd_id]); osd_enable_hw(osd_id, (osd_enable[osd_id] != 0) ? 0 : 1); + kfree(buf); return count; } @@ -264,18 +277,22 @@ static ssize_t free_scale_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; unsigned int free_scale_enable; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &free_scale_enable); osd_set_free_scale_enable_hw(osd_id, free_scale_enable); + kfree(buf); return count; } @@ -298,20 +315,25 @@ static ssize_t free_scale_axis_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; int parsed[4]; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; + } buf[count] = 0; if (likely(parse_para(buf, 4, parsed) == 4)) osd_set_free_scale_axis_hw(osd_id, parsed[0], parsed[1], parsed[2], parsed[3]); else osd_log_err("set free scale axis error\n"); + kfree(buf); return count; } @@ -335,20 +357,25 @@ static ssize_t window_axis_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; int parsed[4]; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; + } buf[count] = 0; if (likely(parse_para(buf, 4, parsed) == 4)) osd_set_window_axis_hw(osd_id, parsed[0], parsed[1], parsed[2], parsed[3]); else osd_log_err("set window axis error\n"); + kfree(buf); return count; } @@ -375,20 +402,24 @@ static ssize_t osd_reverse_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; unsigned int osd_reverse = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &osd_reverse); if (osd_reverse >= REVERSE_MAX) osd_reverse = REVERSE_FALSE; osd_set_reverse_hw(osd_id, osd_reverse, 1); + kfree(buf); return count; } @@ -411,18 +442,22 @@ static ssize_t osd_order_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; unsigned int order = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &order); osd_set_order_hw(osd_id, order); + kfree(buf); return count; } @@ -447,17 +482,21 @@ static ssize_t osd_afbcd_write_file(struct file *file, { struct seq_file *s = file->private_data; int osd_id = *(int *)s; - char buf[128]; + char *buf = NULL; unsigned int enable_afbcd = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &enable_afbcd); osd_log_info("afbc: %d\n", enable_afbcd); osd_set_afbc(osd_id, enable_afbcd); + kfree(buf); return count; } @@ -465,19 +504,23 @@ static ssize_t osd_clear_write_file(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { - char buf[128]; + char *buf = NULL; struct seq_file *s = file->private_data; int osd_id = *(int *)s; unsigned int osd_clear = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &osd_clear); if (osd_clear) osd_set_clear(osd_id); + kfree(buf); return count; } @@ -584,17 +627,21 @@ static ssize_t osd_hwc_enable_write_file(struct file *file, { struct seq_file *s = file->private_data; int osd_id = *(int *)s; - char buf[128]; + char *buf = NULL; unsigned int hwc_enable = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &hwc_enable); osd_log_info("hwc enable: %d\n", hwc_enable); osd_set_hwc_enable(osd_id, hwc_enable); + kfree(buf); return count; } @@ -604,18 +651,22 @@ static ssize_t osd_do_hwc_write_file(struct file *file, { struct seq_file *s = file->private_data; int osd_id = *(int *)s; - char buf[128]; + char *buf = NULL; unsigned int do_hwc = 0; int ret = 0; - count = min_t(size_t, count, (sizeof(buf)-1)); - if (copy_from_user(buf, userbuf, count)) + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + if (copy_from_user(buf, userbuf, count)) { + kfree(buf); return -EFAULT; - buf[count] = 0; + } ret = kstrtoint(buf, 0, &do_hwc); osd_log_info("do_hwc: %d\n", do_hwc); if (do_hwc) osd_do_hwc(osd_id); + kfree(buf); return count; } diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index da3c43422346..9ef624e99bc1 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -652,7 +652,8 @@ static int osd_check_var(struct fb_var_screeninfo *var, struct fb_info *info) var->transp.length, var->transp.offset); fix->visual = color_format_pt->color_type; /* adjust memory length. */ - fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; + fix->line_length = + CANVAS_ALIGNED(var->xres_virtual * var->bits_per_pixel / 8); osd_log_dbg(MODULE_BASE, "xvirtual=%d, bpp:%d, line_length=%d\n", var->xres_virtual, var->bits_per_pixel, fix->line_length); @@ -1182,7 +1183,7 @@ static int osd_compat_ioctl(struct fb_info *info, static int malloc_osd_memory(struct fb_info *info) { - int j; + int j = 0; int ret = 0; u32 fb_index; int logo_index = -1; @@ -1450,14 +1451,16 @@ static int malloc_osd_memory(struct fb_info *info) if (fbdev->fb_mem_vaddr) memset(fbdev->fb_mem_vaddr, 0x0, fbdev->fb_len); if (osd_meson_dev.afbc_type && osd_get_afbc(fb_index)) { - for (j = 1; j < OSD_MAX_BUF_NUM; j++) { - osd_log_info( - "---------------clear fb%d memory %p\n", - fb_index, - fbdev->fb_mem_afbc_vaddr[j]); - memset(fbdev->fb_mem_afbc_vaddr[j], - 0x0, - fbdev->fb_afbc_len[j]); + for (j = 0; j < OSD_MAX_BUF_NUM; j++) { + if (j > 0) { + osd_log_info( + "---------------clear fb%d memory %p\n", + fb_index, + fbdev->fb_mem_afbc_vaddr[j]); + memset(fbdev->fb_mem_afbc_vaddr[j], + 0x0, + fbdev->fb_afbc_len[j]); + } } } else { /* two case in one @@ -1561,7 +1564,6 @@ static int osd_mmap(struct fb_info *info, struct vm_area_struct *vma) mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; if (vma->vm_pgoff >= mmio_pgoff) { if (info->var.accel_flags) { - mutex_unlock(&info->mm_lock); return -EINVAL; } @@ -1569,7 +1571,6 @@ static int osd_mmap(struct fb_info *info, struct vm_area_struct *vma) start = info->fix.mmio_start; len = info->fix.mmio_len; } - mutex_unlock(&info->mm_lock); vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -1984,9 +1985,11 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd, switch (cmd) { case VOUT_EVENT_MODE_CHANGE: set_osd_logo_freescaler(); +#if 0 /*def LINE_INT_WORK_AROUND */ if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && is_meson_rev_b()) set_reset_rdma_trigger_line(); +#endif if ((osd_meson_dev.osd_ver == OSD_NORMAL) || (osd_meson_dev.osd_ver == OSD_SIMPLE) || (osd_hw.hwc_enable[VIU1] == 0)) { @@ -4078,7 +4081,7 @@ static struct osd_device_data_s osd_tm2 = { .has_deband = 1, .has_lut = 1, .has_rdma = 1, - .has_dolby_vision = 0, + .has_dolby_vision = 1, .osd_fifo_len = 64, /* fifo len 64*8 = 512 */ .vpp_fifo_len = 0xfff,/* 2048 */ .dummy_data = 0x00808000, @@ -4309,6 +4312,7 @@ static int osd_probe(struct platform_device *pdev) /* get default display mode from dt */ ret = of_property_read_string(pdev->dev.of_node, "display_mode_default", &str); + prop_idx = 0; prop = of_get_property(pdev->dev.of_node, "pxp_mode", NULL); if (prop) prop_idx = of_read_ulong(prop, 1); @@ -4413,7 +4417,7 @@ static int osd_probe(struct platform_device *pdev) (fbdev->color->color_index > 16 ? (fbdev->color->color_index > 24 ? 4 : 3) : 2) : 1); - fix->line_length = var->xres_virtual * bpp; + fix->line_length = CANVAS_ALIGNED(var->xres_virtual * bpp); fix->smem_start = fbdev->fb_mem_paddr; fix->smem_len = fbdev->fb_len; if (fb_alloc_cmap(&fbi->cmap, 16, 0) != 0) { diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 19bbcc506f42..bc7572087c7e 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -94,6 +94,8 @@ #define osd_tprintk(...) #define FREE_SCALE_MAX_WIDTH 1920 +#define WAIT_CNT_MAX 20 + struct hw_para_s osd_hw; static DEFINE_MUTEX(osd_mutex); static DECLARE_WAIT_QUEUE_HEAD(osd_vsync_wq); @@ -585,7 +587,6 @@ static int pxp_mode; s64 timestamp[VIU_COUNT]; static unsigned int osd_h_filter_mode = 1; -#define CANVAS_ALIGNED(x) (((x) + 31) & ~31) #define BYTE_32_ALIGNED(x) (((x) + 31) & ~31) #define BYTE_16_ALIGNED(x) (((x) + 15) & ~15) #define BYTE_8_ALIGNED(x) (((x) + 7) & ~7) @@ -2502,6 +2503,10 @@ int osd_set_scan_mode(u32 index) osd_h_filter_mode = 1; osd_v_filter_mode = 1; } + if ((osd_hw.fb_for_4k2k) && + (osd_hw.free_scale_enable[index])) + osd_hw.scale_workaround = 1; + if (is_interlaced(vinfo)) { osd_hw.scan_mode[index] = SCAN_MODE_INTERLACE; if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) @@ -2570,9 +2575,6 @@ int osd_set_scan_mode(u32 index) && (vinfo->height == 2160)) || ((vinfo->width == 4096) && (vinfo->height == 2160))) { - if ((osd_hw.fb_for_4k2k) - && (osd_hw.free_scale_enable[index])) - osd_hw.scale_workaround = 1; osd_hw.field_out_en[output_index] = 0; } else if (((vinfo->width == 720) && (vinfo->height == 480)) @@ -2891,7 +2893,7 @@ void osd_setup_hw(u32 index, else { canvas_config(osd_hw.fb_gem[index].canvas_idx, osd_hw.fb_gem[index].addr, - osd_hw.fb_gem[index].width, + CANVAS_ALIGNED(osd_hw.fb_gem[index].width), osd_hw.fb_gem[index].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); } @@ -3177,6 +3179,7 @@ void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) struct vinfo_s *vinfo = NULL; s32 temp_y0, temp_y1; u32 output_index; + u32 height_dst, height_src; output_index = get_output_device_id(index); if (output_index == VIU1) @@ -3218,6 +3221,16 @@ void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1) osd_hw.dst_data[index].w = x1 - x0 + 1; osd_hw.dst_data[index].h = y1 - y0 + 1; + height_dst = osd_hw.free_dst_data[index].y_end - + osd_hw.free_dst_data[index].y_start + 1; + height_src = osd_hw.free_src_data[index].y_end - + osd_hw.free_src_data[index].y_start + 1; + + if (height_dst != height_src) + osd_set_dummy_data(index, 0); + else + osd_set_dummy_data(index, 0xff); + if (osd_hw.free_dst_data[index].y_end >= osd_hw.vinfo_height[index] - 1) osd_set_dummy_data(index, 0xff); osd_update_window_axis = true; @@ -4318,7 +4331,7 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map) if (!osd_hw.osd_afbcd[index].enable) { canvas_config(osd_hw.fb_gem[index].canvas_idx, ext_addr, - fence_map->byte_stride, + CANVAS_ALIGNED(fence_map->byte_stride), fence_map->height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); osd_hw.screen_base[index] = ext_addr; @@ -4671,7 +4684,8 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map) canvas_config(osd_hw.fb_gem[index].canvas_idx, osd_hw.fb_gem[index].addr, - osd_hw.fb_gem[index].width, + CANVAS_ALIGNED( + osd_hw.fb_gem[index].width), osd_hw.fb_gem[index].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); @@ -6367,6 +6381,7 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending) blending->din_reoder_sel; } +#ifdef FREESCAL_CHECK static bool is_freescale_para_changed(u32 index) { static int first[HW_OSD_COUNT - 1] = {1}; @@ -6391,6 +6406,7 @@ static bool is_freescale_para_changed(u32 index) first[index] = 0; return freescale_update; } +#endif static int osd_setting_blending_scope(u32 index) { @@ -8541,11 +8557,11 @@ static int osd_setting_order(u32 output_index) struct layer_blend_reg_s *blend_reg; struct hw_osd_blending_s *blending; u32 osd_count = osd_hw.osd_meson_dev.viu1_osd_count; - bool update = false; int line1; int line2; int active_begin_line; - u32 val; + int vinfo_height; + u32 val, wait_cnt = 0; blending = &osd_blending; blend_reg = &(blending->blend_reg); @@ -8587,11 +8603,20 @@ static int osd_setting_order(u32 output_index) active_begin_line = get_active_begin_line(VIU1); line1 = get_enter_encp_line(VIU1); /* if nearly vsync signal, wait vsync here */ - if (line1 <= active_begin_line * line_threshold / 100) { + vinfo_height = osd_hw.field_out_en[output_index] ? + (osd_hw.vinfo_height[output_index] * 2) : + osd_hw.vinfo_height[output_index]; + while (line1 >= vinfo_height + active_begin_line * + (100 - line_threshold) / 100 || + line1 <= active_begin_line * line_threshold / 100) { osd_log_dbg(MODULE_RENDER, "enter osd_setting_order:encp line=%d\n", line1); - osd_wait_vsync_hw_viu1(); + /* 0.5ms */ + usleep_range(500, 600); + wait_cnt++; + if (wait_cnt >= WAIT_CNT_MAX) + break; line1 = get_enter_encp_line(VIU1); } spin_lock_irqsave(&osd_lock, lock_flags); @@ -8601,11 +8626,11 @@ static int osd_setting_order(u32 output_index) if (osd_hw.enable[i]) { struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[i]; - update = is_freescale_para_changed(i); + /* update = is_freescale_para_changed(i); */ if (!osd_hw.osd_afbcd[i].enable) canvas_config(osd_hw.fb_gem[i].canvas_idx, osd_hw.fb_gem[i].addr, - osd_hw.fb_gem[i].width, + CANVAS_ALIGNED(osd_hw.fb_gem[i].width), osd_hw.fb_gem[i].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); @@ -8636,14 +8661,12 @@ static int osd_setting_order(u32 output_index) osd_hw.reg[DISP_GEOMETRY].update_func(i); osd_hw.reg[OSD_GBL_ALPHA].update_func(i); osd_hw.reg[DISP_OSD_REVERSE].update_func(i); - if (update || osd_update_window_axis) { - osd_set_scan_mode(i); - osd_hw.reg - [OSD_FREESCALE_COEF].update_func(i); - osd_hw.reg[DISP_FREESCALE_ENABLE] + osd_set_scan_mode(i); + osd_hw.reg[OSD_FREESCALE_COEF].update_func(i); + osd_hw.reg[DISP_FREESCALE_ENABLE] .update_func(i); + if (osd_update_window_axis) osd_update_window_axis = false; - } if (osd_hw.premult_en[i] && !osd_hw.blend_bypass) VSYNCOSD_WR_MPEG_REG_BITS( osd_reg->osd_mali_unpack_ctrl, 0x1, 28, 1); @@ -8755,8 +8778,6 @@ static void osd_setting_default_hwc(void) VSYNCOSD_WR_MPEG_REG(VPP_OSD1_IN_SIZE, blend_vsize << 16 | blend_hsize); - VSYNCOSD_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL, - 0x3, 2, 2); } static bool set_old_hwc_freescale(u32 index) @@ -8830,7 +8851,7 @@ static void osd_setting_old_hwc(void) if (!osd_hw.osd_afbcd[index].enable) canvas_config(osd_hw.fb_gem[index].canvas_idx, osd_hw.fb_gem[index].addr, - osd_hw.fb_gem[index].width, + CANVAS_ALIGNED(osd_hw.fb_gem[index].width), osd_hw.fb_gem[index].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); @@ -8872,7 +8893,7 @@ static void osd_setting_viu2(void) if (!osd_hw.osd_afbcd[index].enable) canvas_config(osd_hw.fb_gem[index].canvas_idx, osd_hw.fb_gem[index].addr, - osd_hw.fb_gem[index].width, + CANVAS_ALIGNED(osd_hw.fb_gem[index].width), osd_hw.fb_gem[index].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); @@ -10357,7 +10378,7 @@ void osd_restore_hw(void) for (i = 0; i < osd_hw.osd_meson_dev.osd_count; i++) canvas_config(osd_hw.fb_gem[i].canvas_idx, osd_hw.fb_gem[i].addr, - osd_hw.fb_gem[i].width, + CANVAS_ALIGNED(osd_hw.fb_gem[i].width), osd_hw.fb_gem[i].height, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); } @@ -10699,7 +10720,7 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map) } else { canvas_config(osd_hw.fb_gem[index].canvas_idx, phy_addr, - plane_map->byte_stride, + CANVAS_ALIGNED(plane_map->byte_stride), plane_map->src_h, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); } @@ -10948,7 +10969,7 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map) plane_map->byte_stride * plane_map->src_h; canvas_config(osd_hw.fb_gem[index].canvas_idx, phy_addr, - plane_map->byte_stride, + CANVAS_ALIGNED(plane_map->byte_stride), plane_map->src_h, CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index b043cef6ea10..d4ec6a0904cb 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -23,6 +23,7 @@ #include "osd_sync.h" #include "osd_drm.h" +#define CANVAS_ALIGNED(x) (((x) + 63) & ~63) #define MAX_HOLD_LINE 0x1f #define MIN_HOLD_LINE 0x04 #define VIU1_DEFAULT_HOLD_LINE 0x08 diff --git a/drivers/amlogic/media/osd/osd_rdma.c b/drivers/amlogic/media/osd/osd_rdma.c index 2a07c3b91b2a..2d18339da5ed 100644 --- a/drivers/amlogic/media/osd/osd_rdma.c +++ b/drivers/amlogic/media/osd/osd_rdma.c @@ -1169,6 +1169,7 @@ static int start_osd_rdma(char channel) data32 &= ~(1 << inc_bit); osd_reg_write(RDMA_ACCESS_AUTO, data32); #else +#if 0 /*def LINE_INT_WORK_AROUND */ if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B && is_meson_rev_b()) { set_reset_rdma_trigger_line(); @@ -1176,7 +1177,9 @@ static int start_osd_rdma(char channel) RDMA_AUTO_START_MASK); osd_hw.line_n_rdma = 1; - } else { + } else +#endif + { rdma_config(channel, RDMA_TRIGGER_VSYNC_INPUT | RDMA_AUTO_START_MASK); diff --git a/drivers/amlogic/media/osd/osd_virtual.c b/drivers/amlogic/media/osd/osd_virtual.c index 0f7ab7b6600a..633c1d371fdf 100644 --- a/drivers/amlogic/media/osd/osd_virtual.c +++ b/drivers/amlogic/media/osd/osd_virtual.c @@ -59,10 +59,15 @@ #include "osd_fb.h" #include "osd_virtual.h" +/* #define SPI_DEBUG */ +/* #define SOFTWARE_VSYNC */ +#define HW_VSYNC + #define DEFAULT_FPS (HZ/25) static u32 fb_memsize; static __u32 var_screeninfo[5]; static bool b_reserved_mem; +static int ready_post; static int start_post; static struct fb_virtual_dev_s *fb_vir_dev; static struct virt_fb_para_s virt_fb; @@ -106,6 +111,16 @@ static struct fb_fix_screeninfo fb_def_fix = { .accel = FB_ACCEL_NONE, }; +#ifdef SPI_DEBUG +static int spi_write_min; +module_param(spi_write_min, int, 0664); +MODULE_PARM_DESC(spi_write_min, "spi_write_min"); + +static int spi_write_max; +module_param(spi_write_max, int, 0664); +MODULE_PARM_DESC(spi_write_max, "spi_write_max"); +#endif + static void lcd_init(void) { /* set gamma */ @@ -123,23 +138,6 @@ static void lcd_enable(int blank) } -static void lcd_post_frame(u32 addr, u32 size) -{ - unsigned char *fb_data; - - start_post = 1; - /* frame post*/ - fb_data = virt_fb.screen_base_vaddr + addr; - #ifdef CONFIG_AMLOGIC_LCD_SPI - frame_post(fb_data, size); - #endif - /* gen complete signal*/ - complete(&fb_vir_dev->post_com); - /*start_post = 0; */ - osd_log_dbg(MODULE_BASE, "lcd_post_frame:=>addr 0x%x, size=%d\n", - addr, size); -} - static void fb_get_fps(u32 index, u32 *osd_fps) { *osd_fps = virt_fb.osd_fps; @@ -148,6 +146,7 @@ static void fb_get_fps(u32 index, u32 *osd_fps) static void fb_set_fps(u32 index, u32 osd_fps_start) { static int stime, etime; + int osd_fps; virt_fb.osd_fps_start = osd_fps_start; if (osd_fps_start) { @@ -157,10 +156,10 @@ static void fb_set_fps(u32 index, u32 osd_fps_start) } else { /* stop to calc fps */ etime = ktime_to_us(ktime_get()); - virt_fb.osd_fps = + osd_fps = (virt_fb.osd_fps * 1000000) / (etime - stime); - osd_log_info("osd fps:=%d\n", virt_fb.osd_fps); + osd_log_info("osd fps:=%d\n", osd_fps); } } @@ -325,20 +324,20 @@ static int virt_osd_check_fbsize(struct fb_var_screeninfo *var, return 0; } +#ifdef SOFTWARE_VSYNC s64 virt_osd_wait_vsync_event(void) { int ret; unsigned long timeout; ktime_t stime; - stime = ktime_get(); - timeout = msecs_to_jiffies(2000); /* waiting for 1s. */ ret = wait_for_completion_timeout(&fb_vir_dev->fb_com, timeout); if (ret == 0) pr_err("software vsync timeout\n"); + stime = ktime_get(); osd_log_dbg(MODULE_BASE, "%s\n", __func__); return stime.tv64; @@ -353,6 +352,44 @@ static void sw_vsync_timer_func(unsigned long arg) complete(&fbdev->timer_com); } +static void lcd_post_frame(u32 addr, u32 size) +{ + unsigned char *fb_data; +#ifdef SPI_DEBUG + int stime, etime, time_write; + static int cnt; + + stime = ktime_to_us(ktime_get()); +#endif + + start_post = 1; + /* frame post*/ + fb_data = virt_fb.screen_base_vaddr + addr; + +#ifdef CONFIG_AMLOGIC_LCD_SPI + frame_post(fb_data, size); +#endif + +#ifdef SPI_DEBUG + etime = ktime_to_us(ktime_get()); + time_write = etime - stime; + cnt++; + if (cnt == 1) { + spi_write_min = time_write; + spi_write_max = time_write; + } + if (time_write < spi_write_min) + spi_write_min = time_write; + if (time_write > spi_write_max) + spi_write_max = time_write; +#endif + /* gen complete signal*/ + complete(&fb_vir_dev->post_com); + /*start_post = 0; */ + osd_log_dbg(MODULE_BASE, "lcd_post_frame:=>addr 0x%x, size=%d\n", + addr, size); +} + static int fb_monitor_thread(void *data) { int ret; @@ -384,6 +421,96 @@ static int fb_monitor_thread(void *data) return 0; } +int te_cb(void) +{ + return 0; +} +#endif + +#ifdef HW_VSYNC +s64 virt_osd_wait_vsync_event(void) +{ + int ret; + unsigned long timeout; + ktime_t stime; + + timeout = msecs_to_jiffies(2000); + /* waiting for 1s. */ + ret = wait_for_completion_timeout(&fb_vir_dev->fb_com, + timeout); + if (ret == 0) + pr_err("software vsync timeout\n"); + stime = ktime_get(); + osd_log_dbg(MODULE_BASE, "%s\n", __func__); + + return stime.tv64; +} + +static void lcd_post_frame(u32 addr, u32 size) +{ + unsigned char *fb_data; +#ifdef SPI_DEBUG + int stime, etime, time_write; + static int cnt; + + stime = ktime_to_us(ktime_get()); +#endif + /* frame post*/ + fb_data = virt_fb.screen_base_vaddr + addr; + +#ifdef CONFIG_AMLOGIC_LCD_SPI + start_post = 1; + frame_post(fb_data, size); + start_post = 0; +#endif + +#ifdef SPI_DEBUG + etime = ktime_to_us(ktime_get()); + time_write = etime - stime; + cnt++; + if (cnt == 1) { + spi_write_min = time_write; + spi_write_max = time_write; + } + if (time_write < spi_write_min) + spi_write_min = time_write; + if (time_write > spi_write_max) + spi_write_max = time_write; +#endif + osd_log_dbg(MODULE_BASE, "lcd_post_frame:=>addr 0x%x, size=%d\n", + addr, size); +} + +static int fb_monitor_thread(void *data) +{ + struct fb_virtual_dev_s *fbdev = fb_vir_dev; + + osd_log_info("fb monitor start\n"); + ready_post = 0; + while (fbdev->fb_monitor_run) { + /* waiting for 1s. */ + wait_for_completion(&fb_vir_dev->post_com); + /* call frame_post*/ + lcd_post_frame(virt_fb.offset, virt_fb.size); + /* gen complete signal*/ + complete(&fbdev->fb_com); + } + osd_log_info("exit fb_monitor_thread\n"); + return 0; +} + +int te_cb(void) +{ + if (ready_post && (start_post == 0)) { + /* gen complete signal*/ + complete(&fb_vir_dev->post_com); + ready_post = 0; + } + return 0; +} +#endif +EXPORT_SYMBOL(te_cb); + static int virt_fb_start_monitor(void) { int ret = 0; @@ -487,8 +614,7 @@ static int malloc_fb_memory(struct fb_info *info) fb_index = fbdev->fb_index; fix = &info->fix; var = &info->var; - if (!fb_ion_client) - fb_ion_client = meson_ion_client_create(-1, "meson-fb"); + fb_ion_client = meson_ion_client_create(-1, "meson-fb"); fb_memsize_total = fb_memsize; /* read cma/fb-reserved memory first */ if ((b_reserved_mem == true) && @@ -529,7 +655,7 @@ static int malloc_fb_memory(struct fb_info *info) fb_ion_handle, (ion_phys_addr_t *) &fb_rmem_paddr, - (size_t *)&fb_memsize); + (size_t *)&fb_memsize_total); fb_rmem_vaddr = ion_map_kernel(fb_ion_client, fb_ion_handle); @@ -612,7 +738,6 @@ static int virt_osd_mmap(struct fb_info *info, struct vm_area_struct *vma) mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; if (vma->vm_pgoff >= mmio_pgoff) { if (info->var.accel_flags) { - mutex_unlock(&info->mm_lock); return -EINVAL; } @@ -620,7 +745,6 @@ static int virt_osd_mmap(struct fb_info *info, struct vm_area_struct *vma) start = info->fix.mmio_start; len = info->fix.mmio_len; } - mutex_unlock(&info->mm_lock); vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -653,14 +777,19 @@ static int virt_osd_pan_display(struct fb_var_screeninfo *var, virt_fb.osd_fps++; stride = var->xres * (var->bits_per_pixel >> 3); offset = stride * virt_fb.pandata.y_start; + virt_fb.offset = offset; size = stride * var->yres; + virt_fb.size = size; + ready_post = 1; osd_log_dbg(MODULE_BASE, "offset[%d-%d]x[%d-%d]y[%d-%d]\n", var->xoffset, var->yoffset, virt_fb.pandata.x_start, virt_fb.pandata.x_end, virt_fb.pandata.y_start, virt_fb.pandata.y_end); +#ifdef SOFTWARE_VSYNC lcd_post_frame(offset, size); +#endif } return 0; } @@ -691,7 +820,7 @@ static int virt_osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; - u32 blank; + u32 blank = 0; int ret = 0; s32 vsync_timestamp; @@ -701,8 +830,8 @@ static int virt_osd_ioctl(struct fb_info *info, ret = copy_to_user(argp, &vsync_timestamp, sizeof(s32)); break; case FBIOPUT_OSD_BLANK: - lcd_enable((blank != 0) ? 0 : 1); ret = copy_from_user(&blank, argp, sizeof(u32)); + lcd_enable((blank != 0) ? 0 : 1); break; default: osd_log_err("command 0x%x not supported (%s)\n", @@ -771,7 +900,6 @@ int amlfb_virtual_probe(struct platform_device *pdev) struct fb_fix_screeninfo *fix; int index = 0, bpp; struct fb_virtual_dev_s *fbdev = NULL; - const struct vinfo_s *vinfo = NULL; int i; int ret = 0; @@ -787,13 +915,12 @@ int amlfb_virtual_probe(struct platform_device *pdev) osd_log_info("fb_memsize=0x%x\n", fb_memsize); /* init reserved memory */ ret = of_reserved_mem_device_init(&pdev->dev); - if (ret != 0) + if (ret != 0) { osd_log_err("failed to init reserved memory\n"); - else + b_reserved_mem = false; + } else { b_reserved_mem = true; - #if 0 - vinfo = get_current_vinfo(); - #endif + } /* register frame buffer memory */ fbi = framebuffer_alloc(sizeof(struct fb_virtual_dev_s), &pdev->dev); @@ -812,10 +939,6 @@ int amlfb_virtual_probe(struct platform_device *pdev) fbdev->fb_len = 0; fbdev->fb_mem_paddr = 0; fbdev->fb_mem_vaddr = 0; - if (vinfo) { - fb_def_var.width = vinfo->screen_real_width; - fb_def_var.height = vinfo->screen_real_height; - } /* setup fb0 display size */ ret = of_property_read_u32_array(pdev->dev.of_node, "display_size_default", @@ -865,11 +988,6 @@ int amlfb_virtual_probe(struct platform_device *pdev) fbi->fbops = &virtual_fb_ops; fbi->screen_base = (char __iomem *)fbdev->fb_mem_vaddr; fbi->screen_size = fix->smem_len; - #if 0 - if (vinfo) - set_default_display_axis(&fbdev->fb_info->var, - &fbdev->osd_ctl, vinfo); - #endif virt_osd_check_var(var, fbi); /* register frame buffer */ register_framebuffer(fbi); @@ -880,15 +998,19 @@ int amlfb_virtual_probe(struct platform_device *pdev) init_completion(&fbdev->fb_com); init_completion(&fbdev->post_com); +#ifdef SOFTWARE_VSYNC init_completion(&fbdev->timer_com); +#endif lcd_init(); virt_fb_start_monitor(); + #ifdef SOFTWARE_VSYNC /* add timer to simulate software vsync */ init_timer(&fbdev->timer); fbdev->timer.data = (ulong) fbdev; fbdev->timer.function = sw_vsync_timer_func; fbdev->timer.expires = jiffies + DEFAULT_FPS; add_timer(&fbdev->timer); + #endif osd_log_info("virtual osd probe OK\n"); return 0; failed2: diff --git a/drivers/amlogic/media/osd/osd_virtual.h b/drivers/amlogic/media/osd/osd_virtual.h index 58f166f9eda5..f870a9f8e5af 100644 --- a/drivers/amlogic/media/osd/osd_virtual.h +++ b/drivers/amlogic/media/osd/osd_virtual.h @@ -52,6 +52,7 @@ struct virt_fb_para_s { ulong screen_size; u32 stride; u32 offset; + u32 size; u32 osd_fps; u32 osd_fps_start; }; diff --git a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c index a06190f12bb8..8d9bb9b12127 100644 --- a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c +++ b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c @@ -1266,11 +1266,32 @@ ion_video_class_attrs, }; static int ionvideo_open(struct inode *inode, struct file *file) { + int *ion_id = kzalloc(sizeof(int), GFP_KERNEL); + + if (ion_id != NULL) { + *ion_id = -1; + file->private_data = ion_id; + pr_info("%p: alloc space for storing ion_id\n", file); + } + return 0; } static int ionvideo_release(struct inode *inode, struct file *file) { + int *ion_id = file->private_data; + + if (ion_id != NULL && (*ion_id) != -1) { + pr_info("%p: ion_id leak detected, release it: %d\n", + file, *ion_id); + ionvideo_release_map(*ion_id); + } + + if (file->private_data != NULL) + kfree(file->private_data); + + file->private_data = NULL; + return 0; } @@ -1284,17 +1305,32 @@ static long ionvideo_ioctl(struct file *file, switch (cmd) { case IONVIDEO_IOCTL_ALLOC_ID:{ u32 ionvideo_id = 0; + int *a = (int *) file->private_data; ret = ionvideo_alloc_map(&ionvideo_id); + + if (a != NULL) { + *a = ionvideo_id; + pr_info("%p:allocated ion_id:%d\n", file, *a); + } + if (ret != 0) break; + put_user(ionvideo_id, (u32 __user *)argp); } break; case IONVIDEO_IOCTL_FREE_ID:{ u32 ionvideo_id; - + int *a = (int *) file->private_data; get_user(ionvideo_id, (u32 __user *)argp); + + if (a != NULL) { + pr_info("%p: free ion_id:%d, priv_data:%d\n", + file, ionvideo_id, *a); + *a = -1; + } + ionvideo_release_map(ionvideo_id); } break; diff --git a/drivers/amlogic/media/video_processor/pic_dev/picdec.c b/drivers/amlogic/media/video_processor/pic_dev/picdec.c index 075c0e2437f0..b061e79bfa0d 100644 --- a/drivers/amlogic/media/video_processor/pic_dev/picdec.c +++ b/drivers/amlogic/media/video_processor/pic_dev/picdec.c @@ -271,60 +271,64 @@ static int render_frame(struct ge2d_context_s *context, h_phase = (input->frame_width << 18) / dev->disp_width; v_phase = (input->frame_height << 18) / dev->disp_height; phase = max(h_phase, v_phase); + + new_vf = &vfpool[fill_ptr]; + new_vf->canvas0Addr = new_vf->canvas1Addr = index2canvas(index); + dev->p2p_mode = p2p_mode; switch (dev->p2p_mode) { case 0: - if ((input->frame_width < dev->disp_width) && - (input->frame_height < dev->disp_height)) { + if ((input->frame_width <= dev->disp_width) && + (input->frame_height <= dev->disp_height)) { dev->target_width = input->frame_width; dev->target_height = input->frame_height; } else { dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; } + new_vf->width = dev->target_width; + new_vf->height = dev->target_height; break; case 1: - if ((input->frame_width >= ZOOM_WIDTH) && - (input->frame_height >= ZOOM_HEIGHT)) { - if ((input->frame_width < dev->disp_width) && - (input->frame_height < dev->disp_height)) { - dev->target_width = input->frame_width; - dev->target_height = input->frame_height; - } else { - dev->target_width = dev->disp_width; - dev->target_height = dev->disp_height; - } + if ((input->frame_width <= dev->disp_width) && + (input->frame_height <= dev->disp_height)) { + dev->target_width = input->frame_width; + dev->target_height = input->frame_height; } else { dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; } + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; case 2: - if ((phase <= (1 << 18)) && (phase >= (1 << 16))) { + if (phase >= (1 << 16)) { /* ratio >= 1/4 */ input->frame_width = (input->frame_width << 18) / phase; input->frame_height = (input->frame_height << 18) / phase; - } else if (phase < (1 << 16)) { + } else if (phase < (1 << 16)) { /* ratio < 1/4 */ input->frame_width <<= 2; input->frame_height <<= 2; } - dev->target_width = dev->disp_width; - dev->target_height = dev->disp_height; + dev->target_width = input->frame_width; + dev->target_height = input->frame_height; + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; default: dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; + } aml_pr_info(1, "p2p_mode :%d ----render buffer index is %d\n", dev->p2p_mode, index); aml_pr_info(1, "render target width: %d ; target height: %d\n", dev->target_width, dev->target_height); - new_vf = &vfpool[fill_ptr]; - new_vf->canvas0Addr = new_vf->canvas1Addr = index2canvas(index); - new_vf->width = dev->target_width; - new_vf->height = dev->target_height; + if (dev->output_format_mode) new_vf->type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE @@ -384,60 +388,63 @@ static int render_frame_block(void) h_phase = (input->frame_width << 18) / dev->disp_width; v_phase = (input->frame_height << 18) / dev->disp_height; phase = max(h_phase, v_phase); + + new_vf = &vfpool[fill_ptr]; + new_vf->canvas0Addr = new_vf->canvas1Addr = index2canvas(index); + dev->p2p_mode = p2p_mode; switch (dev->p2p_mode) { case 0: - if ((input->frame_width < dev->disp_width) && - (input->frame_height < dev->disp_height)) { - dev->target_width = input->frame_width; + if ((input->frame_width <= dev->disp_width) && + (input->frame_height <= dev->disp_height)) { + dev->target_width = input->frame_width; dev->target_height = input->frame_height; } else { - dev->target_width = dev->disp_width; + dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; } + new_vf->width = dev->target_width; + new_vf->height = dev->target_height; break; case 1: - if ((input->frame_width >= ZOOM_WIDTH) && - (input->frame_height >= ZOOM_HEIGHT)) { - if ((input->frame_width < dev->disp_width) && - (input->frame_height < dev->disp_height)) { - dev->target_width = input->frame_width; - dev->target_height = input->frame_height; - } else { - dev->target_width = dev->disp_width; - dev->target_height = dev->disp_height; - } + if ((input->frame_width <= dev->disp_width) && + (input->frame_height <= dev->disp_height)) { + dev->target_width = input->frame_width; + dev->target_height = input->frame_height; } else { - dev->target_width = dev->disp_width; + dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; } + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; case 2: - if ((phase <= (1 << 18)) && (phase >= (1 << 16))) { + if (phase >= (1 << 16)) { /* ratio >= 1/4 */ input->frame_width = (input->frame_width << 18) / phase; input->frame_height = (input->frame_height << 18) / phase; - } else if (phase < (1 << 16)) { + } else if (phase < (1 << 16)) { /* ratio < 1/4 */ input->frame_width <<= 2; input->frame_height <<= 2; } - dev->target_width = dev->disp_width; - dev->target_height = dev->disp_height; + dev->target_width = input->frame_width; + dev->target_height = input->frame_height; + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; default: dev->target_width = dev->disp_width; dev->target_height = dev->disp_height; + new_vf->width = dev->disp_width; + new_vf->height = dev->disp_height; break; } aml_pr_info(1, "p2p_mode :%d ----render buffer index is %d\n", dev->p2p_mode, index); aml_pr_info(1, "render target width: %d ; target height: %d\n", dev->target_width, dev->target_height); - new_vf = &vfpool[fill_ptr]; - new_vf->canvas0Addr = new_vf->canvas1Addr = index2canvas(index); - new_vf->width = picdec_device.target_width; - new_vf->height = picdec_device.target_height; + if (dev->output_format_mode) new_vf->type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE @@ -845,42 +852,6 @@ int fill_color(struct vframe_s *vf, struct ge2d_context_s *context, return 0; } -static void rotate_adjust(int w_in, int h_in, int *w_out, int *h_out, int angle) -{ - int w = 0, h = 0, disp_w = 0, disp_h = 0; - - disp_w = *w_out; - disp_h = *h_out; - if ((angle == 90) || (angle == 270)) { - if ((w_in < disp_h) && (h_in < disp_w)) { - w = h_in; - h = w_in; - } else { - h = min_t(int, w_in, disp_h); - w = h_in * h / w_in; - if (w > disp_w) { - h = (h * disp_w) / w; - w = disp_w; - } - } - } else { - if ((w_in < disp_w) && (h_in < disp_h)) { - w = w_in; - h = h_in; - } else { - if ((w_in * disp_h) > (disp_w * h_in)) { - w = disp_w; - h = disp_w * h_in / w_in; - } else { - h = disp_h; - w = disp_h * w_in / h_in; - } - } - } - *w_out = w; - *h_out = h; -} - static int copy_phybuf_to_file(ulong phys, u32 size, struct file *fp, loff_t pos) { @@ -904,8 +875,6 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context, int src_canvas_id = picdec_canvas_table[2]; int canvas_width = (picdec_device.origin_width + 0x1f) & ~0x1f; int canvas_height = (picdec_device.origin_height + 0xf) & ~0xf; - int frame_width = picdec_input.frame_width; - int frame_height = picdec_input.frame_height; int dst_top, dst_left, dst_width, dst_height; struct file *filp = NULL; loff_t pos = 0; @@ -1015,33 +984,16 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context, dst_left = 0; dst_width = picdec_device.target_width; dst_height = picdec_device.target_height; - rotate_adjust(frame_width, frame_height, &dst_width, &dst_height, - 0); dst_width = (dst_width + 0x1) & ~0x1; dst_height = (dst_height + 0x1) & ~0x1; + switch (picdec_device.p2p_mode) { case 0: dst_left = 0; dst_top = 0; - vf->width = dst_width; - vf->height = dst_height; break; case 1: - if ((picdec_input.frame_width >= ZOOM_WIDTH) && - (picdec_input.frame_height >= ZOOM_HEIGHT)) { - dst_left = 0; - dst_top = 0; - vf->width = dst_width; - vf->height = dst_height; - } else { - dst_left = (picdec_device.disp_width - dst_width) >> 1; - dst_top = (picdec_device.disp_height - dst_height) >> 1; - } - break; case 2: - dst_left = (picdec_device.disp_width - dst_width) >> 1; - dst_top = (picdec_device.disp_height - dst_height) >> 1; - break; default: dst_left = (picdec_device.disp_width - dst_width) >> 1; dst_top = (picdec_device.disp_height - dst_height) >> 1; @@ -1051,6 +1003,10 @@ int picdec_fill_buffer(struct vframe_s *vf, struct ge2d_context_s *context, picdec_device.origin_height, dst_left, dst_top, dst_width, dst_height); + aml_pr_info(1, "%dx%d -> (%d,%d) %dx%d, vframe--w:%d h:%d\n", + picdec_device.origin_width, picdec_device.origin_height, + dst_left, dst_top, dst_width, dst_height, + vf->width, vf->height); /*dump ge2d output buffer data. use this function should close selinux*/ if ((dump_file_flag) && (picdec_device.origin_width > 100)) { if (picdec_device.output_format_mode) { diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_dev.h b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_dev.h index 02f32995b917..b463b227898f 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_dev.h +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_dev.h @@ -74,7 +74,6 @@ struct ppmgr_device_t { struct platform_device *pdev; unsigned int ppmgr_debug; unsigned int debug_first_frame; - unsigned int debug_10bit_frame; char dump_path[32]; }; diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c index 084c73666ec2..c51c839f7bd5 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_drv.c @@ -242,7 +242,8 @@ static int parse_para(const char *para, int para_num, int *result) char *token = NULL; char *params, *params_base; int *out = result; - int len = 0, count = 0; + ssize_t len; + int count = 0; int res = 0; int ret = 0; @@ -490,30 +491,6 @@ static ssize_t debug_first_frame_write(struct class *cla, return count; } -static ssize_t debug_10bit_frame_read(struct class *cla, - struct class_attribute *attr, char *buf) -{ - return snprintf(buf, - 80, - "current debug_10bit_frame is %d\n", - ppmgr_device.debug_10bit_frame); -} - -static ssize_t debug_10bit_frame_write(struct class *cla, - struct class_attribute *attr, const char *buf, size_t count) -{ - long tmp; - - int ret = kstrtol(buf, 0, &tmp); - - if (ret != 0) { - PPMGRDRV_ERR("ERROR converting %s to long int!\n", buf); - return ret; - } - ppmgr_device.debug_10bit_frame = tmp; - return count; -} - static ssize_t rect_read(struct class *cla, struct class_attribute *attr, char *buf) { @@ -530,7 +507,7 @@ static ssize_t rect_write(struct class *cla, struct class_attribute *attr, char *strp = (char *)buf; char *endp = NULL; int value_array[4]; - static int buflen; + static ssize_t buflen; static char *tokenlen; int i; long tmp; @@ -594,7 +571,14 @@ static ssize_t dump_path_write(struct class *cla, struct class_attribute *attr, PPMGRDRV_INFO("buf kstrdup failed\n"); return 0; } - strcpy(ppmgr_device.dump_path, tmp); + if (strlen(tmp) >= sizeof(ppmgr_device.dump_path) - 1) { + memcpy(ppmgr_device.dump_path, tmp, + sizeof(ppmgr_device.dump_path) - 1); + ppmgr_device.dump_path[ + sizeof(ppmgr_device.dump_path) - 1] = '\0'; + } else { + strcpy(ppmgr_device.dump_path, tmp); + } return count; @@ -630,7 +614,7 @@ static void set_disp_para(const char *para) static ssize_t disp_write(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { - int buflen; + ssize_t buflen; buflen = strlen(buf); if (buflen <= 0) @@ -721,7 +705,7 @@ static ssize_t ppscaler_rect_write(struct class *cla, struct class_attribute *attr, const char *buf, size_t count) { - int buflen; + ssize_t buflen; buflen = strlen(buf); if (buflen <= 0) @@ -1402,11 +1386,6 @@ __ATTR(debug_first_frame, debug_first_frame_read, debug_first_frame_write), -__ATTR(debug_10bit_frame, - 0644, - debug_10bit_frame_read, - debug_10bit_frame_write), - __ATTR(dump_path, 0644, dump_path_read, @@ -1743,7 +1722,6 @@ int init_ppmgr_device(void) ppmgr_device.tb_detect_init_mute = 0; ppmgr_device.ppmgr_debug = 0; ppmgr_device.debug_first_frame = 0; - ppmgr_device.debug_10bit_frame = 0; PPMGRDRV_INFO("ppmgr_dev major:%d\n", ret); ppmgr_device.cla = init_ppmgr_cls(); diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index 47d0d80c913a..f0d9caf36274 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -104,7 +104,7 @@ CLEAR_MPEG_REG_MASK(VPP_MISC, \ CLEAR_MPEG_REG_MASK(VPP_MISC, \ VPP_VD1_PREBLEND) -static int ass_index; +static int ass_index = -1; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER static int backup_index = -1; static int backup_content_w = 0, backup_content_h; @@ -953,7 +953,7 @@ static int process_vf_tb_detect(struct vframe_s *vf, { struct canvas_s cs0, cs1, cs2, cd; int interlace_mode; - struct vframe_s src_vf; + u32 canvas_id; u32 format = GE2D_FORMAT_M24_YUV420; u32 h_scale_coef_type = context->config.h_scale_coef_type; @@ -1000,46 +1000,55 @@ static int process_vf_tb_detect(struct vframe_s *vf, ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - src_vf = *vf; - if (vf->canvas0Addr == (u32)-1) { canvas_config_config( tb_src_canvas[0] & 0xff, - &src_vf.canvas0_config[0]); - if (src_vf.plane_num == 2) { - canvas_config_config( - tb_src_canvas[1] & 0xff, - &src_vf.canvas0_config[1]); - } else if (src_vf.plane_num == 3) { - canvas_config_config( - tb_src_canvas[2] & 0xff, - &src_vf.canvas0_config[2]); + &vf->canvas0_config[0]); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = vf->canvas0_config[0].height; + + if (vf->plane_num == 2) { + canvas_config_config(tb_src_canvas[1] & 0xff, + &vf->canvas0_config[1]); + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + } else if (vf->plane_num == 3) { + canvas_config_config(tb_src_canvas[2] & 0xff, + &vf->canvas0_config[2]); + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; } - src_vf.canvas0Addr = + canvas_id = (tb_src_canvas[0] & 0xff) | ((tb_src_canvas[1] & 0xff) << 8) | ((tb_src_canvas[2] & 0xff) << 16); + ge2d_config->src_para.canvas_index = canvas_id; - canvas_read( - src_vf.canvas0Addr & 0xff, &cs0); - canvas_read( - (src_vf.canvas0Addr >> 8) & 0xff, &cs1); - canvas_read( - (src_vf.canvas0Addr >> 16) & 0xff, &cs2); } else { canvas_read(vf->canvas0Addr & 0xff, &cs0); canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; } - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; canvas_read(tb_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -1047,7 +1056,6 @@ static int process_vf_tb_detect(struct vframe_s *vf, ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = src_vf.canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = format; ge2d_config->src_para.fill_color_en = 0; @@ -1140,7 +1148,7 @@ static void process_vf_rotate(struct vframe_s *vf, struct vframe_s *new_vf; struct ppframe_s *pp_vf; struct canvas_s cs0, cs1, cs2, cd; - struct vframe_s src_vf; + u32 canvas_id; int ret = 0; unsigned int cur_angle = 0; int interlace_mode; @@ -1217,12 +1225,6 @@ static void process_vf_rotate(struct vframe_s *vf, pp_vf->dec_frame = vf; if (vf->type & VIDTYPE_COMPRESS) { - if ((vf->bitdepth == ( - BITDEPTH_Y10 | - BITDEPTH_U10 | - BITDEPTH_V10)) - && (!ppmgr_device.debug_10bit_frame)) - pp_vf->dec_frame = vf; if (vf->canvas0Addr != (u32)-1) { canvas_copy(vf->canvas0Addr & 0xff, ppmgr_src_canvas[0]); @@ -1244,7 +1246,7 @@ static void process_vf_rotate(struct vframe_s *vf, ppmgr_src_canvas[2], &vf->canvas0_config[2]); } - vf->canvas0Addr = + canvas_id = ppmgr_src_canvas[0] | (ppmgr_src_canvas[1] << 8) | (ppmgr_src_canvas[2] << 16); @@ -1447,44 +1449,44 @@ static void process_vf_rotate(struct vframe_s *vf, ge2d_config->src1_gb_alpha = 0;/*0xff;*/ ge2d_config->dst_xy_swap = 0; - src_vf = *vf; if (vf->canvas0Addr == (u32)-1) { canvas_config_config(ppmgr_src_canvas[0], - &src_vf.canvas0_config[0]); - if (src_vf.plane_num == 2) { + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { canvas_config_config( ppmgr_src_canvas[1], - &src_vf.canvas0_config[1]); - } else if (src_vf.plane_num == 3) { + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { canvas_config_config( ppmgr_src_canvas[2], - &src_vf.canvas0_config[2]); + &vf->canvas0_config[2]); } - src_vf.canvas0Addr = + canvas_id = ppmgr_src_canvas[0] | (ppmgr_src_canvas[1] << 8) | (ppmgr_src_canvas[2] << 16); ge2d_config->src_planes[0].addr = - src_vf.canvas0_config[0].phy_addr; + vf->canvas0_config[0].phy_addr; ge2d_config->src_planes[0].w = - src_vf.canvas0_config[0].width; + vf->canvas0_config[0].width; ge2d_config->src_planes[0].h = - src_vf.canvas0_config[0].height; + vf->canvas0_config[0].height; ge2d_config->src_planes[1].addr = - src_vf.canvas0_config[1].phy_addr; + vf->canvas0_config[1].phy_addr; ge2d_config->src_planes[1].w = - src_vf.canvas0_config[1].width; + vf->canvas0_config[1].width; ge2d_config->src_planes[1].h = - src_vf.canvas0_config[1].height >> 1; - if (src_vf.plane_num == 3) { + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { ge2d_config->src_planes[2].addr = - src_vf.canvas0_config[2].phy_addr; + vf->canvas0_config[2].phy_addr; ge2d_config->src_planes[2].w = - src_vf.canvas0_config[2].width; + vf->canvas0_config[2].width; ge2d_config->src_planes[2].h = - src_vf.canvas0_config[2].height >> 1; + vf->canvas0_config[2].height >> 1; } + ge2d_config->src_para.canvas_index = canvas_id; } else { canvas_read(vf->canvas0Addr & 0xff, &cs0); canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); @@ -1498,6 +1500,8 @@ static void process_vf_rotate(struct vframe_s *vf, ge2d_config->src_planes[2].addr = cs2.addr; ge2d_config->src_planes[2].w = cs2.width; ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } canvas_read(new_vf->canvas0Addr & 0xff, &cd); @@ -1508,8 +1512,6 @@ static void process_vf_rotate(struct vframe_s *vf, ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format(vf); @@ -1575,45 +1577,44 @@ static void process_vf_rotate(struct vframe_s *vf, ge2d_config->src_key.key_mode = 0; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; - src_vf = *vf; if (vf->canvas0Addr == (u32)-1) { canvas_config_config(ppmgr_src_canvas[0], - &src_vf.canvas0_config[0]); - if (src_vf.plane_num == 2) { + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { canvas_config_config( ppmgr_src_canvas[1], - &src_vf.canvas0_config[1]); - } else if (src_vf.plane_num == 3) { + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { canvas_config_config( ppmgr_src_canvas[2], - &src_vf.canvas0_config[2]); + &vf->canvas0_config[2]); } - src_vf.canvas0Addr = + canvas_id = ppmgr_src_canvas[0] | (ppmgr_src_canvas[1] << 8) | (ppmgr_src_canvas[2] << 16); ge2d_config->src_planes[0].addr = - src_vf.canvas0_config[0].phy_addr; + vf->canvas0_config[0].phy_addr; ge2d_config->src_planes[0].w = - src_vf.canvas0_config[0].width; + vf->canvas0_config[0].width; ge2d_config->src_planes[0].h = - src_vf.canvas0_config[0].height; + vf->canvas0_config[0].height; ge2d_config->src_planes[1].addr = - src_vf.canvas0_config[1].phy_addr; + vf->canvas0_config[1].phy_addr; ge2d_config->src_planes[1].w = - src_vf.canvas0_config[1].width; + vf->canvas0_config[1].width; ge2d_config->src_planes[1].h = - src_vf.canvas0_config[1].height >> 1; - if (src_vf.plane_num == 3) { + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { ge2d_config->src_planes[2].addr = - src_vf.canvas0_config[2].phy_addr; + vf->canvas0_config[2].phy_addr; ge2d_config->src_planes[2].w = - src_vf.canvas0_config[2].width; + vf->canvas0_config[2].width; ge2d_config->src_planes[2].h = - src_vf.canvas0_config[2].height >> 1; + vf->canvas0_config[2].height >> 1; } - ge2d_config->src_para.canvas_index = src_vf.canvas0Addr; + ge2d_config->src_para.canvas_index = canvas_id; } else { canvas_read(vf->canvas0Addr & 0xff, &cs0); canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); @@ -1809,6 +1810,7 @@ static void process_vf_rotate(struct vframe_s *vf, new_vf->source_type = VFRAME_SOURCE_TYPE_PPMGR; if (dumpfirstframe != 2) vfq_push(&q_ready, new_vf); + if (strstr(ppmgr_device.dump_path, "dst") && (dumpfirstframe == 2)) { old_fs = get_fs(); @@ -1855,6 +1857,10 @@ static void process_vf_change(struct vframe_s *vf, unsigned int temp_angle = 0; unsigned int cur_angle = 0; int ret = 0; + + cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4; + if ((cur_angle == 0) || ppmgr_device.bypass) + return; #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS if (platform_type == PLATFORM_TV) ret = ppmgr_buffer_init(1); @@ -1876,7 +1882,6 @@ static void process_vf_change(struct vframe_s *vf, temp_vf.type = VIDTYPE_VIU_444 | VIDTYPE_VIU_SINGLE_PLANE | VIDTYPE_VIU_FIELD; temp_vf.canvas0Addr = temp_vf.canvas1Addr = ass_index; - cur_angle = (ppmgr_device.videoangle + vf->orientation) % 4; temp_angle = (cur_angle >= pp_vf->angle) ? (cur_angle - pp_vf->angle) : @@ -2395,6 +2400,7 @@ static int ppmgr_task(void *data) struct ppframe_s *pp_local = NULL; struct ge2d_context_s *context = create_ge2d_work_queue(); struct config_para_ex_s ge2d_config; + struct ppframe_s *pp_vf; #ifdef PPMGR_TB_DETECT bool first_frame = true; int first_frame_type = 0; @@ -2429,19 +2435,24 @@ static int ppmgr_task(void *data) if (scaler_pos_changed) { scaler_pos_changed = 0; vf = get_cur_dispbuf(); - if (!is_valid_ppframe(to_ppframe(vf))) + if (IS_ERR_OR_NULL(vf)) + continue; + pp_vf = to_ppframe(vf); + if (IS_ERR_OR_NULL(pp_vf)) + continue; + if (!is_valid_ppframe(pp_vf)) continue; if ((vf->type & VIDTYPE_COMPRESS) && (vf->plane_num < 1) && (vf->canvas0Addr == (u32)-1)) { continue; } - if (vf) { - if (process_vf_adjust(vf, - context, - &ge2d_config) >= 0) - EnableVideoLayer(); - } + + if (process_vf_adjust(vf, + context, + &ge2d_config) >= 0) + EnableVideoLayer(); + vf = vfq_peek(&q_ready); while (vf) { @@ -2966,6 +2977,17 @@ int ppmgr_buffer_uninit(void) canvas_pool_map_free_canvas(ppmgr_src_canvas[2]); ppmgr_src_canvas[2] = -1; + if (ass_index >= 0) + canvas_pool_map_free_canvas(ass_index); + ass_index = -1; + +#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER + /*for hdmi output*/ + if (backup_index >= 0) + canvas_pool_map_free_canvas(backup_index); + backup_index = -1; +#endif + ppmgr_buffer_status = 0; return 0; } @@ -3155,13 +3177,22 @@ int ppmgr_buffer_init(int vout_mode) CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); } - - ass_index = PPMGR_CANVAS_INDEX + VF_POOL_SIZE; /*for rotate while pause status*/ + if (ass_index < 0) + ass_index = canvas_pool_map_alloc_canvas(keep_owner); + if (ass_index < 0) { + PPMGRVPP_INFO("ass_index alloc failed\n"); + return -1; + } #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER - backup_index = PPMGR_CANVAS_INDEX + VF_POOL_SIZE + 1; /*for hdmi output*/ + if (backup_index < 0) + backup_index = canvas_pool_map_alloc_canvas(keep_owner); + if (backup_index < 0) { + PPMGRVPP_INFO("backup_index alloc failed\n"); + return -1; + } #endif #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS @@ -3175,36 +3206,6 @@ int ppmgr_buffer_init(int vout_mode) Init3DBuff(PPMGR_CANVAS_INDEX + VF_POOL_SIZE + ASS_POOL_SIZE); #endif - - canvas_config(PPMGR_DEINTERLACE_BUF_CANVAS, - (ulong)(buf_start - + (VF_POOL_SIZE + ASS_POOL_SIZE) * decbuf_size - + canvas_width * canvas_height * MASK_POOL_SIZE), - canvas_width, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - canvas_config(PPMGR_DEINTERLACE_BUF_CANVAS + 1, - (ulong)(buf_start - + (VF_POOL_SIZE + ASS_POOL_SIZE) * decbuf_size - + canvas_width * canvas_height * MASK_POOL_SIZE - + canvas_width * canvas_height), canvas_width >> 1, - canvas_height >> 1, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - canvas_config(PPMGR_DEINTERLACE_BUF_CANVAS + 2, - (ulong)(buf_start - + (VF_POOL_SIZE + ASS_POOL_SIZE) * decbuf_size - + canvas_width * canvas_height * MASK_POOL_SIZE - + (canvas_width * canvas_height * 5) / 4), - canvas_width >> 1, canvas_height >> 1, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); - - canvas_config(PPMGR_DEINTERLACE_BUF_NV21_CANVAS, - (ulong)(buf_start - + (VF_POOL_SIZE + ASS_POOL_SIZE) * decbuf_size - + canvas_width * canvas_height * MASK_POOL_SIZE), - canvas_width * 3, canvas_height, - CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); } else { canvas_width = 1920; @@ -3447,7 +3448,7 @@ static void tb_detect_init(void) static int tb_task(void *data) { int tbff_flag; - struct tbff_stats *pReg = NULL; + struct tbff_stats *tb_reg = NULL; ulong y5fld[5]; int is_top; int inited = 0; @@ -3458,15 +3459,15 @@ static int tb_task(void *data) sched_setscheduler(current, SCHED_FIFO, ¶m); inter_flag = 0; - pReg = kmalloc(sizeof(struct tbff_stats), GFP_KERNEL); - if (IS_ERR_OR_NULL(pReg)) { - PPMGRVPP_INFO("pReg malloc fail\n"); + tb_reg = kmalloc(sizeof(*tb_reg), GFP_KERNEL); + if (!tb_reg) { + PPMGRVPP_INFO("tb_reg malloc fail\n"); return 0; } - memset(pReg, 0, sizeof(struct tbff_stats)); + memset(tb_reg, 0, sizeof(struct tbff_stats)); if (gfunc) - gfunc->stats_init(pReg, TB_DETECT_H, TB_DETECT_W); + gfunc->stats_init(tb_reg, TB_DETECT_H, TB_DETECT_W); allow_signal(SIGTERM); while (down_interruptible(&tb_sem) == 0) { if (kthread_should_stop() || tb_quit_flag) @@ -3487,8 +3488,9 @@ static int tb_task(void *data) y5fld[3] = detect_buf[tb_buff_rptr + 1].vaddr; y5fld[4] = detect_buf[tb_buff_rptr].vaddr; if (gfunc) { - if (IS_ERR_OR_NULL(pReg)) { - PPMGRVPP_INFO("pReg is NULL!\n"); + if (IS_ERR_OR_NULL(tb_reg)) { + kfree(tb_reg); + PPMGRVPP_INFO("tb_reg is NULL!\n"); return 0; } for (i = 0; i < 5; i++) { @@ -3503,13 +3505,13 @@ static int tb_task(void *data) inter_flag = 0; continue; } - gfunc->stats_get(y5fld, pReg); + gfunc->stats_get(y5fld, tb_reg); } is_top = is_top ^ 1; tbff_flag = -1; if (gfunc) tbff_flag = gfunc->fwalg_get( - pReg, is_top, + tb_reg, is_top, (tb_first_frame_type == 3) ? 0 : 1, tb_buff_rptr, atomic_read(&tb_skip_flag), @@ -3556,7 +3558,7 @@ static int tb_task(void *data) } } atomic_set(&tb_run_flag, 0); - kfree(pReg); + kfree(tb_reg); while (!kthread_should_stop()) usleep_range(9000, 10000); return 0; diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c index bc424e7ee36a..7fa1c2f427a6 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo.c @@ -322,15 +322,12 @@ static int vidioc_g_parm(struct file *file, void *priv, struct v4l2_streamparm *parms) { struct vivi_dev *dev = video_drvdata(file); - struct v4l2_amlogic_parm *ap - = (struct v4l2_amlogic_parm *)&parms->parm.capture; if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - memset(ap, 0, sizeof(struct v4l2_amlogic_parm)); - *ap = dev->am_parm; - + memcpy(parms->parm.raw_data, (u8 *)&dev->am_parm, + sizeof(struct v4l2_amlogic_parm)); return 0; } @@ -675,7 +672,6 @@ static int amlvideo_open(struct file *file) { struct vivi_dev *dev = video_drvdata(file); struct vivi_fh *fh = NULL; - int retval = 0; struct videobuf_res_privdata *res = NULL; char *bstart = NULL; unsigned int bsize = 0; @@ -691,6 +687,7 @@ static int amlvideo_open(struct file *file) } res = kzalloc(sizeof(*res), GFP_KERNEL); if ((res == NULL) || (dev->res != NULL)) { + kfree(res); dev->users--; mutex_unlock(&dev->mutex); return -ENOMEM; @@ -700,7 +697,7 @@ static int amlvideo_open(struct file *file) kfree(res); dev->users--; mutex_unlock(&dev->mutex); - retval = -ENOMEM; + return -ENOMEM; } } mutex_unlock(&dev->mutex); @@ -962,8 +959,9 @@ static int __init amlvideo_create_instance(int inst) rel_vdev: video_device_release(vfd); unreg_dev: v4l2_device_unregister(&dev->v4l2_dev); -free_dev: kfree(dev); +free_dev: dev->res = NULL; + kfree(dev); return ret; } diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 78a15aae4099..839d86079178 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -401,6 +402,7 @@ struct completion plug_sema; bool field_flag; bool field_condition_flag; bool ge2d_multi_process_flag; +int aml2_canvas[3]; }; struct amlvideo2_fh { @@ -864,7 +866,7 @@ struct amlvideo2_node *node) struct canvas_s cs0, cs1, cs2, cd; int current_mirror; int cur_angle = 0; - int output_canvas = vf->canvas0Addr; + int output_canvas = output->canvas_id; /* ============================ */ /* top field */ @@ -961,7 +963,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1060,18 +1063,58 @@ struct amlvideo2_node *node) ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -1079,7 +1122,6 @@ struct amlvideo2_node *node) ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format(vf); ge2d_config->src_para.fill_color_en = 0; @@ -1142,12 +1184,14 @@ struct amlvideo2_node *node) return -1; } if (amlvideo2_dbg_en & 4) { - pr_info("src0_addr = %lx, w = %d, h = %d\n", - cs0.addr, cs0.width, cs0.height); - pr_info("src1_addr = %lx, w = %d, h = %d\n", - cs1.addr, cs1.width, cs1.height); - pr_info("src2_addr = %lx, w = %d, h = %d\n", - cs2.addr, cs2.width, cs2.height); + if (vf->canvas0Addr != (u32)-1) { + pr_info("src0_addr = %lx, w = %d, h = %d\n", + cs0.addr, cs0.width, cs0.height); + pr_info("src1_addr = %lx, w = %d, h = %d\n", + cs1.addr, cs1.width, cs1.height); + pr_info("src2_addr = %lx, w = %d, h = %d\n", + cs2.addr, cs2.width, cs2.height); + } pr_info("output: w = %d, h = %d, output_canvas = %x\n\n", output->width, output->height, output_canvas); @@ -1323,7 +1367,8 @@ struct amlvideo2_node *node) if (src_width < src_height) cur_angle = (cur_angle + 90) % 360; if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1411,18 +1456,58 @@ struct amlvideo2_node *node) ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas1Addr & 0xff, &cs0); - canvas_read((vf->canvas1Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas1Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas1Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas1_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas1_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas1_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas1_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas1_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas1_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas1_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas1_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas1_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas1_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas1_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas1_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas1Addr & 0xff, &cs0); + canvas_read((vf->canvas1Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas1Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas1Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -1430,7 +1515,6 @@ struct amlvideo2_node *node) ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas1Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format(vf); ge2d_config->src_para.fill_color_en = 0; @@ -1700,7 +1784,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -1801,18 +1886,58 @@ struct amlvideo2_node *node) ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -1820,7 +1945,6 @@ struct amlvideo2_node *node) ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_interlace_input_format(vf, output); ge2d_config->src_para.fill_color_en = 0; @@ -1882,12 +2006,14 @@ struct amlvideo2_node *node) return -1; } if (amlvideo2_dbg_en & 4) { - pr_info("src0_addr = %lx, w = %d, h = %d\n", - cs0.addr, cs0.width, cs0.height); - pr_info("src1_addr = %lx, w = %d, h = %d\n", - cs1.addr, cs1.width, cs1.height); - pr_info("src2_addr = %lx, w = %d, h = %d\n", - cs2.addr, cs2.width, cs2.height); + if (vf->canvas0Addr != (u32)-1) { + pr_info("src0_addr = %lx, w = %d, h = %d\n", + cs0.addr, cs0.width, cs0.height); + pr_info("src1_addr = %lx, w = %d, h = %d\n", + cs1.addr, cs1.width, cs1.height); + pr_info("src2_addr = %lx, w = %d, h = %d\n", + cs2.addr, cs2.width, cs2.height); + } pr_info("output: w = %d, h = %d, output_canvas = %x\n\n", output->width, output->height, output_canvas); @@ -2102,7 +2228,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2201,18 +2328,58 @@ struct amlvideo2_node *node) ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -2220,7 +2387,6 @@ struct amlvideo2_node *node) ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format_no_interlace(vf); ge2d_config->src_para.fill_color_en = 0; @@ -2282,12 +2448,14 @@ struct amlvideo2_node *node) return -1; } if (amlvideo2_dbg_en & 4) { - pr_info("src0_addr = %lx, w = %d, h = %d\n", - cs0.addr, cs0.width, cs0.height); - pr_info("src1_addr = %lx, w = %d, h = %d\n", - cs1.addr, cs1.width, cs1.height); - pr_info("src2_addr = %lx, w = %d, h = %d\n", - cs2.addr, cs2.width, cs2.height); + if (vf->canvas0Addr != (u32)-1) { + pr_info("src0_addr = %lx, w = %d, h = %d\n", + cs0.addr, cs0.width, cs0.height); + pr_info("src1_addr = %lx, w = %d, h = %d\n", + cs1.addr, cs1.width, cs1.height); + pr_info("src2_addr = %lx, w = %d, h = %d\n", + cs2.addr, cs2.width, cs2.height); + } pr_info("output: w = %d, h = %d, output_canvas = %x\n\n", output->width, output->height, output_canvas); @@ -2502,7 +2670,8 @@ struct amlvideo2_node *node) } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -2601,18 +2770,58 @@ struct amlvideo2_node *node) ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -2620,7 +2829,6 @@ struct amlvideo2_node *node) ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_interlace_input_format(vf, output); ge2d_config->src_para.fill_color_en = 0; @@ -2682,12 +2890,14 @@ struct amlvideo2_node *node) return -1; } if (amlvideo2_dbg_en & 4) { - pr_info("src0_addr = %lx, w = %d, h = %d\n", - cs0.addr, cs0.width, cs0.height); - pr_info("src1_addr = %lx, w = %d, h = %d\n", - cs1.addr, cs1.width, cs1.height); - pr_info("src2_addr = %lx, w = %d, h = %d\n", - cs2.addr, cs2.width, cs2.height); + if (vf->canvas0Addr != (u32)-1) { + pr_info("src0_addr = %lx, w = %d, h = %d\n", + cs0.addr, cs0.width, cs0.height); + pr_info("src1_addr = %lx, w = %d, h = %d\n", + cs1.addr, cs1.width, cs1.height); + pr_info("src2_addr = %lx, w = %d, h = %d\n", + cs2.addr, cs2.width, cs2.height); + } pr_info("output: w = %d, h = %d, output_canvas = %x\n\n", output->width, output->height, output_canvas); @@ -2879,18 +3089,58 @@ int amlvideo2_ge2d_multi_pre_process(struct vframe_s *vf, ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -2898,7 +3148,6 @@ int amlvideo2_ge2d_multi_pre_process(struct vframe_s *vf, ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format(vf); ge2d_config->src_para.fill_color_en = 0; @@ -3110,7 +3359,8 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, } if ((node->crop_info.capture_crop_enable == 0) && - (node->porttype != TVIN_PORT_VIU1_VIDEO)) { + ((node->porttype != TVIN_PORT_VIU1_VIDEO) && + (node->porttype != TVIN_PORT_VIU1_WB0_VD1))) { output_axis_adjust( src_width, src_height, &dst_width, &dst_height, @@ -3209,18 +3459,58 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, ge2d_config->src1_gb_alpha = 0;/* 0xff; */ ge2d_config->dst_xy_swap = 0; - canvas_read(vf->canvas0Addr & 0xff, &cs0); - canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); - canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); - ge2d_config->src_planes[0].addr = cs0.addr; - ge2d_config->src_planes[0].w = cs0.width; - ge2d_config->src_planes[0].h = cs0.height; - ge2d_config->src_planes[1].addr = cs1.addr; - ge2d_config->src_planes[1].w = cs1.width; - ge2d_config->src_planes[1].h = cs1.height; - ge2d_config->src_planes[2].addr = cs2.addr; - ge2d_config->src_planes[2].w = cs2.width; - ge2d_config->src_planes[2].h = cs2.height; + if (vf->canvas0Addr == (u32)-1) { + canvas_config_config(node->aml2_canvas[0], + &vf->canvas0_config[0]); + if (vf->plane_num == 2) { + canvas_config_config( + node->aml2_canvas[1], + &vf->canvas0_config[1]); + } else if (vf->plane_num == 3) { + canvas_config_config( + node->aml2_canvas[2], + &vf->canvas0_config[2]); + } + ge2d_config->src_para.canvas_index = + node->aml2_canvas[0] + | (node->aml2_canvas[1] << 8) + | (node->aml2_canvas[2] << 16); + ge2d_config->src_planes[0].addr = + vf->canvas0_config[0].phy_addr; + ge2d_config->src_planes[0].w = + vf->canvas0_config[0].width; + ge2d_config->src_planes[0].h = + vf->canvas0_config[0].height; + ge2d_config->src_planes[1].addr = + vf->canvas0_config[1].phy_addr; + ge2d_config->src_planes[1].w = + vf->canvas0_config[1].width; + ge2d_config->src_planes[1].h = + vf->canvas0_config[1].height >> 1; + if (vf->plane_num == 3) { + ge2d_config->src_planes[2].addr = + vf->canvas0_config[2].phy_addr; + ge2d_config->src_planes[2].w = + vf->canvas0_config[2].width; + ge2d_config->src_planes[2].h = + vf->canvas0_config[2].height >> 1; + } + } else { + canvas_read(vf->canvas0Addr & 0xff, &cs0); + canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1); + canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2); + ge2d_config->src_planes[0].addr = cs0.addr; + ge2d_config->src_planes[0].w = cs0.width; + ge2d_config->src_planes[0].h = cs0.height; + ge2d_config->src_planes[1].addr = cs1.addr; + ge2d_config->src_planes[1].w = cs1.width; + ge2d_config->src_planes[1].h = cs1.height; + ge2d_config->src_planes[2].addr = cs2.addr; + ge2d_config->src_planes[2].w = cs2.width; + ge2d_config->src_planes[2].h = cs2.height; + ge2d_config->src_para.canvas_index = vf->canvas0Addr; + } + canvas_read(output_canvas & 0xff, &cd); ge2d_config->dst_planes[0].addr = cd.addr; ge2d_config->dst_planes[0].w = cd.width; @@ -3228,7 +3518,6 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, ge2d_config->src_key.key_enable = 0; ge2d_config->src_key.key_mask = 0; ge2d_config->src_key.key_mode = 0; - ge2d_config->src_para.canvas_index = vf->canvas0Addr; ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID; ge2d_config->src_para.format = get_input_format(vf); ge2d_config->src_para.fill_color_en = 0; @@ -3290,12 +3579,14 @@ int amlvideo2_ge2d_pre_process(struct vframe_s *vf, return -1; } if (amlvideo2_dbg_en & 4) { - pr_info("src0_addr = %lx, w = %d, h = %d\n", - cs0.addr, cs0.width, cs0.height); - pr_info("src1_addr = %lx, w = %d, h = %d\n", - cs1.addr, cs1.width, cs1.height); - pr_info("src2_addr = %lx, w = %d, h = %d\n", - cs2.addr, cs2.width, cs2.height); + if (vf->canvas0Addr != (u32)-1) { + pr_info("src0_addr = %lx, w = %d, h = %d\n", + cs0.addr, cs0.width, cs0.height); + pr_info("src1_addr = %lx, w = %d, h = %d\n", + cs1.addr, cs1.width, cs1.height); + pr_info("src2_addr = %lx, w = %d, h = %d\n", + cs2.addr, cs2.width, cs2.height); + } pr_info("output: w = %d, h = %d, output_canvas = %x\n\n", output->width, output->height, output_canvas); @@ -3592,7 +3883,7 @@ static int amlvideo2_thread_tick(struct amlvideo2_fh *fh) if ((node->video_blocking) && (node->amlvideo2_pool_ready != NULL)) { vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); node->video_blocking = false; node->tmp_vf = NULL; @@ -4028,7 +4319,14 @@ static int amlvideo2_thread(void *data) } /*msleep(10);*/ - node->tmp_vf = NULL; + if (node->tmp_vf != NULL) { + if ((node->recv.name != NULL) && + (!vf_get_receiver(node->recv.name))) { + vf_put(node->tmp_vf, node->recv.name); + } + node->tmp_vf = NULL; + } + if (amlvideo2_dbg_en) { if (node->vid == 0) pr_info("amlvideo2.0 thread exit.\n"); @@ -4089,8 +4387,13 @@ static int amlvideo2_start_thread(struct amlvideo2_fh *fh) static void amlvideo2_stop_thread(struct amlvideo2_node_dmaqueue *dma_q) { int ret = 0; - struct amlvideo2_node *node = - container_of(dma_q, struct amlvideo2_node, vidq); + struct amlvideo2_node *node; + + if (IS_ERR_OR_NULL(dma_q)) { + pr_info("dma_q is NULL\n"); + return; + } + node = container_of(dma_q, struct amlvideo2_node, vidq); dpr_err(node->vid_dev, 1, "%s\n", __func__); if (amlvideo2_dbg_en & 1) { if (node->vid == 0) @@ -4100,7 +4403,7 @@ static void amlvideo2_stop_thread(struct amlvideo2_node_dmaqueue *dma_q) } mutex_lock(&node->mutex); /* shutdown control thread */ - if (!IS_ERR(dma_q->kthread)) { + if (!IS_ERR_OR_NULL(dma_q->kthread)) { dma_q->task_running = 0; send_sig(SIGTERM, dma_q->kthread, 1); #ifdef USE_SEMA_QBUF @@ -4788,10 +5091,11 @@ static int amlvideo2_start_tvin_service(struct amlvideo2_node *node) para.dest_vactive = dst_h; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) + para.cfmt = 1; + if (amlvideo2_dbg_en) { pr_info("node->r_type=%d, node->p_type=%d\n", node->r_type, node->p_type); @@ -4960,7 +5264,9 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } memset(&node->display_info, 0, sizeof(struct vdisplay_info_s)); - if (!node->start_vdin_flag) { + if ((!node->start_vdin_flag) || + (node->porttype == TVIN_PORT_VIU1_WB0_VD1) || + (node->porttype == TVIN_PORT_VIU1_VIDEO)) { ret = vf_notify_receiver_by_name("amvideo", VFRAME_EVENT_PROVIDER_QUREY_DISPLAY_INFO, &node->display_info); @@ -5013,8 +5319,16 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) para.port = node->porttype; para.fmt = TVIN_SIG_FMT_MAX; para.frame_rate = vinfo->sync_duration_num/vinfo->sync_duration_den; - para.h_active = vinfo->width; - para.v_active = vinfo->height; + if ((para.port == TVIN_PORT_VIU1_WB0_VD1) || + (para.port == TVIN_PORT_VIU1_VIDEO)) { + para.h_active = (node->display_info.display_hsc_endp - + node->display_info.display_hsc_startp + 1); + para.v_active = (node->display_info.display_vsc_endp - + node->display_info.display_vsc_startp + 1); + } else { + para.h_active = vinfo->width; + para.v_active = vinfo->height; + } para.hsync_phase = 0; para.vsync_phase = 1; para.hs_bp = 0; @@ -5057,14 +5371,13 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) para.reserved |= PARAM_STATE_SCREENCAP; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; - if (para.port == TVIN_PORT_VIU1_VIDEO) { + if ((para.port == TVIN_PORT_VIU1_VIDEO) || + (para.port == TVIN_PORT_VIU1_WB0_VD1)) { if (node->ge2d_multi_process_flag) { para.dest_hactive = 384; para.dest_vactive = 216; - } else { - para.dest_hactive = 0; - para.dest_vactive = 0; - } + } else + para.cfmt = 1; } if (amlvideo2_dbg_en) { pr_info("para.h_active: %d, para.v_active: %d,", @@ -5336,9 +5649,59 @@ static int vidioc_s_output(struct file *file, void *fh, return 0; } +static int alloc_canvas(struct amlvideo2_node *node) +{ + const char *keep_owner = "amlvideo2"; + + if (node->aml2_canvas[0] < 0) + node->aml2_canvas[0] = + canvas_pool_map_alloc_canvas(keep_owner); + if (node->aml2_canvas[1] < 0) + node->aml2_canvas[1] = + canvas_pool_map_alloc_canvas(keep_owner); + if (node->aml2_canvas[2] < 0) + node->aml2_canvas[2] = + canvas_pool_map_alloc_canvas(keep_owner); + + if ((node->aml2_canvas[0] < 0) || + (node->aml2_canvas[1] < 0) || + (node->aml2_canvas[2] < 0)) { + pr_err("amlvideo2 canvas alloc failed\n"); + return -1; + } + return 0; +} + +static int free_canvas(struct amlvideo2_node *node) +{ + if (node->aml2_canvas[0] >= 0) { + canvas_pool_map_free_canvas(node->aml2_canvas[0]); + node->aml2_canvas[0] = -1; + } + + if (node->aml2_canvas[1] >= 0) { + canvas_pool_map_free_canvas(node->aml2_canvas[1]); + node->aml2_canvas[1] = -1; + } + + if (node->aml2_canvas[2] >= 0) { + canvas_pool_map_free_canvas(node->aml2_canvas[2]); + node->aml2_canvas[2] = -1; + } + + if ((node->aml2_canvas[0] >= 0) || + (node->aml2_canvas[1] >= 0) || + (node->aml2_canvas[2] >= 0)) { + pr_err("amlvideo2 canvas free failed!\n"); + return -1; + } + return 0; +} + int amlvideo2_cma_buf_init(struct amlvideo2_device *vid_dev, int node_id) { int flags; + int ret; if (!vid_dev->use_reserve) { if (vid_dev->cma_mode == 0) { @@ -5356,6 +5719,12 @@ int amlvideo2_cma_buf_init(struct amlvideo2_device *vid_dev, int node_id) } else { flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_CMA_CLEAR; + ret = alloc_canvas(vid_dev->node[node_id]); + if (ret < 0) { + pr_err("amlvideo2 alloc cma failed!\n"); + return -1; + } + if (node_id == 0) { if (vid_dev->node[node_id]-> ge2d_multi_process_flag == 1) @@ -5414,6 +5783,7 @@ int amlvideo2_cma_buf_init(struct amlvideo2_device *vid_dev, int node_id) int amlvideo2_cma_buf_uninit(struct amlvideo2_device *vid_dev, int node_id) { + int ret; if (!vid_dev->use_reserve) { if (vid_dev->cma_mode == 0) { if (vid_dev->cma_pages) { @@ -5424,6 +5794,10 @@ int amlvideo2_cma_buf_uninit(struct amlvideo2_device *vid_dev, int node_id) vid_dev->cma_pages = NULL; } } else { + ret = free_canvas(vid_dev->node[node_id]); + if (ret < 0) + pr_err("%s free canvas fail! line: %d", + __func__, __LINE__); if (vid_dev->buffer_start != 0) { if (node_id == 0) { codec_mm_free_for_dma( @@ -5748,7 +6122,7 @@ static int amlvideo2_receiver_event_fun(int type, void *data, case VFRAME_EVENT_PROVIDER_REG: node->video_blocking = false; vfq_init(&node->q_ready, - node->amlvideo2_pool_size + 1, + node->amlvideo2_pool_size, (struct vframe_s **)&(node->amlvideo2_pool_ready[0])); break; case VFRAME_EVENT_PROVIDER_UNREG: @@ -5806,6 +6180,7 @@ static int amlvideo2_release_node(struct amlvideo2_device *vid_dev) { int i = 0; struct video_device *vfd = NULL; + int ret; for (i = 0; i < vid_dev->node_num; i++) { if (vid_dev->node[i]) { @@ -5818,6 +6193,10 @@ static int amlvideo2_release_node(struct amlvideo2_device *vid_dev) kfree(vid_dev->node[i]->fh); kfree(vid_dev->node[i]->amlvideo2_pool_ready); vid_dev->node[i]->fh = NULL; + ret = free_canvas(vid_dev->node[i]); + if (ret < 0) + pr_err("%s free canvas failed! line: %d\n", + __func__, __LINE__); kfree(vid_dev->node[i]); vid_dev->node[i] = NULL; } @@ -5874,7 +6253,7 @@ static int amlvideo2_create_node(struct platform_device *pdev, int node_id) vid_node->amlvideo2_pool_ready = NULL; vid_node->amlvideo2_pool_size = 12; vid_node->amlvideo2_pool_ready = - kmalloc((sizeof(struct vframe_s *) * + kmalloc((sizeof(struct vframe_s) * (vid_node->amlvideo2_pool_size)), GFP_KERNEL); if (!vid_node->amlvideo2_pool_ready) { @@ -5884,7 +6263,7 @@ static int amlvideo2_create_node(struct platform_device *pdev, int node_id) } if (vid_node->amlvideo2_pool_ready != NULL) { vfq_init(&vid_node->q_ready, - vid_node->amlvideo2_pool_size + 1, + vid_node->amlvideo2_pool_size, (struct vframe_s **)&(vid_node->amlvideo2_pool_ready[0])); } vid_node->context = create_ge2d_work_queue(); @@ -5964,6 +6343,9 @@ static int amlvideo2_create_node(struct platform_device *pdev, int node_id) vid_node->field_condition_flag = false; vid_node->ge2d_multi_process_flag = false; vid_node->r_type = AML_RECEIVER_NONE; + vid_node->aml2_canvas[0] = -1; + vid_node->aml2_canvas[1] = -1; + vid_node->aml2_canvas[2] = -1; vid_dev->node[node_id] = vid_node; v4l2_info(&vid_dev->v4l2_dev, "V4L2 device registered as %s\n", video_device_node_name(vfd)); diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.c b/drivers/amlogic/media/video_processor/videosync/videosync.c index a990854ca40c..40d0a2170c8d 100644 --- a/drivers/amlogic/media/video_processor/videosync/videosync.c +++ b/drivers/amlogic/media/video_processor/videosync/videosync.c @@ -40,7 +40,7 @@ static u32 omx_version = 3; static u32 vp_debug_flag; static bool no_render;/* default: false */ static bool async_mode;/* default: false */ -static u32 video_early_threshold = 900; /* default: 900=>10ms */ +/*static u32 video_early_threshold = 900; default: 900=>10ms */ /* video freerun mode */ @@ -52,6 +52,8 @@ static u32 video_early_threshold = 900; /* default: 900=>10ms */ #define M_PTS_SMOOTH_ADJUST 900 #define DURATION_GCD 750 +static int duration_gcd = DURATION_GCD; + static int omx_pts_interval_upper = 11000; static int omx_pts_interval_lower = -5500; #define DUR2PTS(x) ((x) - ((x) >> 4)) @@ -59,12 +61,40 @@ static int omx_pts_interval_lower = -5500; #define PRINT_ERROR 0X0 #define PRINT_QUEUE_STATUS 0X0001 #define PRINT_TIMESTAMP 0X0002 -#define PRINT_OTHER 0X0004 +#define PRINT_PATTERN 0X0004 +#define PRINT_OTHER 0X0008 + static struct videosync_dev *vp_dev; static uint show_first_frame_nosync; +static uint max_delata_time; + static u32 cur_omx_index; +#define PTS_32_PATTERN_DETECT_RANGE 10 +#define PTS_22_PATTERN_DETECT_RANGE 10 +#define PTS_41_PATTERN_DETECT_RANGE 2 +#define PTS_32_PATTERN_DURATION 3750 +#define PTS_22_PATTERN_DURATION 3000 + +enum video_refresh_pattern { + PTS_32_PATTERN = 0, + PTS_22_PATTERN, + PTS_41_PATTERN, + PTS_MAX_NUM_PATTERNS +}; + +static int pts_trace; +static int pre_pts_trace; +static bool pts_enforce_pulldown = true; +static int pts_pattern[3] = {0, 0, 0}; +static int pts_pattern_enter_cnt[3] = {0, 0, 0}; +static int pts_pattern_exit_cnt[3] = {0, 0, 0}; +static int pts_log_enable[3] = {0, 0, 0}; +static int pts_escape_vsync = -1; +static s32 vsync_pts_align = -DURATION_GCD / 2; +static int pts_pattern_detected = -1; + static int vp_print(char *name, int debug_flag, const char *fmt, ...) { if ((vp_debug_flag & debug_flag) @@ -85,7 +115,7 @@ static int vp_print(char *name, int debug_flag, const char *fmt, ...) static u32 ts_pcrscr_get(struct videosync_s *dev_s) { u32 sys_time = 0; - /*unsigned long flags;*/ + sys_time = dev_s->system_time; return sys_time; } @@ -106,6 +136,166 @@ static u32 ts_pcrscr_enable_state(struct videosync_s *dev_s) return dev_s->system_time_up; } +static void log_vsync_video_pattern(int pattern) +{ + int factor1 = 0, factor2 = 0, pattern_range = 0; + + if (pattern >= PTS_MAX_NUM_PATTERNS) + return; + + if (pattern == PTS_32_PATTERN) { + factor1 = 3; + factor2 = 2; + pattern_range = PTS_32_PATTERN_DETECT_RANGE; + } else if (pattern == PTS_22_PATTERN) { + factor1 = 2; + factor2 = 2; + pattern_range = PTS_22_PATTERN_DETECT_RANGE; + } else if (pattern == PTS_41_PATTERN) { + pr_info("not support 41 pattern\n"); + return; + } + + /* update 3:2 or 2:2 mode detection */ + if (((pre_pts_trace == factor1) && (pts_trace == factor2)) || + ((pre_pts_trace == factor2) && (pts_trace == factor1))) { + if (pts_pattern[pattern] < pattern_range) { + pts_pattern[pattern]++; + if (pts_pattern[pattern] == pattern_range) { + pts_pattern_enter_cnt[pattern]++; + pts_pattern_detected = pattern; + if (pts_log_enable[pattern]) + pr_info("video %d:%d mode detected\n", + factor1, factor2); + } + } + } else if (pts_pattern[pattern] == pattern_range) { + pts_pattern[pattern] = 0; + pts_pattern_exit_cnt[pattern]++; + if (pts_log_enable[pattern]) + pr_info("video %d:%d mode broken\n", factor1, factor2); + } else { + pts_pattern[pattern] = 0; + } +} + +static void vsync_video_pattern(void) +{ + /*log_vsync_video_pattern(PTS_32_PATTERN);*/ + log_vsync_video_pattern(PTS_22_PATTERN); + /*log_vsync_video_pattern(PTS_41_PATTERN);*/ +} + +static inline void vpts_perform_pulldown( + struct videosync_s *dev_s, + struct vframe_s *next_vf, + bool *expired) +{ + int pattern_range, expected_curr_interval; + int expected_prev_interval; + int next_vf_nextpts = 0; + int nextPts; + + /* Dont do anything if we have invalid data */ + if (!next_vf || !next_vf->pts) + return; + if (next_vf->next_vf_pts_valid) + next_vf_nextpts = next_vf->next_vf_pts; + + switch (pts_pattern_detected) { + case PTS_32_PATTERN: + pattern_range = PTS_32_PATTERN_DETECT_RANGE; + switch (pre_pts_trace) { + case 3: + expected_prev_interval = 3; + expected_curr_interval = 2; + break; + case 2: + expected_prev_interval = 2; + expected_curr_interval = 3; + break; + default: + return; + } + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_32_PATTERN_DURATION; + break; + case PTS_22_PATTERN: + if (pre_pts_trace != 2) + return; + pattern_range = PTS_22_PATTERN_DETECT_RANGE; + expected_prev_interval = 2; + expected_curr_interval = 2; + if (!next_vf_nextpts) + next_vf_nextpts = next_vf->pts + + PTS_22_PATTERN_DURATION; + break; + case PTS_41_PATTERN: + /* TODO */ + default: + return; + } + + /* We do nothing if we dont have enough data*/ + if (pts_pattern[pts_pattern_detected] != pattern_range) + return; + + if (*expired) { + if (pts_trace < expected_curr_interval) { + /* 2323232323..2233..2323, prev=2, curr=3,*/ + /* check if next frame will toggle after 3 vsyncs */ + /* 22222...22222 -> 222..2213(2)22...22 */ + /* check if next frame will toggle after 3 vsyncs */ + nextPts = ts_pcrscr_get(dev_s) + vsync_pts_align; + + if (((int)(nextPts + (expected_prev_interval + 1) * + vsync_pts_inc - next_vf_nextpts) >= 0)) { + *expired = false; + if (pts_log_enable[PTS_32_PATTERN] || + pts_log_enable[PTS_22_PATTERN]) + pr_info("hold frame for pattern: %d", + pts_pattern_detected); + } + + /* here need to escape a vsync */ + if (ts_pcrscr_get(dev_s) > + (next_vf->pts + vsync_pts_inc)) { + *expired = true; + pts_escape_vsync = 1; + if (pts_log_enable[PTS_32_PATTERN] || + pts_log_enable[PTS_22_PATTERN]) + pr_info("escape a vsync pattern: %d", + pts_pattern_detected); + } + } + } else { + if (pts_trace == expected_curr_interval) { + /* 23232323..233223...2323 curr=2, prev=3 */ + /* check if this frame will expire next vsyncs and */ + /* next frame will expire after 3 vsyncs */ + /* 22222...22222 -> 222..223122...22 */ + /* check if this frame will expire next vsyncs and */ + /* next frame will expire after 2 vsyncs */ + int nextPts = ts_pcrscr_get(dev_s) + vsync_pts_align; + + if (((int)(nextPts + vsync_pts_inc - next_vf->pts) + >= 0) && + ((int)(nextPts + + vsync_pts_inc * (expected_prev_interval - 1) + - next_vf_nextpts) < 0) && + ((int)(nextPts + expected_prev_interval * + vsync_pts_inc - next_vf_nextpts) >= 0)) { + *expired = true; + if (pts_log_enable[PTS_32_PATTERN] || + pts_log_enable[PTS_22_PATTERN]) + pr_info("pull frame for pattern: %d", + pts_pattern_detected); + } + } + } +} + void videosync_pcrscr_update(s32 inc, u32 base) { int i = 0; @@ -127,9 +317,11 @@ void videosync_pcrscr_update(s32 inc, u32 base) system_time_scale_base = base; } if (dev_s->system_time_up) { + dev_s->time_update = sched_clock(); dev_s->system_time += div_u64_rem(90000ULL * inc, base, &r) + system_time_inc_adj; + vsync_pts_inc = 90000 * inc / base; dev_s->system_time_scale_remainder += r; if (dev_s->system_time_scale_remainder >= system_time_scale_base) { @@ -157,7 +349,7 @@ void videosync_pcrscr_update(s32 inc, u32 base) current_omx_pts, diff); ts_pcrscr_set(dev_s, - current_omx_pts + DURATION_GCD); + current_omx_pts + duration_gcd); } } } @@ -203,6 +395,29 @@ static void videosync_vf_put(struct vframe_s *vf, void *op_arg) } } +void vsync_notify_videosync(void) +{ + int i = 0; + struct videosync_s *dev_s = NULL; + bool has_active = false; + + if (!videosync_inited) + return; + + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { + dev_s = &vp_dev->video_prov[i]; + if (dev_s && dev_s->active_state == VIDEOSYNC_ACTIVE) { + has_active = true; + break; + } + } + if (has_active) { + pts_trace++; + vp_dev->wakeup = 1; + wake_up_interruptible(&vp_dev->videosync_wait); + } +} + static int videosync_event_cb(int type, void *data, void *private_data) { return 0; @@ -701,10 +916,11 @@ static long videosync_ioctl(struct file *file, if (dev_id < VIDEOSYNC_S_COUNT) dev_s = &vp_dev->video_prov[dev_id]; - if (dev_s != NULL && dev_s->mapped) + if (dev_s && dev_s->mapped) { dev_s->show_first_frame_nosync = info[1]; - pr_info("show_first_frame_nosync =%d\n", - dev_s->show_first_frame_nosync); + pr_info("show_first_frame_nosync =%d\n", + dev_s->show_first_frame_nosync); + } } } break; @@ -756,18 +972,35 @@ static void clear_ready_queue(struct videosync_s *dev_s) } } +static u64 func_div(u64 number, u32 divid) +{ + u64 tmp = number; + + do_div(tmp, divid); + return tmp; +} + static inline bool omx_vpts_expire(struct vframe_s *cur_vf, struct vframe_s *next_vf, - struct videosync_s *dev_s) + struct videosync_s *dev_s, + int toggled_cnt) { - u32 pts = next_vf->pts; + u32 pts; #ifdef VIDEO_PTS_CHASE u32 vid_pts, scr_pts; #endif u32 systime; u32 adjust_pts, org_vpts; + unsigned long delta = 0; + int delta_32 = 0; /*u32 dur_pts = 0;*/ + bool expired; + + if (!next_vf) + return false; + + pts = next_vf->pts; if (dev_s->freerun_mode == FREERUN_NODUR) return true; @@ -848,8 +1081,45 @@ static inline bool omx_vpts_expire(struct vframe_s *cur_vf, dev_s->video_frame_repeat_count = 0; } } + delta = func_div(sched_clock() - dev_s->time_update, 1000); + delta_32 = delta * 90 / 1000; + if (delta_32 > max_delata_time) + max_delata_time = delta_32; - return (systime + video_early_threshold) > pts; + expired = (systime + vsync_pts_align) >= pts; + + vp_print(dev_s->vf_receiver_name, PRINT_PATTERN, + "expired=%d, valid=%d, next_pts=%d, cnt=%d, systime=%d, inc=%d\n", + expired, + next_vf->next_vf_pts_valid, + next_vf->next_vf_pts, + toggled_cnt, + systime, + vsync_pts_inc); + + if (expired && next_vf->next_vf_pts_valid && + pts_enforce_pulldown && + next_vf->next_vf_pts && + (toggled_cnt > 0) && + ((int)(systime + vsync_pts_inc + + vsync_pts_align - next_vf->next_vf_pts) < 0)) { + expired = false; + vp_print(dev_s->vf_receiver_name, PRINT_PATTERN, + "force expired false\n"); + } else if (!expired && next_vf->next_vf_pts_valid && + pts_enforce_pulldown && + next_vf->next_vf_pts && + (toggled_cnt == 0) && + ((int)(systime + vsync_pts_inc + + vsync_pts_align - next_vf->next_vf_pts) >= 0)) { + expired = true; + vp_print(dev_s->vf_receiver_name, PRINT_PATTERN, + "force expired true\n"); + } + + if (pts_enforce_pulldown) + vpts_perform_pulldown(dev_s, next_vf, &expired); + return expired; } @@ -857,6 +1127,7 @@ void videosync_sync(struct videosync_s *dev_s) { int ready_q_size = 0; struct vframe_s *vf; + int expire_count = 0; if (smooth_sync_enable) { if (dev_s->video_frame_repeat_count) @@ -866,7 +1137,7 @@ void videosync_sync(struct videosync_s *dev_s) vf = vfq_peek(&dev_s->queued_q); while (vf) { - if (omx_vpts_expire(dev_s->cur_dispbuf, vf, dev_s) + if (omx_vpts_expire(dev_s->cur_dispbuf, vf, dev_s, expire_count) || show_nosync) { vf = vfq_pop(&dev_s->queued_q); @@ -876,6 +1147,15 @@ void videosync_sync(struct videosync_s *dev_s) clear_ready_queue(dev_s); } + if (pts_escape_vsync == 1) { + pts_trace++; + pts_escape_vsync = 0; + } + vsync_video_pattern(); + pre_pts_trace = pts_trace; + pts_trace = 0; + expire_count++; + vfq_push(&dev_s->ready_q, vf); ready_q_size = vfq_level(&dev_s->ready_q); vp_print(dev_s->vf_receiver_name, @@ -923,7 +1203,7 @@ static void prepare_queued_queue(struct videosync_dev *dev) continue; } - if (vf_peek(dev_s->vf_receiver_name)) { + while (vf_peek(dev_s->vf_receiver_name)) { vf = vf_get(dev_s->vf_receiver_name); if (vf) { vfq_push(&dev_s->queued_q, vf); @@ -935,9 +1215,6 @@ static void prepare_queued_queue(struct videosync_dev *dev) vf->index, vfq_level(&dev_s->queued_q)); } - } else { - vp_print(dev_s->vf_receiver_name, PRINT_OTHER, - "peek failed %d\n"); } } @@ -1006,6 +1283,8 @@ static int videosync_receiver_event_fun(int type, void *data, if (dev_s->active_state == VIDEOSYNC_ACTIVE) { dev_s->active_state = VIDEOSYNC_INACTIVE_REQ; + dev->wakeup = 1; + wake_up_interruptible(&dev->videosync_wait); time_left = wait_for_completion_timeout( &dev_s->inactive_done, msecs_to_jiffies(100)); @@ -1043,6 +1322,10 @@ static int videosync_receiver_event_fun(int type, void *data, complete(&dev->thread_active); pr_info("videosync: reg %p, %s\n", dev_s, dev_s->vf_receiver_name); + pts_trace = 0; + pts_pattern_detected = -1; + pre_pts_trace = 0; + pts_escape_vsync = 0; } else if (type == VFRAME_EVENT_PROVIDER_VFRAME_READY) { } else if (type == VFRAME_EVENT_PROVIDER_START) { @@ -1149,6 +1432,10 @@ static void videosync_thread_tick(struct videosync_dev *dev) if (!dev) return; + wait_event_interruptible_timeout(dev->videosync_wait, dev->wakeup, + msecs_to_jiffies(500)); + dev->wakeup = 0; + for (i = 0; i < VIDEOSYNC_S_COUNT; i++) { dev_s = &dev->video_prov[i]; if (dev_s->active_state == VIDEOSYNC_INACTIVE_REQ) { @@ -1165,7 +1452,6 @@ static void videosync_thread_tick(struct videosync_dev *dev) spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); prepare_queued_queue(dev); prepare_ready_queue(dev); - usleep_range(7000, 8000); } else { spin_unlock_irqrestore(&dev->dev_s_num_slock, flags); vp_print(RECEIVER_NAME, PRINT_OTHER, @@ -1248,6 +1534,8 @@ static int __init videosync_init(void) } init_completion(&vp_dev->thread_active); + vp_dev->wakeup = 0; + init_waitqueue_head(&vp_dev->videosync_wait); vp_dev->kthread = kthread_run(videosync_thread, vp_dev, "videosync"); videosync_inited = true; return ret; @@ -1306,11 +1594,20 @@ module_param(no_render, bool, 0664); MODULE_PARM_DESC(async_mode, "\n async_mode\n"); module_param(async_mode, bool, 0664); -MODULE_PARM_DESC(video_early_threshold, "\n video_early_threshold\n"); -module_param(video_early_threshold, uint, 0664); +MODULE_PARM_DESC(vsync_pts_align, "\n vsync_pts_align\n"); +module_param(vsync_pts_align, int, 0664); MODULE_PARM_DESC(cur_omx_index, "\n cur_omx_index\n"); module_param(cur_omx_index, uint, 0664); MODULE_PARM_DESC(show_first_frame_nosync, "\n show_first_frame_nosync\n"); module_param(show_first_frame_nosync, uint, 0664); + +MODULE_PARM_DESC(max_delata_time, "\n max_delata_time\n"); +module_param(max_delata_time, uint, 0664); + +MODULE_PARM_DESC(duration_gcd, "\n duration_gcd\n"); +module_param(duration_gcd, uint, 0664); + +module_param(pts_enforce_pulldown, bool, 0644); +MODULE_PARM_DESC(pts_enforce_pulldown, "enforce video frame pulldown if needed"); diff --git a/drivers/amlogic/media/video_processor/videosync/videosync.h b/drivers/amlogic/media/video_processor/videosync/videosync.h index e36f39e23d93..e212c630bf5e 100644 --- a/drivers/amlogic/media/video_processor/videosync/videosync.h +++ b/drivers/amlogic/media/video_processor/videosync/videosync.h @@ -57,6 +57,8 @@ struct videosync_dev { struct mutex vp_mutex; spinlock_t dev_s_num_slock; u32 active_dev_s_num; + wait_queue_head_t videosync_wait; + int wakeup; }; extern bool omx_secret_mode; @@ -140,6 +142,7 @@ struct videosync_s { u32 zorder; struct vframe_provider_s video_vf_prov; char vf_provider_name[VIDEOSYNC_VF_NAME_SIZE]; + long long time_update; }; diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index 11c02a683c5b..bdfb586d8647 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -1991,16 +1991,22 @@ void hdmirx_20_init(void) data32 |= SCRAMBLE_SEL << 0; /* [1:0] scramble_sel */ hdmirx_wr_dwc(DWC_HDMI20_CONTROL, data32); -data32 = 0; -data32 |= 0 << 1; /* [1] hpd_low */ -data32 |= 1 << 0; /* [0] power_provided */ -hdmirx_wr_dwc(DWC_SCDC_CONFIG, data32); + data32 = 0; + data32 |= 1 << 24; /* [25:24] i2c_spike_suppr */ + data32 |= 0 << 20; /* [20] i2c_timeout_en */ + data32 |= 0 << 0; /* [19:0] i2c_timeout_cnt */ + hdmirx_wr_dwc(DWC_SCDC_I2CCONFIG, data32); data32 = 0; data32 |= 1 << 1; /* [1] hpd_low */ data32 |= 0 << 0; /* [0] power_provided */ hdmirx_wr_dwc(DWC_SCDC_CONFIG, data32); + data32 = 0; + data32 |= 0xabcdef << 8; /* [31:8] manufacture_oui */ + data32 |= 1 << 0; /* [7:0] sink_version */ + hdmirx_wr_dwc(DWC_SCDC_WRDATA0, data32); + data32 = 0; data32 |= 10 << 20; /* [29:20] chlock_max_err */ data32 |= 24000 << 0; /* [15:0] milisec_timer_limit */ diff --git a/drivers/amlogic/media/vout/backlight/aml_bl.c b/drivers/amlogic/media/vout/backlight/aml_bl.c index 2d84bdb4916a..58bb3fb78f94 100644 --- a/drivers/amlogic/media/vout/backlight/aml_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_bl.c @@ -37,6 +37,7 @@ #ifdef CONFIG_AMLOGIC_LCD #include #include +#include #endif #ifdef CONFIG_AMLOGIC_BL_EXTERN #include @@ -68,8 +69,6 @@ MODULE_PARM_DESC(bl_level, "bl_level"); static unsigned int bl_level_uboot; static unsigned int brightness_bypass; -module_param(brightness_bypass, uint, 0664); -MODULE_PARM_DESC(brightness_bypass, "bl_brightness_bypass"); static unsigned char bl_pwm_bypass; /* debug flag */ static unsigned char bl_pwm_duty_free; /* debug flag */ @@ -332,14 +331,6 @@ static void bl_gpio_set(int index, int value) } } -static inline unsigned int bl_do_div(unsigned long num, unsigned int den) -{ - unsigned long long ret = num; - - do_div(ret, den); - return (unsigned int)ret; -} - /* ****************************************************** */ #define BL_PINMUX_MAX 8 static char *bl_pinmux_str[BL_PINMUX_MAX] = { @@ -972,7 +963,7 @@ static unsigned int bl_level_mapping(unsigned int level) static void bl_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1040,7 +1031,7 @@ static void bl_set_level_pwm(struct bl_pwm_config_s *bl_pwm, unsigned int level) unsigned int max = bl_pwm->level_max; unsigned int pwm_max = bl_pwm->pwm_max; unsigned int pwm_min = bl_pwm->pwm_min; - unsigned long temp; + unsigned long long temp; if (bl_pwm_bypass) return; @@ -1131,7 +1122,6 @@ static void bl_set_level_ldim(unsigned int level) static void aml_bl_set_level(unsigned int level) { - unsigned int temp; struct bl_pwm_config_s *pwm0, *pwm1; if (aml_bl_check_driver()) @@ -1165,26 +1155,27 @@ static void aml_bl_set_level(unsigned int level) case BL_CTRL_PWM_COMBO: pwm0 = bl_drv->bconf->bl_pwm_combo0; pwm1 = bl_drv->bconf->bl_pwm_combo1; - if ((level >= pwm0->level_min) && - (level <= pwm0->level_max)) { - temp = (pwm0->level_min > pwm1->level_min) ? - pwm1->level_max : pwm1->level_min; - if (bl_debug_print_flag) { - BLPR("pwm0 region, level=%u, pwm1_level=%u\n", - level, temp); - } + + if (level >= pwm0->level_max) { + bl_set_level_pwm(pwm0, pwm0->level_max); + } else if ((level > pwm0->level_min) && + (level < pwm0->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm0 region, level=%u\n", level); bl_set_level_pwm(pwm0, level); - bl_set_level_pwm(pwm1, temp); - } else if ((level >= pwm1->level_min) && - (level <= pwm1->level_max)) { - temp = (pwm1->level_min > pwm0->level_min) ? - pwm0->level_max : pwm0->level_min; - if (bl_debug_print_flag) { - BLPR("pwm1 region, level=%u, pwm0_level=%u\n", - level, temp); - } - bl_set_level_pwm(pwm0, temp); + } else { + bl_set_level_pwm(pwm0, pwm0->level_min); + } + + if (level >= pwm1->level_max) { + bl_set_level_pwm(pwm1, pwm1->level_max); + } else if ((level > pwm1->level_min) && + (level < pwm1->level_max)) { + if (bl_debug_print_flag) + BLPR("pwm1 region, level=%u,\n", level); bl_set_level_pwm(pwm1, level); + } else { + bl_set_level_pwm(pwm1, pwm1->level_min); } break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING @@ -1213,40 +1204,46 @@ static unsigned int aml_bl_get_level(void) return bl_drv->level; } -static int aml_bl_update_status(struct backlight_device *bd) +static unsigned int aml_bl_update_brightness_level(unsigned int brightness) { - int brightness = bd->props.brightness; - - if (brightness_bypass) - return 0; + unsigned int bl_level = brightness; mutex_lock(&bl_level_mutex); - if (brightness < 0) - brightness = 0; - else if (brightness > 255) - brightness = 255; + if (bl_level > 255) { + BLPR("0-255 is the valid data\n"); + bl_level = 255; + } if (((bl_drv->state & BL_STATE_LCD_ON) == 0) || ((bl_drv->state & BL_STATE_BL_POWER_ON) == 0)) - brightness = 0; + bl_level = 0; - if (bl_debug_print_flag) { - BLPR("%s: %u, real brightness: %u, state: 0x%x\n", - __func__, bd->props.brightness, - brightness, bl_drv->state); - } - if (brightness == 0) { + if (bl_level == 0) { if (bl_drv->state & BL_STATE_BL_ON) bl_power_off(); } else { - aml_bl_set_level(brightness); + aml_bl_set_level(bl_level); if ((bl_drv->state & BL_STATE_BL_ON) == 0) bl_power_on(); } + + if (bl_debug_print_flag) { + BLPR("%s: %u, real brightness: %u, state: 0x%x\n", + __func__, brightness, bl_level, bl_drv->state); + } mutex_unlock(&bl_level_mutex); return 0; } +static int aml_bl_update_status(struct backlight_device *bd) +{ + if (brightness_bypass) + return 0; + + aml_bl_update_brightness_level(bd->props.brightness); + return 0; +} + static int aml_bl_get_brightness(struct backlight_device *bd) { return aml_bl_get_level(); @@ -1287,7 +1284,7 @@ enum bl_pwm_port_e bl_pwm_str_to_pwm(const char *str) void bl_pwm_config_init(struct bl_pwm_config_s *bl_pwm) { unsigned int cnt; - unsigned long temp; + unsigned long long temp; if (bl_debug_print_flag) { BLPR("%s pwm_port %d: freq = %u\n", @@ -1478,8 +1475,21 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, bl_level_uboot = BL_LEVEL_DEFAULT; bconf->level_default = BL_LEVEL_DEFAULT; } else { - bl_level_uboot = bl_para[0]; - bconf->level_default = bl_para[1]; + bl_level_uboot = bl_para[0] & BL_LEVEL_MASK; + bconf->level_default = bl_para[1] & BL_LEVEL_MASK; + + brightness_bypass = + ((bl_para[1] >> BL_POLICY_BRIGHTNESS_BYPASS_BIT) & + BL_POLICY_BRIGHTNESS_BYPASS_MASK); + if (brightness_bypass) + BLPR("0x%x: enable brightness_bypass\n", bl_para[1]); + bl_step_on_flag = + ((bl_para[1] >> BL_POLICY_POWER_ON_BIT) & + BL_POLICY_POWER_ON_MASK); + if (bl_step_on_flag) { + BLPR("0x%x: bl_step_on_flag: %d\n", + bl_para[1], bl_step_on_flag); + } } ret = of_property_read_u32_array(child, "bl_level_attr", @@ -1496,11 +1506,6 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, bconf->level_mid = bl_para[2]; bconf->level_mid_mapping = bl_para[3]; } - /* adjust brightness_bypass by level_default */ - if (bconf->level_default > bconf->level_max) { - brightness_bypass = 1; - BLPR("level_default > level_max, enable brightness_bypass\n"); - } ret = of_property_read_u32(child, "bl_ctrl_method", &val); if (ret) { @@ -1530,7 +1535,8 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, bconf->power_on_delay = bl_para[3]; bconf->power_off_delay = bl_para[4]; } - ret = of_property_read_u32(child, "bl_ldim_mode", &bl_para[0]); + ret = of_property_read_u32(child, "bl_ldim_region_row_col", + &bl_para[0]); if (ret == 0) bconf->ldim_flag = 1; @@ -1598,10 +1604,11 @@ static int aml_bl_config_load_from_dts(struct bl_config_s *bconf, ret = of_property_read_u32(child, "bl_pwm_en_sequence_reverse", &val); if (ret) { - BLPR("don't find bl_pwm_en_sequence_reverse\n"); bconf->en_sequence_reverse = 0; - } else + } else { bconf->en_sequence_reverse = val; + BLPR("find bl_pwm_en_sequence_reverse: %d\n", val); + } bl_pwm->pwm_duty = bl_pwm->pwm_duty_min; /* init pwm config */ @@ -1781,6 +1788,7 @@ static int aml_bl_config_load_from_unifykey(struct bl_config_s *bconf) struct aml_lcd_unifykey_header_s bl_header; struct bl_pwm_config_s *bl_pwm; struct bl_pwm_config_s *pwm_combo0, *pwm_combo1; + unsigned int level; int ret; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_BL_SIZE), GFP_KERNEL); @@ -1841,8 +1849,8 @@ static int aml_bl_config_load_from_unifykey(struct bl_config_s *bconf) /* level: 6byte */ bl_level_uboot = (*(p + LCD_UKEY_BL_LEVEL_UBOOT) | ((*(p + LCD_UKEY_BL_LEVEL_UBOOT + 1)) << 8)); - bconf->level_default = (*(p + LCD_UKEY_BL_LEVEL_KERNEL) | - ((*(p + LCD_UKEY_BL_LEVEL_KERNEL + 1)) << 8)); + level = (*(p + LCD_UKEY_BL_LEVEL_KERNEL) | + ((*(p + LCD_UKEY_BL_LEVEL_KERNEL + 1)) << 8)); bconf->level_max = (*(p + LCD_UKEY_BL_LEVEL_MAX) | ((*(p + LCD_UKEY_BL_LEVEL_MAX + 1)) << 8)); bconf->level_min = (*(p + LCD_UKEY_BL_LEVEL_MIN) | @@ -1852,11 +1860,17 @@ static int aml_bl_config_load_from_unifykey(struct bl_config_s *bconf) bconf->level_mid_mapping = (*(p + LCD_UKEY_BL_LEVEL_MID_MAP) | ((*(p + LCD_UKEY_BL_LEVEL_MID_MAP + 1)) << 8)); - /* adjust brightness_bypass by level_default */ - if (bconf->level_default > bconf->level_max) { - brightness_bypass = 1; - BLPR("level_default > level_max, enable brightness_bypass\n"); - } + bconf->level_default = level & BL_LEVEL_MASK; + brightness_bypass = + ((level >> BL_POLICY_BRIGHTNESS_BYPASS_BIT) & + BL_POLICY_BRIGHTNESS_BYPASS_MASK); + if (brightness_bypass) + BLPR("0x%x: enable brightness_bypass\n", level); + bl_step_on_flag = + ((level >> BL_POLICY_POWER_ON_BIT) & + BL_POLICY_POWER_ON_MASK); + if (bl_step_on_flag) + BLPR("0x%x: bl_step_on_flag: %d\n", level, bl_step_on_flag); /* method: 8byte */ temp = *(p + LCD_UKEY_BL_METHOD); @@ -2042,6 +2056,9 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, struct device_node *child; struct bl_pwm_config_s *bl_pwm = NULL; + if (bl_debug_print_flag) + BLPR("%s\n", __func__); + ret = of_property_read_u32(blnode, "bl_pwm_config", &pwm_phandle); if (ret) { BLERR("not match bl_pwm_config node\n"); @@ -2105,8 +2122,6 @@ static int aml_bl_pwm_channel_register(struct bl_config_s *bconf, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - BLPR("%s ok\n", __func__); - return ret; } @@ -2200,17 +2215,24 @@ static void aml_bl_on_function(void) bl_drv->state |= (BL_STATE_LCD_ON | BL_STATE_BL_POWER_ON); BLPR("%s: bl_level=%u, state=0x%x\n", __func__, bl_drv->level, bl_drv->state); - if (brightness_bypass) { - if ((bl_drv->state & BL_STATE_BL_ON) == 0) - bl_power_on(); - } else { - if (bl_step_on_flag) { - aml_bl_step_on(bl_drv->bconf->level_default); - BLPR("bl_on level: %d\n", - bl_drv->bldev->props.brightness); - } - aml_bl_update_status(bl_drv->bldev); + if (brightness_bypass) + bl_drv->bldev->props.brightness = bl_drv->level; + + switch (bl_step_on_flag) { + case 1: + aml_bl_step_on(bl_drv->bconf->level_default); + BLPR("bl_on level: %d\n", + bl_drv->bldev->props.brightness); + break; + case 2: + bl_drv->bldev->props.brightness = bl_level_uboot; + BLPR("bl_on level: %d\n", + bl_drv->bldev->props.brightness); + break; + default: + break; } + aml_bl_update_brightness_level(bl_drv->bldev->props.brightness); } static void aml_bl_delayd_on(struct work_struct *work) @@ -2273,7 +2295,7 @@ static int aml_bl_off_notifier(struct notifier_block *nb, if (bl_drv->state & BL_STATE_BL_ON) bl_power_off(); } else - aml_bl_update_status(bl_drv->bldev); + aml_bl_update_brightness_level(bl_drv->bldev->props.brightness); return NOTIFY_OK; } @@ -2288,12 +2310,35 @@ static struct notifier_block aml_bl_off_nb = { .priority = LCD_PRIORITY_POWER_BL_OFF, }; +static inline int aml_bl_pwm_vs_lcd_update(struct bl_pwm_config_s *bl_pwm) +{ + unsigned int cnt; + + if (bl_pwm == NULL) { + BLERR("%s: bl_pwm is null\n", __func__); + return 0; + } + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt == bl_pwm->pwm_cnt) + return 0; + + bl_pwm_config_init(bl_pwm); + if (brightness_bypass) + bl_set_duty_pwm(bl_pwm); + else + aml_bl_update_brightness_level(bl_drv->bldev->props.brightness); + + return 0; +} + static int aml_bl_lcd_update_notifier(struct notifier_block *nb, unsigned long event, void *data) { struct bl_pwm_config_s *bl_pwm = NULL; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + unsigned int *frame_rate; #endif /* If we aren't interested in this event, skip it immediately */ @@ -2308,13 +2353,8 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, case BL_CTRL_PWM: if (bl_drv->bconf->bl_pwm->pwm_port == BL_PWM_VS) { bl_pwm = bl_drv->bconf->bl_pwm; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); } break; case BL_CTRL_PWM_COMBO: @@ -2322,16 +2362,16 @@ static int aml_bl_lcd_update_notifier(struct notifier_block *nb, bl_pwm = bl_drv->bconf->bl_pwm_combo0; else if (bl_drv->bconf->bl_pwm_combo1->pwm_port == BL_PWM_VS) bl_pwm = bl_drv->bconf->bl_pwm_combo1; - if (bl_pwm) { - bl_pwm_config_init(bl_pwm); - if (brightness_bypass) - bl_set_duty_pwm(bl_pwm); - else - aml_bl_update_status(bl_drv->bldev); - } + if (bl_pwm) + aml_bl_pwm_vs_lcd_update(bl_pwm); break; #ifdef CONFIG_AMLOGIC_LOCAL_DIMMING case BL_CTRL_LOCAL_DIMMING: + if (data) { + frame_rate = (unsigned int *)data; + ldim_drv->vsync_change_flag = + (unsigned char)(*frame_rate); + } if (ldim_drv->pwm_vs_update) ldim_drv->pwm_vs_update(); break; @@ -2529,7 +2569,7 @@ static ssize_t bl_status_read(struct class *class, return len; } -static ssize_t bl_debug_pwm_show(struct class *class, +static ssize_t bl_debug_pwm_info_show(struct class *class, struct class_attribute *attr, char *buf) { struct bl_config_s *bconf = bl_drv->bconf; @@ -2538,7 +2578,7 @@ static ssize_t bl_debug_pwm_show(struct class *class, unsigned int value; ssize_t len = 0; - len = sprintf(buf, "read backlight pwm state:\n"); + len = sprintf(buf, "read backlight pwm info:\n"); switch (bconf->method) { case BL_CTRL_PWM: len += sprintf(buf+len, @@ -2773,16 +2813,86 @@ static ssize_t bl_debug_pwm_show(struct class *class, return len; } -#define BL_DEBUG_PWM_FREQ 0 -#define BL_DEBUG_PWM_DUTY 1 -#define BL_DEBUG_PWM_POL 2 -#define BL_DEBUG_PWM_DUTY_MAX 3 -#define BL_DEBUG_PWM_DUTY_MIN 4 +static ssize_t bl_debug_pwm_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_config_s *bconf = bl_drv->bconf; + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + switch (bconf->method) { + case BL_CTRL_PWM: + if (bconf->bl_pwm) { + bl_pwm = bconf->bl_pwm; + len += sprintf(buf+len, + "pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + case BL_CTRL_PWM_COMBO: + if (bconf->bl_pwm_combo0) { + bl_pwm = bconf->bl_pwm_combo0; + len += sprintf(buf+len, + "pwm_0: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + + if (bconf->bl_pwm_combo1) { + bl_pwm = bconf->bl_pwm_combo1; + len += sprintf(buf+len, + "pwm_1: freq=%d, pol=%d, duty_max=%d, duty_min=%d, ", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + if (bl_pwm->pwm_duty_max > 100) { + len += sprintf(buf+len, + "duty_value=%d(%d%%)\n", + bl_pwm->pwm_duty, + bl_pwm->pwm_duty*100/255); + } else { + len += sprintf(buf+len, + "duty_value=%d%%\n", + bl_pwm->pwm_duty); + } + } + break; + default: + break; + } + return len; +} + +#define BL_DEBUG_PWM_FREQ 0 +#define BL_DEBUG_PWM_DUTY 1 +#define BL_DEBUG_PWM_POL 2 +#define BL_DEBUG_PWM_DUTY_MAX 3 +#define BL_DEBUG_PWM_DUTY_MIN 4 static void bl_debug_pwm_set(unsigned int index, unsigned int value, int state) { struct bl_config_s *bconf = bl_drv->bconf; struct bl_pwm_config_s *bl_pwm = NULL; - unsigned long temp; + unsigned long long temp; unsigned int pwm_range, temp_duty; if (aml_bl_check_driver()) @@ -3107,9 +3217,58 @@ static ssize_t bl_debug_print_store(struct class *class, return count; } +static ssize_t bl_debug_brightness_bypass_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", brightness_bypass); +} + +static ssize_t bl_debug_brightness_bypass_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + + ret = kstrtouint(buf, 10, &brightness_bypass); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + return count; +} + +static ssize_t bl_debug_brightness_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", bl_drv->level); +} + +static ssize_t bl_debug_brightness_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int brightness_level = 0; + + ret = kstrtouint(buf, 10, &brightness_level); + if (ret != 0) { + BLERR("invalid data\n"); + return -EINVAL; + } + + if (!brightness_bypass) + brightness_bypass = 1; + + ret = aml_bl_update_brightness_level(brightness_level); + if (ret == 0) + BLPR("brightness %d update ok\n", brightness_level); + else + BLERR("update fail\n"); + return count; +} + static struct class_attribute bl_debug_class_attrs[] = { __ATTR(help, 0444, bl_debug_help, NULL), __ATTR(status, 0444, bl_status_read, NULL), + __ATTR(pwm_info, 0644, bl_debug_pwm_info_show, NULL), __ATTR(pwm, 0644, bl_debug_pwm_show, bl_debug_pwm_store), __ATTR(power, 0644, bl_debug_power_show, bl_debug_power_store), __ATTR(step_on, 0644, bl_debug_step_on_show, bl_debug_step_on_store), @@ -3117,6 +3276,10 @@ static struct class_attribute bl_debug_class_attrs[] = { __ATTR(key_valid, 0444, bl_debug_key_valid_show, NULL), __ATTR(config_load, 0444, bl_debug_config_load_show, NULL), __ATTR(print, 0644, bl_debug_print_show, bl_debug_print_store), + __ATTR(brightness_bypass, 0644, bl_debug_brightness_bypass_show, + bl_debug_brightness_bypass_store), + __ATTR(brightness_level, 0644, bl_debug_brightness_show, + bl_debug_brightness_store), }; static int aml_bl_creat_class(void) @@ -3237,6 +3400,12 @@ static struct bl_data_s bl_data_sm1 = { .pwm_reg = pwm_reg_txlx, }; +static struct bl_data_s bl_data_tm2 = { + .chip_type = BL_CHIP_TM2, + .chip_name = "tm2", + .pwm_reg = pwm_reg_txlx, +}; + static const struct of_device_id bl_dt_match_table[] = { { .compatible = "amlogic, backlight-gxl", @@ -3274,14 +3443,25 @@ static const struct of_device_id bl_dt_match_table[] = { .compatible = "amlogic, backlight-sm1", .data = &bl_data_sm1, }, + { + .compatible = "amlogic, backlight-tm2", + .data = &bl_data_tm2, + }, {}, }; #endif static void aml_bl_init_status_update(void) { + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lcd_config_s *pconf; unsigned int state; + pconf = lcd_drv->lcd_config; + + if (pconf->lcd_boot_ctrl->lcd_init_level) + return; + state = bl_vcbus_read(ENCL_VIDEO_EN); if (state == 0) /* default disable lcd & backlight */ return; @@ -3294,7 +3474,7 @@ static void aml_bl_init_status_update(void) if (brightness_bypass) aml_bl_set_level(bl_on_level); else - aml_bl_update_status(bl_drv->bldev); + aml_bl_update_brightness_level(bl_drv->bldev->props.brightness); switch (bl_drv->bconf->method) { case BL_CTRL_PWM: @@ -3322,10 +3502,8 @@ static int aml_bl_probe(struct platform_device *pdev) aml_bl_off_policy_cnt = 0; /* init backlight parameters */ - brightness_bypass = 0; bl_pwm_bypass = 0; bl_pwm_duty_free = 0; - bl_step_on_flag = 0; bl_drv = kzalloc(sizeof(struct aml_bl_drv_s), GFP_KERNEL); if (!bl_drv) { @@ -3394,7 +3572,7 @@ static int aml_bl_probe(struct platform_device *pdev) err: kfree(bl_drv); bl_drv = NULL; - return ret; + return 0; } static int __exit aml_bl_remove(struct platform_device *pdev) @@ -3402,6 +3580,9 @@ static int __exit aml_bl_remove(struct platform_device *pdev) int ret; /*struct aml_bl *bl_drv = platform_get_drvdata(pdev);*/ + if (bl_drv == NULL) + return 0; + aml_bl_remove_class(); ret = cancel_delayed_work_sync(&bl_drv->bl_delayed_work); diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile index bc2132eb8332..1d695bb17d3a 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/Makefile @@ -3,6 +3,6 @@ # obj-$(CONFIG_AMLOGIC_LOCAL_DIMMING) = aml_ldim.o ldim_dev_drv.o ldim_spi.o \ ob3350_bl.o global_bl.o iw7027_bl.o -aml_ldim-objs := ldim_drv.o ldim_func.o +aml_ldim-objs := ldim_drv.o ldim_func.o ldim_hw.o diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c index d2dcd99745b5..1a1856c3017c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c @@ -44,7 +44,8 @@ static int global_hw_init_on(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(2); ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, @@ -61,7 +62,8 @@ static int global_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -88,12 +90,22 @@ static int global_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void global_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int global_power_on(void) { if (global_on_flag) { @@ -137,7 +149,7 @@ static ssize_t global_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -150,6 +162,12 @@ static struct class_attribute global_class_attrs[] = { static int global_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = global_dim_range_update; + ldim_drv->device_power_on = global_power_on; ldim_drv->device_power_off = global_power_off; ldim_drv->device_bri_update = global_smr; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c index 187b7233316c..42d64737f65e 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c @@ -46,9 +46,11 @@ #define IW7027_REG_CHIPID 0x7f #define IW7027_CHIPID 0x28 -#define IW7027_POWER_ON 0 -#define IW7027_POWER_RESET 1 +#define VSYNC_INFO_FREQUENT 30 + static int iw7027_on_flag; +static unsigned short vsync_cnt; +static unsigned short fault_cnt; static DEFINE_MUTEX(iw7027_spi_mutex); @@ -114,6 +116,37 @@ static int iw7027_wregs(struct spi_device *spi, unsigned char addr, return ret; } +static int iw7027_reg_write(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 28) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + if (len > 1) + ret = iw7027_wreg(bl_iw7027->spi, buf[0], buf[1]); + else + ret = iw7027_wregs(bl_iw7027->spi, buf[0], &buf[1], (len - 1)); + + return ret; +} + +static int iw7027_reg_read(unsigned char *buf, unsigned int len) +{ + int ret; + + if (len > 1) { + LDIMERR("%s: unsupport len: %d\n", __func__, len); + return -1; + } + + ret = iw7027_rreg(bl_iw7027->spi, buf[0], &buf[0]); + + return ret; +} + static int ldim_power_cmd_dynamic_size(void) { unsigned char *table; @@ -247,8 +280,6 @@ static int iw7027_hw_init_on(void) unsigned char reg_chk, reg_duty_chk; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - /* step 1: system power_on */ ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_on); @@ -273,7 +304,8 @@ static int iw7027_hw_init_on(void) iw7027_power_on_init(); /* step 5: supply stable vsync */ - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); /* step 6: delay for system clock and light bar PSU stable */ @@ -295,8 +327,6 @@ static int iw7027_hw_init_on(void) } LDIMPR("%s: calibration done: [%d] = %x\n", __func__, i, reg_duty_chk); - mutex_unlock(&iw7027_spi_mutex); - return 0; } @@ -304,14 +334,11 @@ static int iw7027_hw_init_off(void) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - mutex_lock(&iw7027_spi_mutex); - ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); - - mutex_unlock(&iw7027_spi_mutex); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -387,6 +414,48 @@ static int iw7027_spi_dump_dim(char *buf) return len; } +static int fault_cnt_save; +static int fault_check_cnt; +static int iw7027_fault_handler(unsigned int gpio) +{ + unsigned int val; + + if (gpio >= BL_GPIO_NUM_MAX) + return 0; + + if (fault_check_cnt++ > 200) { /* clear fault flag for a cycle */ + fault_check_cnt = 0; + fault_cnt = 0; + fault_cnt_save = 0; + } + + if (ldim_debug_print) { + if (vsync_cnt == 0) { + LDIMPR("%s: fault_cnt: %d, fault_check_cnt: %d\n", + __func__, fault_cnt, fault_check_cnt); + } + } + + val = ldim_gpio_get(gpio); + if (val == 0) + return 0; + + fault_cnt++; + if (fault_cnt_save != fault_cnt) { + fault_cnt_save = fault_cnt; + LDIMPR("%s: fault_cnt: %d\n", __func__, fault_cnt); + } + if (fault_cnt <= 10) { + iw7027_wreg(bl_iw7027->spi, 0x61, 0x0f); + } else { + iw7027_hw_init_on(); + fault_cnt = 0; + fault_cnt_save = 0; + } + + return -1; +} + static unsigned int dim_max, dim_min; static inline unsigned int iw7027_get_value(unsigned int level) { @@ -397,7 +466,6 @@ static inline unsigned int iw7027_get_value(unsigned int level) return val; } -static int smr_cnt; static int iw7027_smr(unsigned short *buf, unsigned char len) { int i; @@ -405,22 +473,22 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) unsigned short *mapping, num; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (smr_cnt++ >= 30) - smr_cnt = 0; + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; if (iw7027_on_flag == 0) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); return 0; } num = ldim_drv->ldev_conf->bl_regnum; if (len != num) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: data len %d invalid\n", __func__, len); return -1; } if (val_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("%s: val_brightness is null\n", __func__); return -1; } @@ -431,9 +499,18 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) dim_max = ldim_drv->ldev_conf->dim_max; dim_min = ldim_drv->ldev_conf->dim_min; +#if 0 /* this function will cause backlight flicker */ + if (ldim_drv->vsync_change_flag == 50) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd7); + ldim_drv->vsync_change_flag = 0; + } else if (ldim_drv->vsync_change_flag == 60) { + iw7027_wreg(bl_iw7027->spi, 0x31, 0xd3); + ldim_drv->vsync_change_flag = 0; + } +#endif if (bl_iw7027->test_mode) { if (test_brightness == NULL) { - if (smr_cnt == 0) + if (vsync_cnt == 0) LDIMERR("test_brightness is null\n"); return 0; } @@ -458,18 +535,51 @@ static int iw7027_smr(unsigned short *buf, unsigned char len) iw7027_wregs(bl_iw7027->spi, 0x40, val_brightness, (num * 2)); + if (ldim_drv->ldev_conf->fault_check) + iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + mutex_unlock(&iw7027_spi_mutex); + return 0; } +static int iw7027_check(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + int ret = 0; + + if (vsync_cnt++ >= VSYNC_INFO_FREQUENT) + vsync_cnt = 0; + + if (iw7027_on_flag == 0) { + if (vsync_cnt == 0) + LDIMPR("%s: on_flag=%d\n", __func__, iw7027_on_flag); + return 0; + } + + mutex_lock(&iw7027_spi_mutex); + + if (ldim_drv->ldev_conf->fault_check) + ret = iw7027_fault_handler(ldim_drv->ldev_conf->lamp_err_gpio); + + mutex_unlock(&iw7027_spi_mutex); + + return ret; +} + static int iw7027_power_on(void) { if (iw7027_on_flag) { LDIMPR("%s: iw7027 is already on, exit\n", __func__); return 0; } + + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); iw7027_on_flag = 1; + vsync_cnt = 0; + fault_cnt = 0; + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -477,8 +587,10 @@ static int iw7027_power_on(void) static int iw7027_power_off(void) { + mutex_lock(&iw7027_spi_mutex); iw7027_on_flag = 0; iw7027_hw_init_off(); + mutex_unlock(&iw7027_spi_mutex); LDIMPR("%s: ok\n", __func__); return 0; @@ -492,11 +604,7 @@ static ssize_t iw7027_show(struct class *class, int ret = 0; int i; - if (!strcmp(attr->attr.name, "mode")) { - ret = sprintf(buf, "0x%02x\n", bl->spi->mode); - } else if (!strcmp(attr->attr.name, "speed")) { - ret = sprintf(buf, "%d\n", bl->spi->max_speed_hz); - } else if (!strcmp(attr->attr.name, "test")) { + if (!strcmp(attr->attr.name, "test")) { ret = sprintf(buf, "test mode=%d\n", bl->test_mode); } else if (!strcmp(attr->attr.name, "brightness")) { if (test_brightness == NULL) { @@ -511,13 +619,15 @@ static ssize_t iw7027_show(struct class *class, ret = sprintf(buf, "iw7027 status:\n" "dev_index = %d\n" "on_flag = %d\n" + "fault_cnt = %d\n" "en_on = %d\n" "en_off = %d\n" "cs_hold_delay = %d\n" "cs_clk_delay = %d\n" "dim_max = 0x%03x\n" "dim_min = 0x%03x\n", - ldim_drv->dev_index, iw7027_on_flag, + ldim_drv->dev_index, + iw7027_on_flag, fault_cnt, ldim_drv->ldev_conf->en_gpio_on, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->cs_hold_delay, @@ -542,23 +652,13 @@ static ssize_t iw7027_store(struct class *class, struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct iw7027_s *bl = container_of(class, struct iw7027_s, cls); unsigned int val, val2; - unsigned char reg_addr, reg_val; + unsigned char reg_addr, reg_val, temp; int i; if (!strcmp(attr->attr.name, "init")) { + mutex_lock(&iw7027_spi_mutex); iw7027_hw_init_on(); - } else if (!strcmp(attr->attr.name, "mode")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->mode = val; - else - LDIMERR("%s: invalid args\n", __func__); - } else if (!strcmp(attr->attr.name, "speed")) { - i = kstrtouint(buf, 10, &val); - if (i == 1) - bl->spi->max_speed_hz = val*1000; - else - LDIMERR("%s: invalid args\n", __func__); + mutex_unlock(&iw7027_spi_mutex); } else if (!strcmp(attr->attr.name, "reg")) { if (buf[0] == 'w') { i = sscanf(buf, "w %x %x", &val, &val2); @@ -567,6 +667,10 @@ static ssize_t iw7027_store(struct class *class, reg_addr = (unsigned char)val; reg_val = (unsigned char)val2; iw7027_wreg(bl->spi, reg_addr, reg_val); + iw7027_rreg(bl->spi, reg_addr, &temp); + pr_info( + "reg 0x%02x = 0x%02x, readback 0x%02x\n", + reg_addr, reg_val, temp); mutex_unlock(&iw7027_spi_mutex); } else { LDIMERR("%s: invalid args\n", __func__); @@ -605,9 +709,7 @@ static ssize_t iw7027_store(struct class *class, } static struct class_attribute iw7027_class_attrs[] = { - __ATTR(init, 0644, iw7027_show, iw7027_store), - __ATTR(mode, 0644, iw7027_show, iw7027_store), - __ATTR(speed, 0644, iw7027_show, iw7027_store), + __ATTR(init, 0644, NULL, iw7027_store), __ATTR(reg, 0644, iw7027_show, iw7027_store), __ATTR(test, 0644, iw7027_show, iw7027_store), __ATTR(brightness, 0644, iw7027_show, iw7027_store), @@ -623,6 +725,10 @@ static int iw7027_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) ldim_drv->device_power_on = iw7027_power_on; ldim_drv->device_power_off = iw7027_power_off; ldim_drv->device_bri_update = iw7027_smr; + ldim_drv->device_bri_check = iw7027_check; + + ldim_drv->ldev_conf->dev_reg_write = iw7027_reg_write; + ldim_drv->ldev_conf->dev_reg_read = iw7027_reg_read; return 0; } @@ -636,6 +742,8 @@ int ldim_dev_iw7027_probe(struct aml_ldim_driver_s *ldim_drv) } iw7027_on_flag = 0; + vsync_cnt = 0; + fault_cnt = 0; bl_iw7027 = kzalloc(sizeof(struct iw7027_s), GFP_KERNEL); if (bl_iw7027 == NULL) { diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c index b2c02250cf71..f7800d9f1342 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c @@ -58,6 +58,7 @@ static struct spi_board_info ldim_spi_info = { static unsigned char *table_init_on_dft; static unsigned char *table_init_off_dft; static int ldim_dev_probe_flag; +static struct class ldim_dev_class; struct ldim_dev_config_s ldim_dev_config = { .type = LDIM_DEV_TYPE_NORMAL, @@ -77,14 +78,25 @@ struct ldim_dev_config_s ldim_dev_config = { .init_off = NULL, .init_on_cnt = 0, .init_off_cnt = 0, - .pwm_config = { + .ldim_pwm_config = { .pwm_method = BL_PWM_POSITIVE, .pwm_port = BL_PWM_MAX, .pwm_duty_max = 100, - .pwm_duty_min = 1, + .pwm_duty_min = 0, + }, + .analog_pwm_config = { + .pwm_method = BL_PWM_POSITIVE, + .pwm_port = BL_PWM_MAX, + .pwm_freq = 1000, + .pwm_duty_max = 100, + .pwm_duty_min = 10, }, .bl_regnum = 0, + + .dim_range_update = NULL, + .dev_reg_write = NULL, + .dev_reg_read = NULL, }; static void ldim_gpio_probe(int index) @@ -246,14 +258,13 @@ unsigned int ldim_gpio_get(int index) void ldim_set_duty_pwm(struct bl_pwm_config_s *bl_pwm) { - unsigned long temp; + unsigned long long temp; if (bl_pwm->pwm_port >= BL_PWM_MAX) return; temp = bl_pwm->pwm_cnt; - temp = (((temp * bl_pwm->pwm_duty) + 50) / 100); - bl_pwm->pwm_level = (unsigned int)temp; + bl_pwm->pwm_level = bl_do_div(((temp * bl_pwm->pwm_duty) + 50), 100); if (ldim_debug_print == 2) { LDIMPR( @@ -277,42 +288,53 @@ void ldim_pwm_off(struct bl_pwm_config_s *bl_pwm) static char *ldim_pinmux_str[] = { "ldim_pwm", /* 0 */ "ldim_pwm_vs", /* 1 */ - "ldim_pwm_off", /* 1 */ - "none", + "ldim_pwm_combo", /* 2 */ + "ldim_pwm_vs_combo", /* 3 */ + "ldim_pwm_off", /* 4 */ + "ldim_pwm_combo_off", /* 5 */ + "custome", }; static int ldim_pwm_pinmux_ctrl(int status) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); struct bl_pwm_config_s *bl_pwm; + char *str; int ret = 0, index = 0xff; - if (strcmp(ldim_drv->ldev_conf->pinmux_name, "invalid") == 0) + if (ldim_drv->ldev_conf->ldim_pwm_config.pwm_port >= BL_PWM_MAX) return 0; - bl_pwm = &ldim_drv->ldev_conf->pwm_config; - if (bl_pwm->pwm_port >= BL_PWM_MAX) - return 0; - - if (bl_pwm->pwm_port == BL_PWM_VS) - index = (status) ? 1 : 2; - else - index = (status) ? 0 : 2; + if (status) { + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; + if (bl_pwm->pwm_port == BL_PWM_VS) + index = 1; + else + index = 0; + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index += 2; + } else { + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) + index = 5; + else + index = 4; + } + str = ldim_pinmux_str[index]; if (ldim_drv->pinmux_flag == index) { - LDIMPR("pinmux %s is already selected\n", - ldim_pinmux_str[index]); + LDIMPR("pinmux %s is already selected\n", str); return 0; } /* request pwm pinmux */ - ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, - ldim_pinmux_str[index]); + ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, str); if (IS_ERR(ldim_drv->pin)) { - LDIMERR("set pinmux %s error\n", ldim_pinmux_str[index]); + LDIMERR("set pinmux %s error\n", str); + ret = -1; } else { - LDIMPR("set pinmux %s: 0x%p\n", - ldim_pinmux_str[index], ldim_drv->pin); + LDIMPR("set pinmux %s: 0x%p\n", str, ldim_drv->pin); } ldim_drv->pinmux_flag = index; @@ -321,12 +343,21 @@ static int ldim_pwm_pinmux_ctrl(int status) static int ldim_pwm_vs_update(void) { - struct bl_pwm_config_s *bl_pwm = NULL; + struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.ldim_pwm_config; + unsigned int cnt; int ret = 0; - bl_pwm = &ldim_dev_config.pwm_config; - bl_pwm_config_init(bl_pwm); - ldim_set_duty_pwm(bl_pwm); + if (bl_pwm->pwm_port != BL_PWM_VS) + return 0; + + if (ldim_debug_print) + LDIMPR("%s\n", __func__); + + cnt = bl_vcbus_read(ENCL_VIDEO_MAX_LNCNT) + 1; + if (cnt != bl_pwm->pwm_cnt) { + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + } return ret; } @@ -354,6 +385,10 @@ static void ldim_dev_init_table_dynamic_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -431,6 +466,10 @@ static void ldim_dev_init_table_fixed_size_print( table = econf->init_off; max_len = econf->init_off_cnt; } + if (max_len == 0) { + kfree(str); + return; + } if (table == NULL) { LDIMERR("init_table %d is NULL\n", flag); kfree(str); @@ -466,15 +505,16 @@ static void ldim_dev_config_print(void) LDIMPR("%s:\n", __func__); pr_info("valid_flag = %d\n" - "dev_index = %d\n", + "dev_index = %d\n" + "vsync_change_flag = %d\n\n", ldim_drv->valid_flag, - ldim_drv->dev_index); + ldim_drv->dev_index, + ldim_drv->vsync_change_flag); if (ldim_drv->ldev_conf == NULL) { LDIMERR("%s: device config is null\n", __func__); return; } - bl_pwm = &ldim_drv->ldev_conf->pwm_config; pr_info("dev_name = %s\n" "type = %d\n" "en_gpio = %d\n" @@ -537,13 +577,14 @@ static void ldim_dev_config_print(void) default: break; } + bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config; if (bl_pwm->pwm_port < BL_PWM_MAX) { - pr_info("pwm_port: %d\n" - "pwm_pol: %d\n" - "pwm_freq: %d\n" - "pwm_cnt: %d\n" - "pwm_level: %d\n" - "pwm_duty: %d%%\n", + pr_info("lidm_pwm_port: %d\n" + "lidm_pwm_pol: %d\n" + "lidm_pwm_freq: %d\n" + "lidm_pwm_cnt: %d\n" + "lidm_pwm_level: %d\n" + "lidm_pwm_duty: %d%%\n", bl_pwm->pwm_port, bl_pwm->pwm_method, bl_pwm->pwm_freq, bl_pwm->pwm_cnt, bl_pwm->pwm_level, bl_pwm->pwm_duty); @@ -555,28 +596,28 @@ static void ldim_dev_config_print(void) case BL_PWM_E: case BL_PWM_F: if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { - pr_info("pwm invalid\n"); + pr_info("lidm_pwm invalid\n"); break; } - pr_info("pwm_pointer: %p\n", + pr_info("lidm_pwm_pointer: 0x%p\n", bl_pwm->pwm_data.pwm); pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); - pr_info("pwm state:\n" - " period: %d\n" - " duty_cycle: %d\n" - " polarity: %d\n" - " enabled: %d\n", + pr_info("lidm_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", pstate.period, pstate.duty_cycle, pstate.polarity, pstate.enabled); value = bl_cbus_read( bl_drv->data->pwm_reg[bl_pwm->pwm_port]); - pr_info("pwm_reg: 0x%08x\n", value); + pr_info("lidm_pwm_reg: 0x%08x\n", value); break; case BL_PWM_VS: - pr_info("pwm_reg0: 0x%08x\n" - "pwm_reg1: 0x%08x\n" - "pwm_reg2: 0x%08x\n" - "pwm_reg3: 0x%08x\n", + pr_info("lidm_pwm_reg0: 0x%08x\n" + "lidm_pwm_reg1: 0x%08x\n" + "lidm_pwm_reg2: 0x%08x\n" + "lidm_pwm_reg3: 0x%08x\n", bl_vcbus_read(VPU_VPU_PWM_V0), bl_vcbus_read(VPU_VPU_PWM_V1), bl_vcbus_read(VPU_VPU_PWM_V2), @@ -586,16 +627,59 @@ static void ldim_dev_config_print(void) break; } } - pr_info("pinmux_flag: %d\n" - "pinmux_pointer: 0x%p\n\n", + bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + pr_info("\nanalog_pwm_port: %d\n" + "analog_pwm_pol: %d\n" + "analog_pwm_freq: %d\n" + "analog_pwm_cnt: %d\n" + "analog_pwm_level: %d\n" + "analog_pwm_duty: %d%%\n" + "analog_pwm_duty_max: %d%%\n" + "analog_pwm_duty_min: %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_method, + bl_pwm->pwm_freq, bl_pwm->pwm_cnt, + bl_pwm->pwm_level, bl_pwm->pwm_duty, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + switch (bl_pwm->pwm_port) { + case BL_PWM_A: + case BL_PWM_B: + case BL_PWM_C: + case BL_PWM_D: + case BL_PWM_E: + case BL_PWM_F: + if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) { + pr_info("analog_pwm invalid\n"); + break; + } + pr_info("analog_pwm_pointer: 0x%p\n", + bl_pwm->pwm_data.pwm); + pwm_get_state(bl_pwm->pwm_data.pwm, &pstate); + pr_info("analog_pwm state:\n" + " period: %d\n" + " duty_cycle: %d\n" + " polarity: %d\n" + " enabled: %d\n", + pstate.period, pstate.duty_cycle, + pstate.polarity, pstate.enabled); + value = bl_cbus_read( + bl_drv->data->pwm_reg[bl_pwm->pwm_port]); + pr_info("analog_pwm_reg: 0x%08x\n", value); + break; + default: + break; + } + } + pr_info("\npinmux_flag: %d\n" + "pinmux_pointer: 0x%p\n\n", ldim_drv->pinmux_flag, ldim_drv->pin); if (ldim_drv->ldev_conf->cmd_size > 0) { - pr_info("table_loaded: %d\n" - "cmd_size: %d\n" - "init_on_cnt: %d\n" - "init_off_cnt: %d\n", + pr_info("table_loaded: %d\n" + "cmd_size: %d\n" + "init_on_cnt: %d\n" + "init_off_cnt: %d\n", ldim_drv->ldev_conf->init_loaded, ldim_drv->ldev_conf->cmd_size, ldim_drv->ldev_conf->init_on_cnt, @@ -625,6 +709,9 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, struct device_node *child; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + if (ldim_debug_print) + LDIMPR("%s ok\n", __func__); + ret = of_property_read_u32(blnode, "ldim_pwm_config", &pwm_phandle); if (ret) { LDIMERR("not match ldim_pwm_config node\n"); @@ -672,8 +759,6 @@ static int ldim_dev_pwm_channel_register(struct bl_pwm_config_s *bl_pwm, bl_pwm->pwm_data.port_index, bl_pwm->pwm_data.pwm); } - LDIMPR("%s ok\n", __func__); - return ret; } @@ -880,6 +965,7 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) int i; int ret = 0; struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct bl_pwm_config_s *bl_pwm; temp = kcalloc(LD_BLKREGNUM, sizeof(unsigned int), GFP_KERNEL); if (temp == NULL) { @@ -901,52 +987,82 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index) LDIMERR("failed to get ldim_dev_name\n"); str = "ldim_dev"; } - strcpy(ldim_dev_config.name, str); + strncpy(ldim_dev_config.name, str, sizeof(ldim_dev_config.name)); + ldim_dev_config.name[sizeof(ldim_dev_config.name) - 1] = '\0'; ret = of_property_read_string(child, "ldim_pwm_pinmux_sel", &str); if (ret) { - LDIMERR("failed to get ldim_pwm_name\n"); strcpy(ldim_dev_config.pinmux_name, "invalid"); } else { + LDIMPR("find custome ldim_pwm_pinmux_sel: %s\n", str); strcpy(ldim_dev_config.pinmux_name, str); } + /* ldim pwm config */ + bl_pwm = &ldim_dev_config.ldim_pwm_config; ret = of_property_read_string(child, "ldim_pwm_port", &str); if (ret) { LDIMERR("failed to get ldim_pwm_port\n"); - ldim_dev_config.pwm_config.pwm_port = BL_PWM_MAX; } else { - ldim_dev_config.pwm_config.pwm_port = bl_pwm_str_to_pwm(str); + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + LDIMPR("ldim_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); } - LDIMPR("pwm_port: %s(%u)\n", str, ldim_dev_config.pwm_config.pwm_port); - - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_MAX) { + if (bl_pwm->pwm_port < BL_PWM_MAX) { ret = of_property_read_u32_array(child, "ldim_pwm_attr", temp, 3); if (ret) { LDIMERR("failed to get ldim_pwm_attr\n"); - ldim_dev_config.pwm_config.pwm_method = BL_PWM_POSITIVE; - if (ldim_dev_config.pwm_config.pwm_port == BL_PWM_VS) - ldim_dev_config.pwm_config.pwm_freq = 1; + bl_pwm->pwm_method = BL_PWM_POSITIVE; + if (bl_pwm->pwm_port == BL_PWM_VS) + bl_pwm->pwm_freq = 1; else - ldim_dev_config.pwm_config.pwm_freq = 60; - ldim_dev_config.pwm_config.pwm_duty = 50; + bl_pwm->pwm_freq = 60; + bl_pwm->pwm_duty = 50; } else { - ldim_dev_config.pwm_config.pwm_method = temp[0]; - ldim_dev_config.pwm_config.pwm_freq = temp[1]; - ldim_dev_config.pwm_config.pwm_duty = temp[2]; + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty = temp[2]; } - LDIMPR("get pwm pol = %d, freq = %d, duty = %d%%\n", - ldim_dev_config.pwm_config.pwm_method, - ldim_dev_config.pwm_config.pwm_freq, - ldim_dev_config.pwm_config.pwm_duty); + LDIMPR( + "get ldim_pwm pol = %d, freq = %d, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty); - bl_pwm_config_init(&ldim_dev_config.pwm_config); + bl_pwm_config_init(bl_pwm); - if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_VS) { - ldim_dev_pwm_channel_register( - &ldim_dev_config.pwm_config, np); + if (bl_pwm->pwm_port < BL_PWM_VS) + ldim_dev_pwm_channel_register(bl_pwm, np); + } + + /* analog pwm config */ + bl_pwm = &ldim_dev_config.analog_pwm_config; + ret = of_property_read_string(child, "analog_pwm_port", &str); + if (ret) + bl_pwm->pwm_port = BL_PWM_MAX; + else + bl_pwm->pwm_port = bl_pwm_str_to_pwm(str); + if (bl_pwm->pwm_port < BL_PWM_VS) { + LDIMPR("find analog_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port); + ret = of_property_read_u32_array(child, "analog_pwm_attr", + temp, 5); + if (ret) { + LDIMERR("failed to get analog_pwm_attr\n"); + } else { + bl_pwm->pwm_method = temp[0]; + bl_pwm->pwm_freq = temp[1]; + bl_pwm->pwm_duty_max = temp[2]; + bl_pwm->pwm_duty_min = temp[3]; + bl_pwm->pwm_duty = temp[4]; } + LDIMPR( +"get analog_pwm pol = %d, freq = %d, duty_max = %d%%, duty_min = %d%%, default duty = %d%%\n", + bl_pwm->pwm_method, bl_pwm->pwm_freq, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min, + bl_pwm->pwm_duty); + + bl_pwm_config_init(bl_pwm); + + ldim_dev_pwm_channel_register(bl_pwm, np); } ret = of_property_read_u32_array(child, "en_gpio_on_off", temp, 3); @@ -1148,11 +1264,389 @@ ldim_get_config_err: return -1; } +static ssize_t ldim_dev_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int ret = 0; + + ldim_dev_config_print(); + + return ret; +} + +static ssize_t ldim_dev_pwm_ldim_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_MAX) { + len += sprintf(buf+len, + "ldim_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_ldim_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.ldim_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_MAX) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + if (ldim_dev_config.dim_range_update) + ldim_dev_config.dim_range_update(); + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static ssize_t ldim_dev_pwm_analog_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct bl_pwm_config_s *bl_pwm; + ssize_t len = 0; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port < BL_PWM_VS) { + len += sprintf(buf+len, + "analog_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,", + bl_pwm->pwm_freq, bl_pwm->pwm_method, + bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min); + len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty); + } + + return len; +} + +static ssize_t ldim_dev_pwm_analog_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int ret; + unsigned int val = 0; + struct bl_pwm_config_s *bl_pwm; + + bl_pwm = &ldim_dev_config.analog_pwm_config; + if (bl_pwm->pwm_port >= BL_PWM_VS) + return count; + + switch (buf[0]) { + case 'f': /* frequency */ + ret = sscanf(buf, "freq %d", &val); + if (ret == 1) { + bl_pwm->pwm_freq = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): freq = %dHz\n", + bl_pwm->pwm_port, bl_pwm->pwm_freq); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'd': /* duty */ + ret = sscanf(buf, "duty %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty = val; + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): duty = %d%%\n", + bl_pwm->pwm_port, bl_pwm->pwm_duty); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'p': /* polarity */ + ret = sscanf(buf, "pol %d", &val); + if (ret == 1) { + bl_pwm->pwm_method = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR("set ldim_pwm (port %d): method = %d\n", + bl_pwm->pwm_port, bl_pwm->pwm_method); + } + } else { + LDIMERR("invalid parameters\n"); + } + break; + case 'm': + if (buf[1] == 'a') { /* max */ + ret = sscanf(buf, "max %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_max = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_max = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_max); + } + } else { + LDIMERR("invalid parameters\n"); + } + } else if (buf[1] == 'i') { /* min */ + ret = sscanf(buf, "min %d", &val); + if (ret == 1) { + bl_pwm->pwm_duty_min = val; + bl_pwm_config_init(bl_pwm); + ldim_set_duty_pwm(bl_pwm); + if (ldim_debug_print) { + LDIMPR( + "set ldim_pwm (port %d): duty_min = %d%%\n", + bl_pwm->pwm_port, + bl_pwm->pwm_duty_min); + } + } else { + LDIMERR("invalid parameters\n"); + } + } + break; + default: + LDIMERR("wrong command\n"); + break; + } + + return count; +} + +static unsigned char ldim_dev_reg; +static unsigned char ldim_dev_reg_dump_cnt; +static ssize_t ldim_dev_reg_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char data; + ssize_t len = 0; + int ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + data = ldim_dev_reg; + ret = ldim_dev_config.dev_reg_read(&data, 1); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len = sprintf(buf, "reg[0x%02x] = 0x%02x\n", + ldim_dev_reg, data); + } + + return len; +} + +static ssize_t ldim_dev_reg_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, val = 0; + unsigned char data[2]; + unsigned int ret; + + ret = sscanf(buf, "%x %x", ®, &val); + if (ret == 1) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + } else if (ret == 2) { + if (ldim_dev_config.dev_reg_write == NULL) { + LDIMERR("ldim dev_reg_write is null\n"); + return count; + } + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + ldim_dev_reg = (unsigned char)reg; + data[0] = ldim_dev_reg; + data[1] = (unsigned char)val; + ldim_dev_config.dev_reg_write(data, 2); + LDIMPR("write reg[0x%02x] = 0x%02x\n", data[0], data[1]); + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static ssize_t ldim_dev_reg_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned char *data; + ssize_t len = 0; + int i, ret; + + if (ldim_dev_config.dev_reg_read == NULL) + return sprintf(buf, "ldim dev_reg_read is null\n"); + + if (ldim_dev_reg_dump_cnt == 0) + return sprintf(buf, "ldim reg_dump_cnt is zero\n"); + + data = kcalloc(ldim_dev_reg_dump_cnt, + sizeof(unsigned char), GFP_KERNEL); + ret = ldim_dev_config.dev_reg_read(data, ldim_dev_reg_dump_cnt); + if (ret) { + len = sprintf(buf, "reg[0x%02x] read error\n", ldim_dev_reg); + } else { + len += sprintf(buf+len, "reg[0x%02x] = ", ldim_dev_reg); + for (i = 0; i < (ldim_dev_reg_dump_cnt - 1); i++) + len += sprintf(buf+len, "0x%02x,", data[i]); + len += sprintf(buf+len, "0x%02x\n", + data[ldim_dev_reg_dump_cnt - 1]); + } + kfree(data); + + return len; +} + +static ssize_t ldim_dev_reg_dump_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + unsigned int reg = 0, cnt = 0; + unsigned int ret; + + ret = sscanf(buf, "%x %d", ®, &cnt); + if (ret == 2) { + if (reg > 0xff) { + LDIMERR("invalid reg address: 0x%x\n", reg); + return count; + } + if (cnt > 0xff) { + LDIMERR("invalid reg cnt: %d\n", cnt); + return count; + } + ldim_dev_reg = (unsigned char)reg; + ldim_dev_reg_dump_cnt = (unsigned char)cnt; + } else { + LDIMERR("invalid parameters\n"); + } + + return count; +} + +static struct class_attribute ldim_dev_class_attrs[] = { + __ATTR(status, 0644, ldim_dev_show, NULL), + __ATTR(pwm_ldim, 0644, ldim_dev_pwm_ldim_show, ldim_dev_pwm_ldim_store), + __ATTR(pwm_analog, 0644, ldim_dev_pwm_analog_show, + ldim_dev_pwm_analog_store), + __ATTR(reg, 0644, ldim_dev_reg_show, ldim_dev_reg_store), + __ATTR(reg_dump, 0644, ldim_dev_reg_dump_show, ldim_dev_reg_dump_store), + __ATTR_NULL +}; + +static void ldim_dev_class_create(void) +{ + int ret; + + ldim_dev_class.name = kzalloc(10, GFP_KERNEL); + if (ldim_dev_class.name == NULL) { + LDIMERR("%s: malloc failed\n", __func__); + return; + } + sprintf((char *)ldim_dev_class.name, "ldim_dev"); + ldim_dev_class.class_attrs = ldim_dev_class_attrs; + ret = class_register(&ldim_dev_class); + if (ret < 0) + LDIMERR("register ldim_dev_class failed\n"); +} + static int ldim_dev_add_driver(struct aml_ldim_driver_s *ldim_drv) { struct ldim_dev_config_s *ldev_conf = ldim_drv->ldev_conf; int index = ldim_drv->dev_index; - int ret = -1; + int ret = 0; switch (ldim_dev_config.type) { case LDIM_DEV_TYPE_SPI: @@ -1243,12 +1737,14 @@ static int ldim_dev_probe(struct platform_device *pdev) ldim_dev_get_config_from_dts(pdev->dev.of_node, ldim_drv->dev_index); + ldim_dev_class_create(); ldim_dev_add_driver(ldim_drv); + + /* init ldim function */ + if (ldim_drv->valid_flag) + ldim_drv->init(); + LDIMPR("%s OK\n", __func__); } - /* init ldim function */ - if (ldim_drv->valid_flag) - ldim_drv->init(); - LDIMPR("%s OK\n", __func__); return 0; } @@ -1257,10 +1753,11 @@ static int __exit ldim_dev_remove(struct platform_device *pdev) { struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - if (ldim_drv->dev_index != 0xff) + if (ldim_drv->dev_index != 0xff) { ldim_dev_remove_driver(ldim_drv); + LDIMPR("%s OK\n", __func__); + } - LDIMPR("%s OK\n", __func__); return 0; } diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c index bb5e4e6cb46e..6cfe4d25df26 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.c @@ -309,258 +309,22 @@ static void ldim_db_load_update(struct LDReg_s *mLDReg, ldim_db_para_print(mLDReg); } -static void ldim_stts_initial_txlx(unsigned int resolution) -{ - Wr_reg(LDIM_STTS_CTRL0, 7 << 2); - ldim_set_matrix_ycbcr2rgb(); - ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); -} - static void ldim_stts_initial(unsigned int pic_h, unsigned int pic_v, unsigned int BLK_Vnum, unsigned int BLK_Hnum) { - unsigned int resolution, resolution_region, blk_height, blk_width; - unsigned int row_start, col_start; - - BLK_Vnum = (BLK_Vnum == 0) ? 1 : BLK_Vnum; - BLK_Hnum = (BLK_Hnum == 0) ? 1 : BLK_Hnum; LDIMPR("%s: %d %d %d %d\n", __func__, pic_h, pic_v, BLK_Vnum, BLK_Hnum); ldim_fw_para.hist_col = BLK_Vnum; ldim_fw_para.hist_row = BLK_Hnum; - resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); - /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ - if (ldim_dev.ldim_op_func == NULL) { LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->stts_init) - ldim_dev.ldim_op_func->stts_init(resolution); - - resolution_region = 0; - - blk_height = (pic_v - 8) / BLK_Vnum; - blk_width = (pic_h - 8) / BLK_Hnum; - row_start = (pic_v - (blk_height * BLK_Vnum)) >> 1; - col_start = (pic_h - (blk_width * BLK_Hnum)) >> 1; - ldim_set_region(0, blk_height, blk_width, - row_start, col_start, BLK_Hnum); -} - -static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) -{ - int data; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - if (data & (1 << 12)) { /*bl_ram_mode=1;*/ - if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) - /*Previous Matrix is not used*/ - goto Previous_Matrix; - else { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, - (BlMatrixNum & 0x1ff) | (1 << 16)); - /*set Matrix update ready*/ - - return 0; - } - } else { /*bl_ram_mode=0*/ - /*set ram_clk_sel=0, ram_bus_sel = 0*/ - data = data & (~(3 << 9)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - NewBlMatrix, BlMatrixNum); - data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - return 0; + if (ldim_dev.ldim_op_func->stts_init) { + ldim_dev.ldim_op_func->stts_init(pic_h, pic_v, + BLK_Vnum, BLK_Hnum); } - -Previous_Matrix: - return 1; -} - -static void ldim_initial_txlx(unsigned int ldim_bl_en, - unsigned int ldim_hvcnt_bypass) -{ - unsigned int i; - unsigned int data; - unsigned int *arrayTmp; - - arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); - if (arrayTmp == NULL) { - LDIMERR("%s malloc error\n", __func__); - return; - } - - /* LD_FRM_SIZE */ - data = ((nPRM.reg_LD_pic_RowMax & 0xfff)<<16) | - (nPRM.reg_LD_pic_ColMax & 0xfff); - LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); - - /* LD_RGB_MOD */ - data = ((0 & 0xfff) << 20) | - ((nPRM.reg_LD_RGBmapping_demo & 0x1) << 19) | - ((nPRM.reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | - ((nPRM.reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | - ((nPRM.reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | - ((0 & 0x1) << 15) | - ((nPRM.reg_LD_BkLit_LPFmod & 0x7) << 12) | - ((nPRM.reg_LD_Litshft & 0x7) << 8) | - ((nPRM.reg_LD_BackLit_Xtlk & 0x1) << 7) | - ((nPRM.reg_LD_BkLit_Intmod & 0x1) << 6) | - ((nPRM.reg_LD_BkLUT_Intmod & 0x1) << 5) | - ((nPRM.reg_LD_BkLit_curmod & 0x1) << 4) | - ((nPRM.reg_LD_BackLit_mode & 0x3)); - LDIM_WR_32Bits(REG_LD_RGB_MOD, data); - - /* LD_BLK_HVNUM */ - data = ((nPRM.reg_LD_Reflect_Vnum & 0x7) << 20) | - ((nPRM.reg_LD_Reflect_Hnum & 0x7) << 16) | - ((nPRM.reg_LD_BLK_Vnum & 0x3f) << 8) | - ((nPRM.reg_LD_BLK_Hnum & 0x3f)); - LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); - - /* LD_HVGAIN */ - data = ((nPRM.reg_LD_Vgain & 0xfff) << 16) | - (nPRM.reg_LD_Hgain & 0xfff); - LDIM_WR_32Bits(REG_LD_HVGAIN, data); - - /* LD_BKLIT_VLD */ - data = 0; - for (i = 0; i < 32; i++) - if (nPRM.reg_LD_BkLit_valid[i]) - data = data | (1 << i); - LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); - - /* LD_BKLIT_PARAM */ - data = ((nPRM.reg_LD_BkLit_Celnum & 0xff) << 16) | - (nPRM.reg_BL_matrix_AVG & 0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* LD_LIT_GAIN_COMP */ - data = ((nPRM.reg_LD_Litgain & 0xfff) << 16) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - - /* LD_FRM_RST_POS */ - data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ - LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); - - /* LD_FRM_BL_START_POS */ - data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ - LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); - - /* REG_LD_FRM_HBLAN_VHOLS */ - data = ((nPRM.reg_LD_LUT_VHo_LS & 0x7) << 16) | - ((6 & 0x1fff)) ; /*frm_hblank_num */ - LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); - - /* REG_LD_XLUT_DEMO_ROI_XPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_xstart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_YPOS */ - data = ((nPRM.reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | - (nPRM.reg_LD_xlut_demo_roi_ystart & 0x1fff); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); - - /* REG_LD_XLUT_DEMO_ROI_CTRL */ - data = ((nPRM.reg_LD_xlut_oroi_enable & 0x1) << 1) | - (nPRM.reg_LD_xlut_iroi_enable & 0x1); - LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); - - /*LD_BLMAT_RAM_MISC*/ - LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); - - /* X_idx: 12*16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM.X_idx[0], 16, 16); - - /* X_nrm[16]: 4 * 16 */ - LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM.X_nrm[0], 4, 16); - - /*reg_LD_BLK_Hidx[33]: 14*33 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Hidx, 16, 33); - - /* reg_LD_BLK_Vidx[25]: 14*25 */ - LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, - nPRM.reg_LD_BLK_Vidx, 16, 25); - - /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHk_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHk_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ - for (i = 0; i < 32; i++) - arrayTmp[i] = nPRM.reg_LD_LUT_VHo_pos[i]; - for (i = 0; i < 32; i++) - arrayTmp[32+i] = nPRM.reg_LD_LUT_VHo_neg[i]; - LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); - - /* reg_LD_LUT_HHk[32]:u8 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM.reg_LD_LUT_HHk, 8, 32); - - /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], - * reg_LD_Reflect_Xdgr[4] - */ - for (i = 0; i < 20; i++) - arrayTmp[i] = nPRM.reg_LD_Reflect_Hdgr[i]; - for (i = 0; i < 20; i++) - arrayTmp[20+i] = nPRM.reg_LD_Reflect_Vdgr[i]; - for (i = 0; i < 4; i++) - arrayTmp[40+i] = nPRM.reg_LD_Reflect_Xdgr[i]; - LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); - - /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ - for (i = 0; i < 8; i++) - arrayTmp[i] = (nPRM.reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | - ((nPRM.reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | - ((nPRM.reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); - LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); - - /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, - nPRM.reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, - nPRM.reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ - LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, - nPRM.reg_LD_LUT_VHk_TXLX[0], 16, 8*32); - - /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ - LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM.reg_LD_LUT_Id, 4, 384); - - /*enable the CBUS configure the RAM*/ - /*LD_MISC_CTRL0 {reg_blmat_ram_mode, - *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, - *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, - *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) - */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = (data & (~(3 << 9))) | (1 << 8); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /*X_lut[3][16][16]*/ - LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM.X_lut2[0][0], 3*16*16); - data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | - (ldim_hvcnt_bypass << 5) | (1 << 8) | - (3 << 9) | (1 << 12); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - LDIM_Update_Matrix(nPRM.BL_matrix, 16 * 24); - - kfree(arrayTmp); } static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, @@ -591,105 +355,23 @@ static void LDIM_Initial(unsigned int pic_h, unsigned int pic_v, LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->ldim_init) - ldim_dev.ldim_op_func->ldim_init(ldim_bl_en, ldim_hvcnt_bypass); -} - -static void ldim_update_matrix(unsigned int mode) -{ - unsigned int data; - int bl_matrix[8] = {0}; - unsigned int reg_BL_matrix_Compensate = 0x0; - int bl_matrix_1[8] = {0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_1 = 0xfff; - int bl_matrix_2[8] = {0xfff, 0xfff, 0xfff, 0x000, 0x000, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_2 = 0xbff; - int bl_matrix_3[8] = {0, 0, 0, 0xfff, 0, 0, 0, 0}; - unsigned int reg_BL_matrix_Compensate_3 = 0x1ff; - int bl_matrix_4[8] = {0xfff, 0xfff, 0xfff, 0, 0xfff, 0xfff, - 0xfff, 0xfff}; - unsigned int reg_BL_matrix_Compensate_4 = 0xdff; - - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data & (~(3<<4)); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); - - /* gMatrix_LUT: s12*100 ==> max to 8*8 enum ##r/w ram method*/ - if (mode == 0) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate&0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 1) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_1[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_1 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 2) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_2[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data|(reg_BL_matrix_Compensate_2 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 3) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_3[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_3 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } else if (mode == 4) { - LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, - &bl_matrix_4[0], 8); - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = data | (reg_BL_matrix_Compensate_4 & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + if (ldim_dev.ldim_op_func->ldim_init) { + ldim_dev.ldim_op_func->ldim_init(&nPRM, + ldim_bl_en, ldim_hvcnt_bypass); } - /* disable the CBUS configure the RAM */ - data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); - data = data | (3<<4); - LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); } -static void ldim_update_txlx(void) -{ - unsigned int data; - - if (ldim_avg_update_en) { - /* LD_BKLIT_PARAM */ - data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); - data = (data&(~0xfff)) | (nPRM.reg_BL_matrix_AVG&0xfff); - LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); - - /* compensate */ - data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); - data = (data&(~0xfff)) | - (nPRM.reg_BL_matrix_Compensate & 0xfff); - LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); - } - - if (ldim_matrix_update_en) - LDIM_Update_Matrix(nPRM.BL_matrix, ldim_blk_row*ldim_blk_col); - -} - -static void ldim_update_setting(void) +static void ldim_remap_update(void) { if (ldim_dev.ldim_op_func == NULL) { if (brightness_vs_cnt == 0) LDIMERR("%s: invalid ldim_op_func\n", __func__); return; } - if (ldim_dev.ldim_op_func->update_setting) - ldim_dev.ldim_op_func->update_setting(); + if (ldim_dev.ldim_op_func->remap_update) { + ldim_dev.ldim_op_func->remap_update(&nPRM, + ldim_avg_update_en, ldim_matrix_update_en); + } } static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) @@ -706,7 +388,7 @@ static irqreturn_t ldim_vsync_isr(int irq, void *dev_id) if (ldim_func_en) { if (ldim_avg_update_en) - ldim_update_setting(); + ldim_remap_update(); if (ldim_hist_en) { /*schedule_work(&ldim_on_vs_work);*/ @@ -1293,7 +975,7 @@ static void ldim_get_matrix_info(void) } pr_info("current black_frm: %d\n", ldim_fw_para.black_frm); - pr_info("spi transfer_matrix:\n"); + pr_info("ldim_dev brightness transfer_matrix:\n"); for (i = 0; i < ldim_blk_row; i++) { len = 0; for (j = 0; j < ldim_blk_col; j++) { @@ -1662,7 +1344,8 @@ static int ldim_on_init(void) { int ret = 0; - LDIMPR("%s\n", __func__); + if (ldim_debug_print) + LDIMPR("%s\n", __func__); /* init ldim */ ldim_stts_initial(ldim_config.hsize, ldim_config.vsize, @@ -1745,6 +1428,7 @@ static struct aml_ldim_driver_s ldim_driver = { .valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */ .dev_index = 0xff, .static_pic_flag = 0, + .vsync_change_flag = 0, .pinmux_flag = 0xff, .ldim_conf = &ldim_config, .ldev_conf = NULL, @@ -1774,6 +1458,45 @@ struct aml_ldim_driver_s *aml_ldim_get_driver(void) return &ldim_driver; } +/* ****************************************************** + * local dimming dummy function for virtual ldim dev + * ****************************************************** + */ +static int ldim_virtual_smr(unsigned short *buf, unsigned char len) +{ + return 0; +} + +static int ldim_virtual_power_on(void) +{ + return 0; +} + +static int ldim_virtual_power_off(void) +{ + return 0; +} + +static int ldim_virtual_driver_update(struct aml_ldim_driver_s *ldim_drv) +{ + ldim_drv->device_power_on = ldim_virtual_power_on; + ldim_drv->device_power_off = ldim_virtual_power_off; + ldim_drv->device_bri_update = ldim_virtual_smr; + + return 0; +} + +static int ldim_dev_add_virtual_driver(struct aml_ldim_driver_s *ldim_drv) +{ + LDIMPR("%s\n", __func__); + + ldim_virtual_driver_update(ldim_drv); + ldim_drv->init(); + + return 0; +} +/* ****************************************************** */ + static int ldim_open(struct inode *inode, struct file *file) { struct ldim_dev_s *devp; @@ -2355,16 +2078,6 @@ static ssize_t ldim_attr_store(struct class *cla, pr_info("reg_addr: 0x%x=0x%x, readback: 0x%x\n", reg_addr, reg_val, LDIM_RD_32Bits(reg_addr)); } - } else if (!strcmp(parm[0], "update_matrix")) { - unsigned int mode = 0; - - if (parm[1] != NULL) { - if (kstrtouint(parm[1], 10, &mode) < 0) - goto ldim_attr_store_err; - - ldim_update_matrix(mode); - pr_info("mode: %d\n", mode); - } } else if (!strcmp(parm[0], "bl_remap_curve")) { if (parm[1] != NULL) { if (!strcmp(parm[1], "r")) { @@ -2854,7 +2567,8 @@ static ssize_t ldim_attr_store(struct class *cla, ldim_fw_para.Dbprint_lv); } else if (!strcmp(parm[0], "info")) { pr_info("ldim_drv_ver: %s\n", LDIM_DRV_VER); - ldim_driver.config_print(); + if (ldim_driver.config_print) + ldim_driver.config_print(); pr_info("\nldim_blk_row = %d\n" "ldim_blk_col = %d\n" "ldim_hist_row = %d\n" @@ -2943,10 +2657,32 @@ static ssize_t ldim_func_en_store(struct class *class, return count; } +static ssize_t ldim_para_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = sprintf(buf, "boost_gain=%d\n", ldim_fw_para.boost_gain); + + return len; +} + +static ssize_t ldim_dump_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + int len = 0; + + len = ldim_hw_reg_dump(buf); + + return len; +} + static struct class_attribute aml_ldim_class_attrs[] = { __ATTR(attr, 0644, ldim_attr_show, ldim_attr_store), __ATTR(func_en, 0644, ldim_func_en_show, ldim_func_en_store), + __ATTR(para, 0644, ldim_para_show, NULL), + __ATTR(dump, 0644, ldim_dump_show, NULL), __ATTR_NULL, }; @@ -2999,7 +2735,8 @@ int aml_ldim_get_config_dts(struct device_node *child) LDIMERR("failed to get ldim_dev_index\n"); else ldim_driver.dev_index = (unsigned char)para[0]; - LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get ldim_dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3031,7 +2768,8 @@ int aml_ldim_get_config_unifykey(unsigned char *buf) /* get ldim_dev_index 1byte*/ ldim_driver.dev_index = *(p + LCD_UKEY_BL_LDIM_DEV_INDEX); - LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); + if (ldim_driver.dev_index < 0xff) + LDIMPR("get dev_index = %d\n", ldim_driver.dev_index); return 0; } @@ -3191,17 +2929,52 @@ ldim_malloc_err0: } static struct ldim_operate_func_s ldim_op_func_txlx = { - .update_setting = ldim_update_txlx, + .h_region_max = 24, + .v_region_max = 16, + .total_region_max = 384, + .remap_update = ldim_remap_update_txlx, .stts_init = ldim_stts_initial_txlx, .ldim_init = ldim_initial_txlx, }; static struct ldim_operate_func_s ldim_op_func_tl1 = { - .update_setting = NULL, - .stts_init = NULL, + .h_region_max = 31, + .v_region_max = 16, + .total_region_max = 128, + .remap_update = NULL, + .stts_init = ldim_stts_initial_tl1, .ldim_init = NULL, }; +static int ldim_region_num_check(struct ldim_operate_func_s *ldim_func) +{ + unsigned short temp; + + if (ldim_func == NULL) { + LDIMERR("%s: ldim_func is NULL\n", __func__); + return -1; + } + + if (ldim_config.row > ldim_func->v_region_max) { + LDIMERR("%s: blk row (%d) is out of support (%d)\n", + __func__, ldim_config.row, ldim_func->v_region_max); + return -1; + } + if (ldim_config.col > ldim_func->h_region_max) { + LDIMERR("%s: blk col (%d) is out of support (%d)\n", + __func__, ldim_config.col, ldim_func->h_region_max); + return -1; + } + temp = ldim_config.row * ldim_config.col; + if (temp > ldim_func->total_region_max) { + LDIMERR("%s: blk total region (%d) is out of support (%d)\n", + __func__, temp, ldim_func->total_region_max); + return -1; + } + + return 0; +} + int aml_ldim_probe(struct platform_device *pdev) { int ret = 0; @@ -3240,6 +3013,7 @@ int aml_ldim_probe(struct platform_device *pdev) /* ldim_op_func */ switch (bl_drv->data->chip_type) { case BL_CHIP_TL1: + case BL_CHIP_TM2: devp->ldim_op_func = &ldim_op_func_tl1; break; case BL_CHIP_TXLX: @@ -3249,6 +3023,9 @@ int aml_ldim_probe(struct platform_device *pdev) devp->ldim_op_func = NULL; break; } + ret = ldim_region_num_check(devp->ldim_op_func); + if (ret) + return -1; ret = aml_ldim_malloc(ldim_blk_row, ldim_blk_col); if (ret) { @@ -3319,12 +3096,18 @@ int aml_ldim_probe(struct platform_device *pdev) goto err; } ldim_vsync_irq = bl_drv->res_ldim_vsync_irq->start; - LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); + if (ldim_debug_print) + LDIMPR("ldim_vsync_irq: %d\n", ldim_vsync_irq); if (request_irq(ldim_vsync_irq, ldim_vsync_isr, IRQF_SHARED, - "ldim_vsync", (void *)"ldim_vsync")) + "ldim_vsync", (void *)"ldim_vsync")) { LDIMERR("can't request ldim_vsync_irq\n"); - else - LDIMPR("request ldim_vsync_irq successful\n"); + } else { + if (ldim_debug_print) + LDIMPR("request ldim_vsync_irq successful\n"); + } + + if (bl_drv->bconf->method != BL_CTRL_LOCAL_DIMMING) + ldim_dev_add_virtual_driver(&ldim_driver); ldim_driver.valid_flag = 1; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h index dfd58f785a62..76c23ce4b7f6 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h @@ -24,7 +24,10 @@ /*20180730: algorithm clear up */ /*20180820: pq tooling support, espically optimize some alg parameters */ /*20181101: fix ldim_op_func null mistake, add new spi api support */ -#define LDIM_DRV_VER "20181101" +/*20181203: add 50/60hz change & iw7027 error handle support */ +/*20181220: add tl1 support*/ +/*20190103: add analog pwm support*/ +#define LDIM_DRV_VER "20190103" extern unsigned char ldim_debug_print; @@ -38,25 +41,36 @@ extern int LD_remap_lut[16][32]; /*========================================*/ struct ldim_operate_func_s { - void (*update_setting)(void); - void (*stts_init)(unsigned int resolution); - void (*ldim_init)(unsigned int bl_en, unsigned int hvcnt_bypass); + unsigned short h_region_max; + unsigned short v_region_max; + unsigned short total_region_max; + void (*remap_update)(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + void (*stts_init)(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); + void (*ldim_init)(struct LDReg_s *nPRM, + unsigned int bl_en, unsigned int hvcnt_bypass); }; /*========================================*/ extern int ldim_round(int ix, int ib); -extern void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en); -extern void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum); extern void LD_ConLDReg(struct LDReg_s *Reg); extern void ld_fw_cfg_once(struct LDReg_s *nPRM); -extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); +/* ldim hw */ +extern int ldim_hw_reg_dump(char *buf); +extern void ldim_stts_read_region(unsigned int nrow, unsigned int ncol); extern void ldim_set_matrix_ycbcr2rgb(void); extern void ldim_set_matrix_rgb2ycbcr(int mode); +extern void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass); +extern void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum); +extern void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en); + #endif diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c index 606cd542e203..613c6a728507 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_func.c @@ -38,9 +38,6 @@ #define MIN(a, b) ((a < b) ? a:b) #endif -#define Wr(reg, val) Wr_reg(reg, val) -#define Rd(reg) Rd_reg(reg) - static int LD_BLK_Hidx[33] = { /* S14* 33 */ -1920, -1440, -960, -480, 0, 480, @@ -246,385 +243,6 @@ int ldim_round(int ix, int ib) return ld_rst; } -/***** local dimming stts functions begin *****/ -/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, - *2: the hist of all comp0,1,2 are calculated - */ -/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ -/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after - *read a 25/48 block, 2: increases every read and lock sub-idx - */ -/*one_ram_en 1: one ram mode; 0:double ram mode*/ -void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, - unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, - unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) -{ - int data32; - - Wr(LDIM_STTS_GCLK_CTRL0, 0x0); - Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); - - data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); - data32 = data32 | ((eol_en & 0x1) << 28); - data32 = data32 | ((one_ram_en & 0x1) << 27); - data32 = data32 | ((hist_mode & 0x3) << 22); - data32 = data32 | ((lpf_en & 0x1) << 21); - data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); - Wr(LDIM_STTS_HIST_REGION_IDX, data32); -} - -void ldim_set_region(unsigned int resolution, unsigned int blk_height, - unsigned int blk_width, unsigned int row_start, unsigned int col_start, - unsigned int blk_hnum) -{ - unsigned int hend0, hend1, hend2, hend3, hend4, hend5, - hend6, hend7, hend8, hend9, hend10, hend11, hend12, - hend13, hend14, hend15, hend16, hend17, hend18, - hend19, hend20, hend21, hend22, hend23; - unsigned int vend0, vend1, vend2, vend3, vend4, vend5, - vend6, vend7, vend8, vend9, vend10, vend11, - vend12, vend13, vend14, vend15; - unsigned int data32, k, h_index[24], v_index[16]; - - if (resolution == 0) { - h_index[0] = col_start + blk_width - 1; - for (k = 1; k < 24; k++) { - h_index[k] = h_index[k-1] + blk_width; - if (h_index[k] > 4095) - h_index[k] = 4095; /* clip U12 */ - } - v_index[0] = row_start + blk_height - 1; - for (k = 1; k < 16; k++) { - v_index[k] = v_index[k-1] + blk_height; - if (v_index[k] > 4095) - v_index[k] = 4095; /* clip U12 */ - } - hend0 = h_index[0];/*col_start + blk_width - 1;*/ - hend1 = h_index[1];/*hend0 + blk_width;*/ - hend2 = h_index[2];/*hend1 + blk_width;*/ - hend3 = h_index[3];/*hend2 + blk_width;*/ - hend4 = h_index[4];/*hend3 + blk_width;*/ - hend5 = h_index[5];/*hend4 + blk_width;*/ - hend6 = h_index[6];/*hend5 + blk_width;*/ - hend7 = h_index[7];/*hend6 + blk_width;*/ - hend8 = h_index[8];/*hend7 + blk_width;*/ - hend9 = h_index[9];/*hend8 + blk_width;*/ - hend10 = h_index[10];/*hend9 + blk_width ;*/ - hend11 = h_index[11];/*hend10 + blk_width;*/ - hend12 = h_index[12];/*hend11 + blk_width;*/ - hend13 = h_index[13];/*hend12 + blk_width;*/ - hend14 = h_index[14];/*hend13 + blk_width;*/ - hend15 = h_index[15];/*hend14 + blk_width;*/ - hend16 = h_index[16];/*hend15 + blk_width;*/ - hend17 = h_index[17];/*hend16 + blk_width;*/ - hend18 = h_index[18];/*hend17 + blk_width;*/ - hend19 = h_index[19];/*hend18 + blk_width;*/ - hend20 = h_index[20];/*hend19 + blk_width ;*/ - hend21 = h_index[21];/*hend20 + blk_width;*/ - hend22 = h_index[22];/*hend21 + blk_width;*/ - hend23 = h_index[23];/*hend22 + blk_width;*/ - vend0 = v_index[0];/*row_start + blk_height - 1;*/ - vend1 = v_index[1];/*vend0 + blk_height;*/ - vend2 = v_index[2];/*vend1 + blk_height;*/ - vend3 = v_index[3];/*vend2 + blk_height;*/ - vend4 = v_index[4];/*vend3 + blk_height;*/ - vend5 = v_index[5];/*vend4 + blk_height;*/ - vend6 = v_index[6];/*vend5 + blk_height;*/ - vend7 = v_index[7];/*vend6 + blk_height;*/ - vend8 = v_index[8];/*vend7 + blk_height;*/ - vend9 = v_index[9];/*vend8 + blk_height;*/ - vend10 = v_index[10];/*vend9 + blk_height;*/ - vend11 = v_index[11];/*vend10 + blk_height;*/ - vend12 = v_index[12];/*vend11 + blk_height;*/ - vend13 = v_index[13];/*vend12 + blk_height;*/ - vend14 = v_index[14];/*vend13 + blk_height;*/ - vend15 = v_index[15];/*vend14 + blk_height;*/ - - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, ((((row_start & 0x1fff) << 16) - & 0xffff0000) | (col_start & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) - | (hend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) - | (vend0 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) - | (hend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) - | (vend2 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) - | (hend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) - | (vend4 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) - | (hend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) - | (vend6 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) - | (hend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) - | (vend8 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) - | (hend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) - | (vend10 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) - | (hend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) - | (vend12 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) - | (hend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) - | (vend14 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) - | (hend16 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) - | (hend18 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) - | (hend20 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) - | (hend22 & 0x1fff))); - Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ - } else if (resolution == 1) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); - Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ - } else if (resolution == 2) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ - Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ - } else if (resolution == 3) { - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); - Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); - Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); - Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); - Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 4) { /* 5x6 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); - Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 5) { /* 8x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 6) { /* 2x1 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); - Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); - Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 7) { /* 2x2 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); - Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 8) { /* 3x5 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); - Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 9) { /* 4x3 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } else if (resolution == 10) { /* 6x8 */ - data32 = Rd(LDIM_STTS_HIST_REGION_IDX); - Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); - - Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); - Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); - Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); - Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); - Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ - /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ - } -} - -static unsigned int invalid_val_cnt; -void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) -{ - unsigned int i, j, k; - unsigned int data32; - struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); - - if (invalid_val_cnt > 0xfffffff) - invalid_val_cnt = 0; - - Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) - & 0xffffc000); - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - - for (i = 0; i < nrow; i++) { - for (j = 0; j < ncol; j++) { - data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); - for (k = 0; k < 17; k++) { - if (k == 16) { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->max_rgb[i * ncol + j] - = data32; - } else { - data32 = Rd(LDIM_STTS_HIST_READ_REGION); - ldim_drv->hist_matrix[i * ncol * 16 + - j * 16 + k] = data32; - } - if (!(data32 & 0x40000000)) - invalid_val_cnt++; - } - } - } -} - -/* VDIN_MATRIX_YUV601_RGB */ -/* -16 1.164 0 1.596 0 */ -/* -128 1.164 -0.391 -0.813 0 */ -/* -128 1.164 2.018 0 0 */ -/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, - * 0x00000000, 0x00000000, 0x00000000,}, - */ -void ldim_set_matrix_ycbcr2rgb(void) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ - - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); - Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); - Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); - Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); - Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); - Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); -} - -void ldim_set_matrix_rgb2ycbcr(int mode) -{ - Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); - if (mode == 0) {/*ycbcr not full range, 601 conversion*/ - Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); - Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); - /* 0.257 0.504 0.098 */ - /* -0.148 -0.291 0.439 */ - /* 0.439 -0.368 -0.071 */ - Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); - Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); - Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); - Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); - Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); - - Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); - } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ - /* todo */ - } -} - int Round(int iX, int iB) { int Rst = 0; diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c new file mode 100644 index 000000000000..7d2dcc1f83b1 --- /dev/null +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c @@ -0,0 +1,1021 @@ +/* + * drivers/amlogic/media/vout/backlight/aml_ldim/ldim_hw.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldim_drv.h" +#include "ldim_reg.h" + +#define Wr(reg, val) Wr_reg(reg, val) +#define Rd(reg) Rd_reg(reg) + +static int LDIM_Update_Matrix(int NewBlMatrix[], int BlMatrixNum) +{ + int data; + + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + if (data & (1 << 12)) { /*bl_ram_mode=1;*/ + if (LDIM_RD_32Bits(REG_LD_BLMAT_RAM_MISC) & 0x10000) + /*Previous Matrix is not used*/ + goto Previous_Matrix; + else { + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, + (BlMatrixNum & 0x1ff) | (1 << 16)); + /*set Matrix update ready*/ + + return 0; + } + } else { /*bl_ram_mode=0*/ + /*set ram_clk_sel=0, ram_bus_sel = 0*/ + data = data & (~(3 << 9)); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + LDIM_WR_BASE_LUT_DRT(REG_LD_MATRIX_BASE, + NewBlMatrix, BlMatrixNum); + data = data | (3 << 9); /*set ram_clk_sel=1, ram_bus_sel = 1*/ + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + return 0; + } + +Previous_Matrix: + return 1; +} + +void ldim_initial_txlx(struct LDReg_s *nPRM, + unsigned int ldim_bl_en, unsigned int ldim_hvcnt_bypass) +{ + unsigned int i; + unsigned int data; + unsigned int *arrayTmp; + + arrayTmp = kcalloc(1536, sizeof(unsigned int), GFP_KERNEL); + if (arrayTmp == NULL) { + LDIMERR("%s malloc error\n", __func__); + return; + } + + /* LD_FRM_SIZE */ + data = ((nPRM->reg_LD_pic_RowMax & 0xfff)<<16) | + (nPRM->reg_LD_pic_ColMax & 0xfff); + LDIM_WR_32Bits(REG_LD_FRM_SIZE, data); + + /* LD_RGB_MOD */ + data = ((0 & 0xfff) << 20) | + ((nPRM->reg_LD_RGBmapping_demo & 0x1) << 19) | + ((nPRM->reg_LD_X_LUT_interp_mode[2] & 0x1) << 18) | + ((nPRM->reg_LD_X_LUT_interp_mode[1] & 0x1) << 17) | + ((nPRM->reg_LD_X_LUT_interp_mode[0] & 0x1) << 16) | + ((0 & 0x1) << 15) | + ((nPRM->reg_LD_BkLit_LPFmod & 0x7) << 12) | + ((nPRM->reg_LD_Litshft & 0x7) << 8) | + ((nPRM->reg_LD_BackLit_Xtlk & 0x1) << 7) | + ((nPRM->reg_LD_BkLit_Intmod & 0x1) << 6) | + ((nPRM->reg_LD_BkLUT_Intmod & 0x1) << 5) | + ((nPRM->reg_LD_BkLit_curmod & 0x1) << 4) | + ((nPRM->reg_LD_BackLit_mode & 0x3)); + LDIM_WR_32Bits(REG_LD_RGB_MOD, data); + + /* LD_BLK_HVNUM */ + data = ((nPRM->reg_LD_Reflect_Vnum & 0x7) << 20) | + ((nPRM->reg_LD_Reflect_Hnum & 0x7) << 16) | + ((nPRM->reg_LD_BLK_Vnum & 0x3f) << 8) | + ((nPRM->reg_LD_BLK_Hnum & 0x3f)); + LDIM_WR_32Bits(REG_LD_BLK_HVNUM, data); + + /* LD_HVGAIN */ + data = ((nPRM->reg_LD_Vgain & 0xfff) << 16) | + (nPRM->reg_LD_Hgain & 0xfff); + LDIM_WR_32Bits(REG_LD_HVGAIN, data); + + /* LD_BKLIT_VLD */ + data = 0; + for (i = 0; i < 32; i++) + if (nPRM->reg_LD_BkLit_valid[i]) + data = data | (1 << i); + LDIM_WR_32Bits(REG_LD_BKLIT_VLD, data); + + /* LD_BKLIT_PARAM */ + data = ((nPRM->reg_LD_BkLit_Celnum & 0xff) << 16) | + (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* LD_LIT_GAIN_COMP */ + data = ((nPRM->reg_LD_Litgain & 0xfff) << 16) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + + /* LD_FRM_RST_POS */ + data = (1 << 16) | (5); /* h=1,v=5 :ldim_param_frm_rst_pos */ + LDIM_WR_32Bits(REG_LD_FRM_RST_POS, data); + + /* LD_FRM_BL_START_POS */ + data = (1 << 16) | (6); /* ldim_param_frm_bl_start_pos; */ + LDIM_WR_32Bits(REG_LD_FRM_BL_START_POS, data); + + /* REG_LD_FRM_HBLAN_VHOLS */ + data = ((nPRM->reg_LD_LUT_VHo_LS & 0x7) << 16) | + ((6 & 0x1fff)) ; /*frm_hblank_num */ + LDIM_WR_32Bits(REG_LD_FRM_HBLAN_VHOLS, data); + + /* REG_LD_XLUT_DEMO_ROI_XPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_xend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_xstart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_XPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_YPOS */ + data = ((nPRM->reg_LD_xlut_demo_roi_yend & 0x1fff) << 16) | + (nPRM->reg_LD_xlut_demo_roi_ystart & 0x1fff); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_YPOS, data); + + /* REG_LD_XLUT_DEMO_ROI_CTRL */ + data = ((nPRM->reg_LD_xlut_oroi_enable & 0x1) << 1) | + (nPRM->reg_LD_xlut_iroi_enable & 0x1); + LDIM_WR_32Bits(REG_LD_XLUT_DEMO_ROI_CTRL, data); + + /*LD_BLMAT_RAM_MISC*/ + LDIM_WR_32Bits(REG_LD_BLMAT_RAM_MISC, 384 & 0x1ff); + + /* X_idx: 12*16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_IDX_BASE, nPRM->X_idx[0], 16, 16); + + /* X_nrm[16]: 4 * 16 */ + LDIM_WR_BASE_LUT(REG_LD_RGB_NRMW_BASE_TXLX, nPRM->X_nrm[0], 4, 16); + + /*reg_LD_BLK_Hidx[33]: 14*33 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_HIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Hidx, 16, 33); + + /* reg_LD_BLK_Vidx[25]: 14*25 */ + LDIM_WR_BASE_LUT(REG_LD_BLK_VIDX_BASE_TXLX, + nPRM->reg_LD_BLK_Vidx, 16, 25); + + /* reg_LD_LUT_VHk_pos[32]/reg_LD_LUT_VHk_neg[32]: u8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHk_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHk_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_VHo_pos[32]/reg_LD_LUT_VHo_neg[32]: s8 */ + for (i = 0; i < 32; i++) + arrayTmp[i] = nPRM->reg_LD_LUT_VHo_pos[i]; + for (i = 0; i < 32; i++) + arrayTmp[32+i] = nPRM->reg_LD_LUT_VHo_neg[i]; + LDIM_WR_BASE_LUT(REG_LD_LUT_VHO_NEGPOS_BASE_TXLX, arrayTmp, 8, 64); + + /* reg_LD_LUT_HHk[32]:u8 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_HHK_BASE_TXLX, nPRM->reg_LD_LUT_HHk, 8, 32); + + /*reg_LD_Reflect_Hdgr[20],reg_LD_Reflect_Vdgr[20], + * reg_LD_Reflect_Xdgr[4] + */ + for (i = 0; i < 20; i++) + arrayTmp[i] = nPRM->reg_LD_Reflect_Hdgr[i]; + for (i = 0; i < 20; i++) + arrayTmp[20+i] = nPRM->reg_LD_Reflect_Vdgr[i]; + for (i = 0; i < 4; i++) + arrayTmp[40+i] = nPRM->reg_LD_Reflect_Xdgr[i]; + LDIM_WR_BASE_LUT(REG_LD_REFLECT_DGR_BASE_TXLX, arrayTmp, 8, 44); + + /*reg_LD_LUT_Hdg_LEXT[8]/reg_LD_LUT_Vdg_LEXT[8]/reg_LD_LUT_VHk_LEXT[8]*/ + for (i = 0; i < 8; i++) + arrayTmp[i] = (nPRM->reg_LD_LUT_Hdg_LEXT_TXLX[i] & 0x3ff) | + ((nPRM->reg_LD_LUT_VHk_LEXT_TXLX[i] & 0x3ff) << 10) | + ((nPRM->reg_LD_LUT_Vdg_LEXT_TXLX[i] & 0x3ff) << 20); + LDIM_WR_BASE_LUT_DRT(REG_LD_LUT_LEXT_BASE_TXLX, arrayTmp, 8); + + /*reg_LD_LUT_Hdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_HDG_BASE_TXLX, + nPRM->reg_LD_LUT_Hdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Vdg[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VDG_BASE_TXLX, + nPRM->reg_LD_LUT_Vdg_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_VHk[8][32]: u10*8*32*/ + LDIM_WR_BASE_LUT(REG_LD_LUT_VHK_BASE_TXLX, + nPRM->reg_LD_LUT_VHk_TXLX[0], 16, 8*32); + + /*reg_LD_LUT_Id[16][24]: u3*16*24=u3*384 */ + LDIM_WR_BASE_LUT(REG_LD_LUT_ID_BASE_TXLX, nPRM->reg_LD_LUT_Id, 4, 384); + + /*enable the CBUS configure the RAM*/ + /*LD_MISC_CTRL0 {reg_blmat_ram_mode, + *1'h0,ram_bus_sel,ram_clk_sel,ram_clk_gate_en, + *2'h0,reg_hvcnt_bypass,reg_demo_synmode,reg_ldbl_synmode, + *reg_ldim_bl_en,soft_bl_start,reg_soft_rst) + */ + data = LDIM_RD_32Bits(REG_LD_MISC_CTRL0); + data = (data & (~(3 << 9))) | (1 << 8); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + /*X_lut[3][16][16]*/ + LDIM_WR_BASE_LUT_DRT(REG_LD_RGB_LUT_BASE, nPRM->X_lut2[0][0], 3*16*16); + + data = 0 | (0 << 1) | ((ldim_bl_en & 0x1) << 2) | + (ldim_hvcnt_bypass << 5) | (1 << 8) | + (3 << 9) | (1 << 12); + LDIM_WR_32Bits(REG_LD_MISC_CTRL0, data); + + LDIM_Update_Matrix(nPRM->BL_matrix, 16 * 24); + + kfree(arrayTmp); +} + +static unsigned int ldim_hw_reg_dump_table[] = { + LDIM_STTS_GCLK_CTRL0, + LDIM_STTS_WIDTHM1_HEIGHTM1, + LDIM_STTS_CTRL0, + LDIM_STTS_HIST_REGION_IDX, +}; + +int ldim_hw_reg_dump(char *buf) +{ + unsigned int reg, data32; + int i, size, len = 0; + + size = sizeof(ldim_hw_reg_dump_table) / sizeof(unsigned int); + for (i = 0; i < size; i++) { + reg = ldim_hw_reg_dump_table[i]; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + for (i = 0; i < 23; i++) { + reg = LDIM_STTS_HIST_SET_REGION; + data32 = Rd(reg); + len += sprintf(buf+len, "0x%x = 0x%08x\n", reg, data32); + } + + return len; +} + +/***** local dimming stts functions begin *****/ +/*hist mode: 0: comp0 hist only, 1: Max(comp0,1,2) for hist, + *2: the hist of all comp0,1,2 are calculated + */ +/*lpf_en 1: 1,2,1 filter on before finding max& hist*/ +/*rd_idx_auto_inc_mode 0: no self increase, 1: read index increase after + *read a 25/48 block, 2: increases every read and lock sub-idx + */ +/*one_ram_en 1: one ram mode; 0:double ram mode*/ +static void ldim_stts_en(unsigned int resolution, unsigned int pix_drop_mode, + unsigned int eol_en, unsigned int hist_mode, unsigned int lpf_en, + unsigned int rd_idx_auto_inc_mode, unsigned int one_ram_en) +{ + int data32; + + Wr(LDIM_STTS_GCLK_CTRL0, 0x0); + Wr(LDIM_STTS_WIDTHM1_HEIGHTM1, resolution); + + data32 = 0x80000000 | ((pix_drop_mode & 0x3) << 29); + data32 = data32 | ((eol_en & 0x1) << 28); + data32 = data32 | ((one_ram_en & 0x1) << 27); + data32 = data32 | ((hist_mode & 0x3) << 22); + data32 = data32 | ((lpf_en & 0x1) << 21); + data32 = data32 | ((rd_idx_auto_inc_mode & 0xff) << 14); + Wr(LDIM_STTS_HIST_REGION_IDX, data32); +} + +static void ldim_stts_set_region_txlx(unsigned int resolution, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_hnum) +{ + unsigned int hend0, hend1, hend2, hend3, hend4, hend5, + hend6, hend7, hend8, hend9, hend10, hend11, hend12, + hend13, hend14, hend15, hend16, hend17, hend18, + hend19, hend20, hend21, hend22, hend23; + unsigned int vend0, vend1, vend2, vend3, vend4, vend5, + vend6, vend7, vend8, vend9, vend10, vend11, + vend12, vend13, vend14, vend15; + unsigned int data32, k, h_index[24], v_index[16]; + + if (resolution == 0) { + h_index[0] = col_start + blk_width - 1; + for (k = 1; k < 24; k++) { + h_index[k] = h_index[k-1] + blk_width; + if (h_index[k] > 4095) + h_index[k] = 4095; /* clip U12 */ + } + v_index[0] = row_start + blk_height - 1; + for (k = 1; k < 16; k++) { + v_index[k] = v_index[k-1] + blk_height; + if (v_index[k] > 4095) + v_index[k] = 4095; /* clip U12 */ + } + hend0 = h_index[0];/*col_start + blk_width - 1;*/ + hend1 = h_index[1];/*hend0 + blk_width;*/ + hend2 = h_index[2];/*hend1 + blk_width;*/ + hend3 = h_index[3];/*hend2 + blk_width;*/ + hend4 = h_index[4];/*hend3 + blk_width;*/ + hend5 = h_index[5];/*hend4 + blk_width;*/ + hend6 = h_index[6];/*hend5 + blk_width;*/ + hend7 = h_index[7];/*hend6 + blk_width;*/ + hend8 = h_index[8];/*hend7 + blk_width;*/ + hend9 = h_index[9];/*hend8 + blk_width;*/ + hend10 = h_index[10];/*hend9 + blk_width ;*/ + hend11 = h_index[11];/*hend10 + blk_width;*/ + hend12 = h_index[12];/*hend11 + blk_width;*/ + hend13 = h_index[13];/*hend12 + blk_width;*/ + hend14 = h_index[14];/*hend13 + blk_width;*/ + hend15 = h_index[15];/*hend14 + blk_width;*/ + hend16 = h_index[16];/*hend15 + blk_width;*/ + hend17 = h_index[17];/*hend16 + blk_width;*/ + hend18 = h_index[18];/*hend17 + blk_width;*/ + hend19 = h_index[19];/*hend18 + blk_width;*/ + hend20 = h_index[20];/*hend19 + blk_width ;*/ + hend21 = h_index[21];/*hend20 + blk_width;*/ + hend22 = h_index[22];/*hend21 + blk_width;*/ + hend23 = h_index[23];/*hend22 + blk_width;*/ + vend0 = v_index[0];/*row_start + blk_height - 1;*/ + vend1 = v_index[1];/*vend0 + blk_height;*/ + vend2 = v_index[2];/*vend1 + blk_height;*/ + vend3 = v_index[3];/*vend2 + blk_height;*/ + vend4 = v_index[4];/*vend3 + blk_height;*/ + vend5 = v_index[5];/*vend4 + blk_height;*/ + vend6 = v_index[6];/*vend5 + blk_height;*/ + vend7 = v_index[7];/*vend6 + blk_height;*/ + vend8 = v_index[8];/*vend7 + blk_height;*/ + vend9 = v_index[9];/*vend8 + blk_height;*/ + vend10 = v_index[10];/*vend9 + blk_height;*/ + vend11 = v_index[11];/*vend10 + blk_height;*/ + vend12 = v_index[12];/*vend11 + blk_height;*/ + vend13 = v_index[13];/*vend12 + blk_height;*/ + vend14 = v_index[14];/*vend13 + blk_height;*/ + vend15 = v_index[15];/*vend14 + blk_height;*/ + + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend1 & 0x1fff) << 16) + | (hend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend1 & 0x1fff) << 16) + | (vend0 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend3 & 0x1fff) << 16) + | (hend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend3 & 0x1fff) << 16) + | (vend2 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend5 & 0x1fff) << 16) + | (hend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend5 & 0x1fff) << 16) + | (vend4 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend7 & 0x1fff) << 16) + | (hend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend7 & 0x1fff) << 16) + | (vend6 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend9 & 0x1fff) << 16) + | (hend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend9 & 0x1fff) << 16) + | (vend8 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend11 & 0x1fff) << 16) + | (hend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend11 & 0x1fff) << 16) + | (vend10 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend13 & 0x1fff) << 16) + | (hend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend13 & 0x1fff) << 16) + | (vend12 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend15 & 0x1fff) << 16) + | (hend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend15 & 0x1fff) << 16) + | (vend14 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend17 & 0x1fff) << 16) + | (hend16 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend19 & 0x1fff) << 16) + | (hend18 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend21 & 0x1fff) << 16) + | (hend20 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend23 & 0x1fff) << 16) + | (hend22 & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, blk_hnum); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /*line_n_int_num*/ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260);*/ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/*hv00*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/*h01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/*v01*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/*h23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/*v23*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/*h45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/*v45*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/*h67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/*v67*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v89*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1011*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1213*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*v1415*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1617*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h1819*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2021*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/*h2223*/ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780);*/ + /*Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438);*/ + } +} + +static void ldim_stts_set_region_tl1( + unsigned int resolution, + /* 0: auto calc by height/width/row_start/col_start + * 1: 720p + * 2: 1080p + */ + unsigned int height, unsigned int width, + unsigned int blk_height, unsigned int blk_width, + unsigned int row_start, unsigned int col_start, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int data32, h_region_num; + unsigned int heightm1, widthm1; + unsigned int lights_mode = 0; + unsigned int hend[24], vend[16], i; + + memset(hend, 0, (sizeof(unsigned int) * 24)); + memset(vend, 0, (sizeof(unsigned int) * 16)); + + /* 0:normal 1:>24 h region */ + if (blk_hnum > 24) + lights_mode = 1; + h_region_num = blk_hnum; + if (ldim_debug_print) { + pr_info("%s: lights_mode=%d, h_region_num=%d\n", + __func__, lights_mode, h_region_num); + } + + heightm1 = height - 1; + widthm1 = width - 1; + + if (resolution == 0) { + hend[0] = col_start + blk_width - 1; + for (i = 1; i < 24; i++) { + hend[i] = (hend[i-1] + blk_width >= widthm1) ? + hend[i-1] : (hend[i-1] + blk_width); + } + vend[0] = row_start + blk_height - 1; + for (i = 1; i < 16; i++) { + vend[i] = (vend[i-1] + blk_height >= heightm1) ? + vend[i-1] : (vend[i-1] + blk_height); + } + + if (lights_mode == 1) { /* 31 h region */ + vend[8] = (hend[23] + blk_width >= widthm1) ? + hend[23] : (hend[23] + blk_width); + for (i = 9; i < 16; i++) { + vend[i] = (vend[i-1] + blk_width >= widthm1) ? + vend[i-1] : (vend[i-1] + blk_width); + } + } + + Wr_reg_bits(LDIM_STTS_CTRL0, lights_mode, 22, 2); + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xffe0ffff & data32); + Wr(LDIM_STTS_HIST_SET_REGION, + ((((row_start & 0x1fff) << 16) & 0xffff0000) | + (col_start & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[1] & 0x1fff) << 16) | + (hend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[1] & 0x1fff) << 16) | + (vend[0] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[3] & 0x1fff) << 16) | + (hend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[3] & 0x1fff) << 16) | + (vend[2] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[5] & 0x1fff) << 16) | + (hend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[5] & 0x1fff) << 16) | + (vend[4] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[7] & 0x1fff) << 16) | + (hend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[7] & 0x1fff) << 16) | + (vend[6] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[9] & 0x1fff) << 16) | + (hend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[9] & 0x1fff) << 16) | + (vend[8] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[11] & 0x1fff) << 16) | + (hend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[11] & 0x1fff) << 16) | + (vend[10] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[13] & 0x1fff) << 16) | + (hend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[13] & 0x1fff) << 16) | + (vend[12] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[15] & 0x1fff) << 16) | + (hend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((vend[15] & 0x1fff) << 16) | + (vend[14] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[17] & 0x1fff) << 16) | + (hend[16] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[19] & 0x1fff) << 16) | + (hend[18] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[21] & 0x1fff) << 16) | + (hend[20] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, (((hend[23] & 0x1fff) << 16) | + (hend[22] & 0x1fff))); + Wr(LDIM_STTS_HIST_SET_REGION, h_region_num); /*h region number*/ + Wr(LDIM_STTS_HIST_SET_REGION, 0); /* line_n_int_num */ + } else if (resolution == 1) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010010); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1000080); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0800040); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2000180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10000c0); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3000280); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1800140); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000380); + Wr(LDIM_STTS_HIST_SET_REGION, 0x20001c0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff0480); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0260); */ + } else if (resolution == 2) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000);/* hv00 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x17f00bf);/* h01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x0d7006b);/* v01 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff023f);/* h23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af0143);/* v23 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x47f03bf);/* h45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x287021b);/* v45 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff053f);/* h67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f02f3);/* v67 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v89 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1011 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1213 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* v1415 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1617 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h1819 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2021 */ + Wr(LDIM_STTS_HIST_SET_REGION, 0xffe0ffe);/* h2223 */ + } else if (resolution == 3) { + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1df00ef); + Wr(LDIM_STTS_HIST_SET_REGION, 0x10d0086); + Wr(LDIM_STTS_HIST_SET_REGION, 0x3bf02cf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x21b0194); + Wr(LDIM_STTS_HIST_SET_REGION, 0x59f04af); + Wr(LDIM_STTS_HIST_SET_REGION, 0x32902a2); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f068f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x43703b0); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 4) { /* 5x6 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0040001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x27f0136); + Wr(LDIM_STTS_HIST_SET_REGION, 0x1af00d7); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4ff03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x35f0287); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f063f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 5) { /* 8x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x31f02bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x233012b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x30b0243); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x42d03d3); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 6) { /* 2x1 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0030002); + Wr(LDIM_STTS_HIST_SET_REGION, 0x78002bb); + Wr(LDIM_STTS_HIST_SET_REGION, 0x0940031); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 7) { /* 2x2 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f03bf); + Wr(LDIM_STTS_HIST_SET_REGION, 0x437021b); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 8) { /* 3x5 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0000000); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2ff017f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2cf0167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x5ff047f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380437); + Wr(LDIM_STTS_HIST_SET_REGION, 0x780077f); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 9) { /* 4x3 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4560333); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800666); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } else if (resolution == 10) { /* 6x8 */ + data32 = Rd(LDIM_STTS_HIST_REGION_IDX); + Wr(LDIM_STTS_HIST_REGION_IDX, 0xfff0ffff & data32); + + Wr(LDIM_STTS_HIST_SET_REGION, 0x0010001); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2430167); + Wr(LDIM_STTS_HIST_SET_REGION, 0x2220180); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000350); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4000338); + Wr(LDIM_STTS_HIST_SET_REGION, 0x6000510); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4370410); + Wr(LDIM_STTS_HIST_SET_REGION, 0x77f0700); + Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x7800780); */ + /* Wr(LDIM_STTS_HIST_SET_REGION, 0x4380438); */ + } +} + +void ldim_stts_initial_txlx(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + Wr_reg(LDIM_STTS_CTRL0, 7 << 2); + ldim_set_matrix_ycbcr2rgb(); + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + + ldim_stts_set_region_txlx(0, blk_height, blk_width, + row_start, col_start, blk_hnum); +} + +void ldim_stts_initial_tl1(unsigned int pic_h, unsigned int pic_v, + unsigned int blk_vnum, unsigned int blk_hnum) +{ + unsigned int resolution, blk_height, blk_width; + unsigned int row_start, col_start; + + blk_vnum = (blk_vnum == 0) ? 1 : blk_vnum; + blk_hnum = (blk_hnum == 0) ? 1 : blk_hnum; + + resolution = (((pic_h - 1) & 0xffff) << 16) | ((pic_v - 1) & 0xffff); + /*Wr_reg(VDIN0_HIST_CTRL, 0x10d);*/ + + blk_height = (pic_v - 8) / blk_vnum; + blk_width = (pic_h - 8) / blk_hnum; + row_start = (pic_v - (blk_height * blk_vnum)) >> 1; + col_start = (pic_h - (blk_width * blk_hnum)) >> 1; + + ldim_stts_en(resolution, 0, 0, 1, 1, 1, 0); + ldim_set_matrix_ycbcr2rgb(); + /*0:di 1:vdin 2:null 3:postblend 4:vpp out 5:vd1 6:vd2 7:osd1*/ + Wr_reg_bits(LDIM_STTS_CTRL0, 3, 3, 3); + + ldim_stts_set_region_tl1(0, pic_v, pic_h, blk_height, blk_width, + row_start, col_start, blk_vnum, blk_hnum); +} + +static unsigned int invalid_val_cnt; +void ldim_stts_read_region(unsigned int nrow, unsigned int ncol) +{ + unsigned int i, j, k; + unsigned int data32; + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + + if (invalid_val_cnt > 0xfffffff) + invalid_val_cnt = 0; + + Wr(LDIM_STTS_HIST_REGION_IDX, Rd(LDIM_STTS_HIST_REGION_IDX) + & 0xffffc000); + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + + for (i = 0; i < nrow; i++) { + for (j = 0; j < ncol; j++) { + data32 = Rd(LDIM_STTS_HIST_START_RD_REGION); + for (k = 0; k < 17; k++) { + if (k == 16) { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->max_rgb[i * ncol + j] + = data32; + } else { + data32 = Rd(LDIM_STTS_HIST_READ_REGION); + ldim_drv->hist_matrix[i * ncol * 16 + + j * 16 + k] = data32; + } + if (!(data32 & 0x40000000)) + invalid_val_cnt++; + } + } + } +} + +/* VDIN_MATRIX_YUV601_RGB */ +/* -16 1.164 0 1.596 0 */ +/* -128 1.164 -0.391 -0.813 0 */ +/* -128 1.164 2.018 0 0 */ +/*{0x07c00600, 0x00000600, 0x04a80000, 0x066204a8, 0x1e701cbf, 0x04a80812, + * 0x00000000, 0x00000000, 0x00000000,}, + */ +void ldim_set_matrix_ycbcr2rgb(void) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); /* enable matrix */ + + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x07c00600); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x00000600); + Wr(LDIM_STTS_MATRIX_COEF00_01, 0x04a80000); + Wr(LDIM_STTS_MATRIX_COEF02_10, 0x066204a8); + Wr(LDIM_STTS_MATRIX_COEF11_12, 0x1e701cbf); + Wr(LDIM_STTS_MATRIX_COEF20_21, 0x04a80812); + Wr(LDIM_STTS_MATRIX_COEF22, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET0_1, 0x00000000); + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x00000000); +} + +void ldim_set_matrix_rgb2ycbcr(int mode) +{ + Wr_reg_bits(LDIM_STTS_CTRL0, 1, 2, 1); + if (mode == 0) {/*ycbcr not full range, 601 conversion*/ + Wr(LDIM_STTS_MATRIX_PRE_OFFSET0_1, 0x0); + Wr(LDIM_STTS_MATRIX_PRE_OFFSET2, 0x0); + /* 0.257 0.504 0.098 */ + /* -0.148 -0.291 0.439 */ + /* 0.439 -0.368 -0.071 */ + Wr(LDIM_STTS_MATRIX_COEF00_01, (0x107 << 16) | 0x204); + Wr(LDIM_STTS_MATRIX_COEF02_10, (0x64 << 16) | 0x1f68); + Wr(LDIM_STTS_MATRIX_COEF11_12, (0x1ed6 << 16) | 0x1c2); + Wr(LDIM_STTS_MATRIX_COEF20_21, (0x1c2 << 16) | 0x1e87); + Wr(LDIM_STTS_MATRIX_COEF22, 0x1fb7); + + Wr(LDIM_STTS_MATRIX_OFFSET2, 0x0200); + } else if (mode == 1) {/*ycbcr full range, 601 conversion*/ + /* todo */ + } +} + +void ldim_remap_update_txlx(struct LDReg_s *nPRM, + unsigned int avg_update_en, unsigned int matrix_update_en) +{ + unsigned int data; + + if (avg_update_en) { + /* LD_BKLIT_PARAM */ + data = LDIM_RD_32Bits(REG_LD_BKLIT_PARAM); + data = (data & (~0xfff)) | (nPRM->reg_BL_matrix_AVG & 0xfff); + LDIM_WR_32Bits(REG_LD_BKLIT_PARAM, data); + + /* compensate */ + data = LDIM_RD_32Bits(REG_LD_LIT_GAIN_COMP); + data = (data & (~0xfff)) | + (nPRM->reg_BL_matrix_Compensate & 0xfff); + LDIM_WR_32Bits(REG_LD_LIT_GAIN_COMP, data); + } + + if (matrix_update_en) { + data = nPRM->reg_LD_BLK_Vnum * nPRM->reg_LD_BLK_Hnum; + LDIM_Update_Matrix(nPRM->BL_matrix, data); + } +} diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h index 6fe28b425554..297dafa379c3 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ldim_reg.h @@ -23,8 +23,8 @@ #define ASSIST_SPARE8_REG1 0x1f58 /*gxtvbb new add*/ -#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_GCLK_CTRL0 0x1ac0 +#define LDIM_STTS_CTRL0 0x1ac1 #define LDIM_STTS_WIDTHM1_HEIGHTM1 0x1ac2 #define LDIM_STTS_MATRIX_COEF00_01 0x1ac3 #define LDIM_STTS_MATRIX_COEF02_10 0x1ac4 diff --git a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c index 4348321adf17..8efef8baaa2c 100644 --- a/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c +++ b/drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c @@ -48,7 +48,8 @@ static int ob3350_hw_init_on(void) ldim_drv->ldev_conf->en_gpio_on); mdelay(2); - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config)); ldim_drv->pinmux_ctrl(1); mdelay(20); @@ -62,7 +63,8 @@ static int ob3350_hw_init_off(void) ldim_gpio_set(ldim_drv->ldev_conf->en_gpio, ldim_drv->ldev_conf->en_gpio_off); ldim_drv->pinmux_ctrl(0); - ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config)); + ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config)); return 0; } @@ -89,12 +91,22 @@ static int ob3350_smr(unsigned short *buf, unsigned char len) level = buf[0]; val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX); - ldim_drv->ldev_conf->pwm_config.pwm_duty = val; - ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config)); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val; + ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config)); return 0; } +static void ob3350_dim_range_update(void) +{ + struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver(); + struct ldim_dev_config_s *ldim_dev; + + ldim_dev = ldim_drv->ldev_conf; + ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max; + ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min; +} + static int ob3350_power_on(void) { if (ob3350_on_flag) { @@ -138,7 +150,7 @@ static ssize_t ob3350_show(struct class *class, ldim_drv->ldev_conf->en_gpio_off, ldim_drv->ldev_conf->dim_max, ldim_drv->ldev_conf->dim_min, - ldim_drv->ldev_conf->pwm_config.pwm_duty); + ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty); } return ret; @@ -151,6 +163,12 @@ static struct class_attribute ob3350_class_attrs[] = { static int ob3350_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv) { + struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf; + + ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max; + ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min; + ldim_dev->dim_range_update = ob3350_dim_range_update; + ldim_drv->device_power_on = ob3350_power_on; ldim_drv->device_power_off = ob3350_power_off; ldim_drv->device_bri_update = ob3350_smr; diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c index bdbacf485d50..c28aacde8c83 100644 --- a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c +++ b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c @@ -606,7 +606,8 @@ static int bl_extern_config_from_dts(struct device_node *np, int index) BLEXERR("failed to get bl_extern_name\n"); strcpy(bl_extern->config.name, "none"); } else { - strcpy(bl_extern->config.name, str); + strncpy(bl_extern->config.name, str, BL_EXTERN_NAME_LEN_MAX); + bl_extern->config.name[BL_EXTERN_NAME_LEN_MAX - 1] = '\0'; } ret = of_property_read_u32(child, "type", &val); diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c index 2eb1233bcac4..7a17ce5500f7 100644 --- a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c +++ b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c @@ -94,7 +94,8 @@ static int bl_extern_i2c_config_from_dts(struct device *dev, BLEXERR("failed to get dev_name\n"); strcpy(i2c_dev->name, "none"); } else { - strcpy(i2c_dev->name, str); + strncpy(i2c_dev->name, str, sizeof(i2c_dev->name)); + i2c_dev->name[sizeof(i2c_dev->name) - 1] = '\0'; } return 0; diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c index c4391c05c46b..679d0ea2e4fa 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_common/hdmi_parameters.c @@ -2870,25 +2870,25 @@ struct hdmi_format_para *hdmi_get_fmt_paras(enum hdmi_vic vic) } /* -void debug_modeline(struct modeline_table tbl) -{ - pr_info("modeline - horpixels %d\n", tbl.horpixels); - pr_info("modeline - verpixels %d\n", tbl.verpixels); - pr_info("modeline - pixel_clock %d\n", tbl.pixel_clock); - pr_info("modeline - hor_freq %d\n", tbl.hor_freq); - pr_info("modeline - ver_freq %d\n", tbl.ver_freq); - pr_info("modeline - hdisp %d\n", tbl.hdisp); - pr_info("modeline - hsyncstart %d\n", tbl.hsyncstart); - pr_info("modeline - hsyncend %d\n", tbl.hsyncend); - pr_info("modeline - htotal %d\n", tbl.htotal); - pr_info("modeline - vdisp %d\n", tbl.vdisp); - pr_info("modeline - vsyncstart %d\n", tbl.vsyncstart); - pr_info("modeline - vsyncend %d\n", tbl.vsyncend); - pr_info("modeline - vtotal %d\n", tbl.vtotal); - pr_info("modeline - hsync_polarity %d\n", tbl.hsync_polarity); - pr_info("modeline - vsync_polarity %d\n", tbl.vsync_polarity); - pr_info("modeline - progress_mode %d\n", tbl.progress_mode); -} +* void debug_modeline(struct modeline_table tbl) +* { +* pr_info("modeline - horpixels %d\n", tbl.horpixels); +* pr_info("modeline - verpixels %d\n", tbl.verpixels); +* pr_info("modeline - pixel_clock %d\n", tbl.pixel_clock); +* pr_info("modeline - hor_freq %d\n", tbl.hor_freq); +* pr_info("modeline - ver_freq %d\n", tbl.ver_freq); +* pr_info("modeline - hdisp %d\n", tbl.hdisp); +* pr_info("modeline - hsyncstart %d\n", tbl.hsyncstart); +* pr_info("modeline - hsyncend %d\n", tbl.hsyncend); +* pr_info("modeline - htotal %d\n", tbl.htotal); +* pr_info("modeline - vdisp %d\n", tbl.vdisp); +* pr_info("modeline - vsyncstart %d\n", tbl.vsyncstart); +* pr_info("modeline - vsyncend %d\n", tbl.vsyncend); +* pr_info("modeline - vtotal %d\n", tbl.vtotal); +* pr_info("modeline - hsync_polarity %d\n", tbl.hsync_polarity); +* pr_info("modeline - vsync_polarity %d\n", tbl.vsync_polarity); +* pr_info("modeline - progress_mode %d\n", tbl.progress_mode); +* } */ void debug_hdmi_fmt_param(struct hdmi_format_para param) diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c index e43210ddd90b..e008025fecb3 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_edid.c @@ -867,14 +867,9 @@ static void Edid_ParsingVendSpec(struct rx_cap *prxcap, unsigned char *dat = buf; unsigned char pos = 0; unsigned int ieeeoui = 0; + u8 length = 0; - memset(dv, 0, sizeof(struct dv_info)); - memset(hdr10_plus, 0, sizeof(struct hdr10_plus_info)); - - dv->block_flag = CORRECT; - dv->length = dat[pos] & 0x1f; - hdr10_plus->length = dat[pos] & 0x1f; - memcpy(dv->rawdata, dat, dv->length + 1); + length = dat[pos] & 0x1f; pos++; if (dat[pos] != 1) { @@ -887,9 +882,12 @@ static void Edid_ParsingVendSpec(struct rx_cap *prxcap, ieeeoui = dat[pos++]; ieeeoui += dat[pos++] << 8; ieeeoui += dat[pos++] << 16; + pr_info("Edid_ParsingVendSpec:ieeeoui=0x%x,len=%u\n", ieeeoui, length); /*HDR10+ use vsvdb*/ if (ieeeoui == HDR10_PLUS_IEEE_OUI) { + memset(hdr10_plus, 0, sizeof(struct hdr10_plus_info)); + hdr10_plus->length = length; hdr10_plus->ieeeoui = ieeeoui; hdr10_plus->application_version = dat[pos] & 0x3; pos++; @@ -900,6 +898,12 @@ static void Edid_ParsingVendSpec(struct rx_cap *prxcap, dv->block_flag = ERROR_OUI; return; } + +/* it is a Dovi block*/ + memset(dv, 0, sizeof(struct dv_info)); + dv->block_flag = CORRECT; + dv->length = length; + memcpy(dv->rawdata, dat, dv->length + 1); dv->ieeeoui = ieeeoui; dv->ver = (dat[pos] >> 5) & 0x7; if ((dv->ver) > 2) { diff --git a/drivers/amlogic/media/vout/vout_serve/vout2_serve.c b/drivers/amlogic/media/vout/vout_serve/vout2_serve.c index 05bc9f2999e4..2f2a2c1c1a12 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout2_serve.c +++ b/drivers/amlogic/media/vout/vout_serve/vout2_serve.c @@ -346,16 +346,22 @@ static void set_vout2_axis(char *para) int parsed[MAX_NUMBER_PARA] = {}; /* parse window para */ - if (parse_para(para, 8, parsed) >= 4) - memcpy(pt, parsed, sizeof(struct disp_rect_s) * OSD_COUNT); + if (parse_para(para, 8, parsed) >= 4) { + pt = &disp_rect[0].x; + memcpy(pt, &parsed[0], sizeof(struct disp_rect_s)); + pt = &disp_rect[1].x; + memcpy(pt, &parsed[4], sizeof(struct disp_rect_s)); + } /* if ((count >= 4) && (count < 8)) * disp_rect[1] = disp_rect[0]; */ VOUTPR("vout2: osd0=> x:%d,y:%d,w:%d,h:%d\n" "osd1=> x:%d,y:%d,w:%d,h:%d\n", - *pt, *(pt + 1), *(pt + 2), *(pt + 3), - *(pt + 4), *(pt + 5), *(pt + 6), *(pt + 7)); + disp_rect[0].x, disp_rect[0].y, + disp_rect[0].w, disp_rect[0].h, + disp_rect[1].x, disp_rect[1].y, + disp_rect[1].w, disp_rect[1].h); vout2_notifier_call_chain(VOUT_EVENT_OSD_DISP_AXIS, &disp_rect[0]); } diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.c b/drivers/amlogic/media/vout/vout_serve/vout_func.c index c8661b355196..eae62401d0b8 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.c +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.c @@ -22,11 +22,11 @@ #include /* Amlogic Headers */ -#include #include /* Local Headers */ #include "vout_func.h" +#include "vout_reg.h" static DEFINE_MUTEX(vout_mutex); @@ -111,24 +111,6 @@ struct vout_module_s *vout_func_get_vout2_module(void) EXPORT_SYMBOL(vout_func_get_vout2_module); #endif -static unsigned int vout_func_vcbus_read(unsigned int _reg) -{ - return aml_read_vcbus(_reg); -}; - -static void vout_func_vcbus_write(unsigned int _reg, unsigned int _value) -{ - aml_write_vcbus(_reg, _value); -}; - -static void vout_func_vcbus_setb(unsigned int _reg, unsigned int _value, - unsigned int _start, unsigned int _len) -{ - vout_func_vcbus_write(_reg, ((vout_func_vcbus_read(_reg) & - ~(((1L << (_len))-1) << (_start))) | - (((_value)&((1L<<(_len))-1)) << (_start)))); -} - static inline int vout_func_check_state(int index, unsigned int state, struct vout_server_s *p_server) { @@ -239,11 +221,11 @@ void vout_func_update_viu(int index) } if (mux_bit < 0xff) { - vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, + vout_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, mux_sel, mux_bit, 2); } if (clk_bit < 0xff) - vout_func_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1); + vout_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1); #if 0 VOUTPR("%s: %d, mux_sel=%d, clk_sel=%d\n", diff --git a/drivers/amlogic/media/vout/vout_serve/vout_func.h b/drivers/amlogic/media/vout/vout_serve/vout_func.h index 5997077730ca..5218a6c44c30 100644 --- a/drivers/amlogic/media/vout/vout_serve/vout_func.h +++ b/drivers/amlogic/media/vout/vout_serve/vout_func.h @@ -36,6 +36,7 @@ #define VPU_VENCX_CLK_CTRL 0x2785 #define VPP_POSTBLEND_H_SIZE 0x1d21 #define VPP2_POSTBLEND_H_SIZE 0x1921 +#define VPP_WRBAK_CTRL 0x1df9 struct vout_cdev_s { dev_t devno; diff --git a/drivers/amlogic/media/vout/vout_serve/vout_reg.h b/drivers/amlogic/media/vout/vout_serve/vout_reg.h new file mode 100644 index 000000000000..54c265fb507d --- /dev/null +++ b/drivers/amlogic/media/vout/vout_serve/vout_reg.h @@ -0,0 +1,227 @@ +/* + * drivers/amlogic/media/vout/vout_serve/vout_reg.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _VOUT_REG_H_ +#define _VOUT_REG_H_ +#include + +/* [3: 2] cntl_viu2_sel_venc: + * 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. + * [1: 0] cntl_viu1_sel_venc: + * 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. + */ +#define VPU_VIU_VENC_MUX_CTRL 0x271a +/* [2] Enci_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm + * [1] Encl_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm + * [0] Encp_afifo_clk: 0: cts_vpu_clk_tm 1: cts_vpu_clkc_tm + */ +#define VPU_VENCX_CLK_CTRL 0x2785 + +#define VPP_POSTBLEND_H_SIZE 0x1d21 +#define VPP2_POSTBLEND_H_SIZE 0x1921 +#define VPP_WRBAK_CTRL 0x1df9 + +/* ENCL registers */ +#define ENCL_VIDEO_EN 0x1ca0 +#define ENCL_VIDEO_Y_SCL 0x1ca1 +#define ENCL_VIDEO_PB_SCL 0x1ca2 +#define ENCL_VIDEO_PR_SCL 0x1ca3 +#define ENCL_VIDEO_Y_OFFST 0x1ca4 +#define ENCL_VIDEO_PB_OFFST 0x1ca5 +#define ENCL_VIDEO_PR_OFFST 0x1ca6 +/* ----- Video mode */ +#define ENCL_VIDEO_MODE 0x1ca7 +#define ENCL_VIDEO_MODE_ADV 0x1ca8 +/* --------------- Debug pins */ +#define ENCL_DBG_PX_RST 0x1ca9 +#define ENCL_DBG_LN_RST 0x1caa +#define ENCL_DBG_PX_INT 0x1cab +#define ENCL_DBG_LN_INT 0x1cac +/* ----------- Video Advanced setting */ +#define ENCL_VIDEO_YFP1_HTIME 0x1cad +#define ENCL_VIDEO_YFP2_HTIME 0x1cae +#define ENCL_VIDEO_YC_DLY 0x1caf +#define ENCL_VIDEO_MAX_PXCNT 0x1cb0 +#define ENCL_VIDEO_HAVON_END 0x1cb1 +#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2 +#define ENCL_VIDEO_VAVON_ELINE 0x1cb3 +#define ENCL_VIDEO_VAVON_BLINE 0x1cb4 +#define ENCL_VIDEO_HSO_BEGIN 0x1cb5 +#define ENCL_VIDEO_HSO_END 0x1cb6 +#define ENCL_VIDEO_VSO_BEGIN 0x1cb7 +#define ENCL_VIDEO_VSO_END 0x1cb8 +#define ENCL_VIDEO_VSO_BLINE 0x1cb9 +#define ENCL_VIDEO_VSO_ELINE 0x1cba +#define ENCL_VIDEO_MAX_LNCNT 0x1cbb +#define ENCL_VIDEO_BLANKY_VAL 0x1cbc +#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd +#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe +#define ENCL_VIDEO_HOFFST 0x1cbf +#define ENCL_VIDEO_VOFFST 0x1cc0 +#define ENCL_VIDEO_RGB_CTRL 0x1cc1 +#define ENCL_VIDEO_FILT_CTRL 0x1cc2 +#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3 +#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4 +#define ENCL_VIDEO_MATRIX_CB 0x1cc5 +#define ENCL_VIDEO_MATRIX_CR 0x1cc6 +#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7 +#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8 +#define ENCL_DACSEL_0 0x1cc9 +#define ENCL_DACSEL_1 0x1cca + +/* ENCP registers */ +#define ENCP_VIDEO_EN 0x1b80 +#define ENCP_VIDEO_SYNC_MODE 0x1b81 +#define ENCP_MACV_EN 0x1b82 +#define ENCP_VIDEO_Y_SCL 0x1b83 +#define ENCP_VIDEO_PB_SCL 0x1b84 +#define ENCP_VIDEO_PR_SCL 0x1b85 +#define ENCP_VIDEO_SYNC_SCL 0x1b86 +#define ENCP_VIDEO_MACV_SCL 0x1b87 +#define ENCP_VIDEO_Y_OFFST 0x1b88 +#define ENCP_VIDEO_PB_OFFST 0x1b89 +#define ENCP_VIDEO_PR_OFFST 0x1b8a +#define ENCP_VIDEO_SYNC_OFFST 0x1b8b +#define ENCP_VIDEO_MACV_OFFST 0x1b8c +//----- Video mode +#define ENCP_VIDEO_MODE 0x1b8d +#define ENCP_VIDEO_MODE_ADV 0x1b8e +//--------------- Debug pins +#define ENCP_DBG_PX_RST 0x1b90 +#define ENCP_DBG_LN_RST 0x1b91 +#define ENCP_DBG_PX_INT 0x1b92 +#define ENCP_DBG_LN_INT 0x1b93 +//----------- Video Advanced setting +#define ENCP_VIDEO_YFP1_HTIME 0x1b94 +#define ENCP_VIDEO_YFP2_HTIME 0x1b95 +#define ENCP_VIDEO_YC_DLY 0x1b96 +#define ENCP_VIDEO_MAX_PXCNT 0x1b97 +#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98 +#define ENCP_VIDEO_HSPULS_END 0x1b99 +#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a +#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b +#define ENCP_VIDEO_VSPULS_END 0x1b9c +#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d +#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e +#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f +#define ENCP_VIDEO_EQPULS_END 0x1ba0 +#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1 +#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2 +#define ENCP_VIDEO_HAVON_END 0x1ba3 +#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4 +#define ENCP_VIDEO_VAVON_ELINE 0x1baf +#define ENCP_VIDEO_VAVON_BLINE 0x1ba6 +#define ENCP_VIDEO_HSO_BEGIN 0x1ba7 +#define ENCP_VIDEO_HSO_END 0x1ba8 +#define ENCP_VIDEO_VSO_BEGIN 0x1ba9 +#define ENCP_VIDEO_VSO_END 0x1baa +#define ENCP_VIDEO_VSO_BLINE 0x1bab +#define ENCP_VIDEO_VSO_ELINE 0x1bac +#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad +#define ENCP_VIDEO_MAX_LNCNT 0x1bae +#define ENCP_VIDEO_SY_VAL 0x1bb0 +#define ENCP_VIDEO_SY2_VAL 0x1bb1 +#define ENCP_VIDEO_BLANKY_VAL 0x1bb2 +#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3 +#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4 +#define ENCP_VIDEO_HOFFST 0x1bb5 +#define ENCP_VIDEO_VOFFST 0x1bb6 +#define ENCP_VIDEO_RGB_CTRL 0x1bb7 +#define ENCP_VIDEO_FILT_CTRL 0x1bb8 +#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9 +#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba +#define ENCP_VIDEO_MATRIX_CB 0x1bbb +#define ENCP_VIDEO_MATRIX_CR 0x1bbc +#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd + +/* HIU */ +#define HHI_VIID_CLK_DIV 0x4a +#define DAC0_CLK_SEL 28 +#define DAC1_CLK_SEL 24 +#define DAC2_CLK_SEL 20 +#define VCLK2_XD_RST 17 +#define VCLK2_XD_EN 16 +#define ENCL_CLK_SEL 12 +#define VCLK2_XD 0 + +#define HHI_VID_CLK_DIV 0x59 +#define ENCI_CLK_SEL 28 +#define ENCP_CLK_SEL 24 +#define ENCT_CLK_SEL 20 +#define VCLK_XD_RST 17 +#define VCLK_XD_EN 16 +#define ENCL_CLK_SEL 12 +#define VCLK_XD1 8 +#define VCLK_XD0 0 + +#define HHI_VID_CLK_CNTL2 0x65 +#define HDMI_TX_PIXEL_GATE_VCLK 5 +#define VDAC_GATE_VCLK 4 +#define ENCL_GATE_VCLK 3 +#define ENCP_GATE_VCLK 2 +#define ENCT_GATE_VCLK 1 +#define ENCI_GATE_VCLK 0 + +static inline unsigned int vout_vcbus_read(unsigned int _reg) +{ + return aml_read_vcbus(_reg); +}; + +static inline void vout_vcbus_write(unsigned int _reg, unsigned int _value) +{ + aml_write_vcbus(_reg, _value); +}; + +static inline void vout_vcbus_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + vout_vcbus_write(_reg, ((vout_vcbus_read(_reg) & + ~(((1L << (_len)) - 1) << (_start))) | + (((_value) & ((1L << (_len)) - 1)) << (_start)))); +} + +static inline unsigned int vout_vcbus_getb(unsigned int reg, + unsigned int _start, unsigned int _len) +{ + return (vout_vcbus_read(reg) >> _start) & ((1L << _len) - 1); +} + +static inline unsigned int vout_hiu_read(unsigned int _reg) +{ + return aml_read_hiubus(_reg); +}; + +static inline void vout_hiu_write(unsigned int _reg, unsigned int _value) +{ + aml_write_hiubus(_reg, _value); +}; + +static inline void vout_hiu_setb(unsigned int _reg, unsigned int _value, + unsigned int _start, unsigned int _len) +{ + vout_hiu_write(_reg, ((vout_hiu_read(_reg) & + ~(((1L << (_len)) - 1) << (_start))) | + (((_value) & ((1L << (_len)) - 1)) << (_start)))); +} + +static inline unsigned int vout_hiu_getb(unsigned int _reg, + unsigned int _start, unsigned int _len) +{ + return (vout_hiu_read(_reg) >> (_start)) & ((1L << (_len)) - 1); +} + +#endif diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c index 52ef8833f6b6..aed82f81f824 100644 --- a/drivers/media/v4l2-core/videobuf2-v4l2.c +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c @@ -204,7 +204,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->timestamp = ns_to_timeval(vb->timestamp); b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; - b->reserved2 = 0; + b->reserved2 = vbuf->private; b->reserved = 0; if (q->is_multiplanar) { diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 3d288d220261..4c1d59eab571 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -534,7 +534,6 @@ static int ramoops_parse_dt(struct platform_device *pdev, #define parse_size(name, field) { \ ret = ramoops_parse_dt_size(pdev, name, &value); \ - pr_info(" <%s> %s %d", __func__, name, value); \ if (ret < 0) \ return ret; \ field = value; \ diff --git a/include/linux/amlogic/media/frame_sync/tsync.h b/include/linux/amlogic/media/frame_sync/tsync.h index ddb697728a27..6d0b1ae3d5e4 100644 --- a/include/linux/amlogic/media/frame_sync/tsync.h +++ b/include/linux/amlogic/media/frame_sync/tsync.h @@ -157,9 +157,18 @@ extern int tsync_set_av_threshold_max(int max); extern void set_pts_realign(void); +extern int tsync_set_tunnel_mode(int mode); + +extern int tsync_get_tunnel_mode(void); + extern void timestamp_set_pcrlatency(u32 latency); extern u32 timestamp_get_pcrlatency(void); extern bool tsync_check_vpts_discontinuity(unsigned int vpts); +extern void timestamp_clac_pts_latency(u8 type, u32 pts); +extern u32 timestamp_get_pts_latency(u8 type); +extern void timestamp_clean_pts_latency(u8 type); +extern int tsync_get_vpts_adjust(void); +void tsync_set_av_state(u8 type, int state); static inline u32 tsync_vpts_discontinuity_margin(void) { diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 468c1c85579e..62fe3c26ae17 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -53,6 +53,8 @@ #define VIDTYPE_RGB_444 0x20000000 #define VIDTYPE_V4L_EOS 0x80000000 +/* 2019-04-22 Suggestions from brian.zhu*/ +#define VIDTYPE_DI_PW 0x40000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 #define DISP_RATIO_FORCE_FULL_STRETCH 0x20000000 @@ -481,6 +483,7 @@ struct vframe_s { * bit 0: flm32 *****************/ u32 di_pulldown; + u32 di_gmv; } /*vframe_t */; #if 0 diff --git a/kernel/cpu.c b/kernel/cpu.c index dd07bf38bfc3..350ebd819391 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -910,10 +910,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, if (!cpu_present(cpu)) return -EINVAL; -#ifdef CONFIG_AMLOGIC_MODIFY - /* avoid dead lock */ - workqueue_offline_cpu(cpu); -#endif cpu_hotplug_begin(); cpuhp_tasks_frozen = tasks_frozen; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 853dced7fb26..71050f5841a3 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -314,11 +314,6 @@ static int suspend_prepare(suspend_state_t state) if (!error) return 0; -#ifdef CONFIG_AMLOGIC_MODIFY - /* Allow device probing and trigger re-probing of deferred devices */ - device_unblock_probing(); -#endif - suspend_stats.failed_freeze++; dpm_save_failed_step(SUSPEND_FREEZE); Finish: diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b7c2012d4256..35cfccbede3d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1864,7 +1864,7 @@ static void __trace_find_cmdline(int pid, char comm[]) map = savedcmd->map_pid_to_cmdline[pid]; if (map != NO_CMDLINE_MAP) - strlcpy(comm, get_saved_cmdlines(map), TASK_COMM_LEN-1); + strcpy(comm, get_saved_cmdlines(map)); else strcpy(comm, "<...>"); } diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 96086b7c490c..592820472419 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -360,6 +360,21 @@ static void purge_vmap_area_lazy(void); static BLOCKING_NOTIFIER_HEAD(vmap_notify_list); +#ifdef CONFIG_AMLOGIC_MODIFY +static void dump_vmalloc(void) +{ + struct vmap_area *va, *next; + + spin_lock(&vmap_area_lock); + list_for_each_entry_safe(va, next, &vmap_area_list, list) { + pr_info("%s, va:%lx-%lx, size:%08ld KB, alloc:%pf\n", + __func__, va->va_start, va->va_end, + (va->va_end - va->va_start) >> 10, va->vm->caller); + } + spin_unlock(&vmap_area_lock); +} +#endif + /* * Allocate a region of KVA of the specified size and alignment, within the * vstart and vend. @@ -496,6 +511,9 @@ overflow: } } +#ifdef CONFIG_AMLOGIC_MODIFY + dump_vmalloc(); +#endif if (printk_ratelimit()) pr_warn("vmap allocation for size %lu failed: use vmalloc= to increase size\n", size); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 1811f8e7ddf4..1fc076420d1e 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -431,8 +431,8 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } -static void hidp_process_report(struct hidp_session *session, int type, - const u8 *data, unsigned int len, int intr) +static void hidp_process_report(struct hidp_session *session, + int type, const u8 *data, int len, int intr) { if (len > HID_MAX_BUFFER_SIZE) len = HID_MAX_BUFFER_SIZE; diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index 43e2d8f8b7e1..f58888ce5674 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -533,6 +533,10 @@ static int new_resample_init(struct audioresample *p_resample) return 0; } +static struct resample_chipinfo axg_resample_chipinfo = { + .resample_version = 0, +}; + static struct resample_chipinfo g12a_resample_chipinfo = { .dividor_fn = true, .resample_version = 0, @@ -569,6 +573,7 @@ static struct resample_chipinfo sm1_resample_b_chipinfo = { static const struct of_device_id resample_device_id[] = { { .compatible = "amlogic, axg-resample", + .data = &axg_resample_chipinfo, }, { .compatible = "amlogic, g12a-resample", @@ -615,11 +620,12 @@ static int resample_platform_probe(struct platform_device *pdev) /* match data */ p_chipinfo = (struct resample_chipinfo *) of_device_get_match_data(dev); - if (!p_chipinfo) + if (!p_chipinfo) { dev_warn_once(dev, "check whether to update resample chipinfo\n"); - else - p_resample->id = p_chipinfo->id; + return -EINVAL; + } + p_resample->id = p_chipinfo->id; p_resample->chipinfo = p_chipinfo; if (p_chipinfo->id == 0) {