From d37f84a2e1735ea30f54be59814fc03770bbc4a3 Mon Sep 17 00:00:00 2001 From: "caiyi.xu" Date: Mon, 4 Mar 2024 02:38:17 +0000 Subject: [PATCH] dtv_demod: rebuild dtmb driver (v3.25.32) [1/1] PD#SWPL-158422 Problem: 1.signal locking and channel scanning are slow 2.signal locking process is unstable Solution: rebuild driver 1.signal locking speed is increased by more than 60% 2.signal locking timeout speed is increased by more than 40% ~ 90% 3.the channel scanning speed is increased by more than 35% 4.improve the stability of signal locking 5.reduced sensitivity to transient abnormalities in the signal Verify: T5M, T950s Change-Id: Ie9b0f522478222e0076fced126a966c2f951cc1c Signed-off-by: caiyi.xu --- drivers/media/dtv_demod/amlfrontend.c | 15 +- drivers/media/dtv_demod/dtmb/dtmb_frontend.c | 159 +++++++++++++++++- drivers/media/dtv_demod/dtmb/dtmb_frontend.h | 4 + drivers/media/dtv_demod/dtmb/dtmb_func.c | 45 +++++ drivers/media/dtv_demod/include/amlfrontend.h | 6 +- drivers/media/dtv_demod/include/demod_func.h | 1 + 6 files changed, 225 insertions(+), 5 deletions(-) diff --git a/drivers/media/dtv_demod/amlfrontend.c b/drivers/media/dtv_demod/amlfrontend.c index 8059a8011..c94559400 100644 --- a/drivers/media/dtv_demod/amlfrontend.c +++ b/drivers/media/dtv_demod/amlfrontend.c @@ -80,6 +80,11 @@ #include #include +//dtmb +unsigned char dtmb_new_driver = 1; +MODULE_PARM_DESC(dtmb_new_driver, "\n\t\t use dtmb new driver to work"); +module_param(dtmb_new_driver, byte, 0644); + //dvb-c MODULE_PARM_DESC(dvbc_new_driver, "\n\t\t use dvbc new driver to work"); static unsigned char dvbc_new_driver; @@ -2338,7 +2343,10 @@ static int aml_dtvdm_read_status(struct dvb_frontend *fe, break; #ifdef AML_DEMOD_SUPPORT_DTMB case SYS_DTMB: - ret = gxtv_demod_dtmb_read_status(fe, status); + if (dtmb_new_driver) + *status = demod->last_status; + else + ret = gxtv_demod_dtmb_read_status(fe, status); break; #endif default: @@ -2759,7 +2767,10 @@ static int aml_dtvdm_tune(struct dvb_frontend *fe, bool re_tune, #endif #ifdef AML_DEMOD_SUPPORT_DTMB case SYS_DTMB: - ret = gxtv_demod_dtmb_tune(fe, re_tune, mode_flags, delay, status); + if (dtmb_new_driver) + ret = dtmb_tune(fe, re_tune, mode_flags, delay, status); + else + ret = gxtv_demod_dtmb_tune(fe, re_tune, mode_flags, delay, status); break; #endif default: diff --git a/drivers/media/dtv_demod/dtmb/dtmb_frontend.c b/drivers/media/dtv_demod/dtmb/dtmb_frontend.c index a139f3b0b..ba8a3b478 100644 --- a/drivers/media/dtv_demod/dtmb/dtmb_frontend.c +++ b/drivers/media/dtv_demod/dtmb/dtmb_frontend.c @@ -40,6 +40,20 @@ #include "addr_dtmb_top.h" #include +#define DTMB_TIME_CHECK_SIGNAL 150 + +static unsigned int dtmb_check_signal_time = DTMB_TIME_CHECK_SIGNAL; +MODULE_PARM_DESC(dtmb_check_signal_time, "\n\t\t dtmb check signal time"); +module_param(dtmb_check_signal_time, int, 0644); + +static unsigned int dtmb_lock_continuous_cnt = 1; +MODULE_PARM_DESC(dtmb_lock_continuous_cnt, "\n\t\t dtmb lock signal continuous counting"); +module_param(dtmb_lock_continuous_cnt, int, 0644); + +static unsigned int dtmb_lost_continuous_cnt = 15; +MODULE_PARM_DESC(dtmb_lost_continuous_cnt, "\n\t\t dtmb lost signal continuous counting"); +module_param(dtmb_lost_continuous_cnt, int, 0644); + void gxtv_demod_dtmb_release(struct dvb_frontend *fe) { } @@ -407,7 +421,8 @@ int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe) #endif tuner_set_params(fe); - msleep(100); + if (!dtmb_new_driver) + msleep(100); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { if (fe->ops.tuner_ops.get_if_frequency) @@ -490,6 +505,148 @@ int gxtv_demod_dtmb_tune(struct dvb_frontend *fe, bool re_tune, return ret; } +static void dtmb_read_status(struct dvb_frontend *fe, enum fe_status *status, unsigned int re_tune, + unsigned int *delay) +{ + int i, lock;//0:none;1:lock;-1:lost + s16 strength; + unsigned int fsm_state, val, cur_time; + struct aml_dtvdemod *demod = (struct aml_dtvdemod *)fe->demodulator_priv; + static int lock_status; + static int has_signal; + //Threshold value of times of continuous lock and lost + int lock_continuous_cnt = dtmb_lock_continuous_cnt > 1 ? dtmb_lock_continuous_cnt : 1; + int lost_continuous_cnt = dtmb_lost_continuous_cnt > 1 ? dtmb_lost_continuous_cnt : 1; + int check_signal_time = dtmb_check_signal_time > 1 ? dtmb_check_signal_time : + DTMB_TIME_CHECK_SIGNAL; + int tuner_strength_threshold = THRD_TUNER_STRENGTH_DTMB; + + cur_time = jiffies_to_msecs(jiffies); + + if (re_tune) { + lock_status = 0; + has_signal = 0; + demod->time_start = cur_time; + *status = 0; + demod->last_status = 0; + dtmb_bch_check_new(fe, true); + return; + } + + demod->time_passed = jiffies_to_msecs(jiffies) - demod->time_start; + + gxtv_demod_dtmb_read_signal_strength(fe, &strength); + if (strength < tuner_strength_threshold && demod->time_passed < check_signal_time) { + *status = FE_TIMEDOUT; + PR_DTMB("%s: tuner strength [%d] no signal(%d).\n", + __func__, strength, tuner_strength_threshold); + + goto finish; + } + + fsm_state = dtmb_read_reg(DTMB_TOP_CTRL_FSM_STATE0); + for (i = 0; i < 8; i++) + if (((fsm_state >> (i * 4)) & 0xf) > 4) + has_signal = 0x1; + + val = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR); + if (is_meson_gxtvbb_cpu()) + demod->real_para.snr = convert_snr(val & 0xfff) * 10; + else + demod->real_para.snr = convert_snr(val & 0x3fff) * 10; + PR_DTMB("fsm=0x%x, r_snr=0x%x, snr=%d dB*10, time_passed=%d\n", + fsm_state, val, demod->real_para.snr, demod->time_passed); + if (val & 0x4000) { + lock = 1; + has_signal = 1; + dtmb_bch_check_new(fe, false); + *delay = 100; + } else { + if (demod->time_passed <= check_signal_time || + (demod->time_passed <= TIMEOUT_DTMB && has_signal)) { + lock = 0; + } else { + lock = -1; + + if (lock_status == 0) {//not dtmb signal + *status = FE_TIMEDOUT; + PR_ATSC("not dtmb signal\n"); + + goto finish; + } + } + } + + //The status is updated only when the status continuously reaches the threshold of times + if (lock == -1) { + if (lock_status >= 0) { + lock_status = -1; + PR_ATSC("==> lost signal first\n"); + } else if (lock_status <= -lost_continuous_cnt) { + lock_status = -lost_continuous_cnt; + PR_ATSC("==> lost signal continue\n"); + } else { + lock_status--; + PR_ATSC("==> lost signal times%d\n", lock_status); + } + + if (lock_status <= -lost_continuous_cnt) + *status = FE_TIMEDOUT; + else + *status = 0; + } else if (lock == 1) { + if (lock_status <= 0) { + lock_status = 1; + PR_ATSC("==> lock signal first\n"); + } else if (lock_status >= lock_continuous_cnt) { + lock_status = lock_continuous_cnt; + PR_ATSC("==> lock signal continue\n"); + } else { + lock_status++; + PR_ATSC("==> lock signal times:%d\n", lock_status); + } + + if (lock_status >= lock_continuous_cnt) + *status = FE_HAS_LOCK | FE_HAS_SIGNAL | + FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; + else + *status = 0; + } else { + *status = 0; + } + +finish: + if (demod->last_status != *status && *status != 0) { + PR_INFO("!! >> %s << !!, freq=%d, time_passed=%d\n", *status == FE_TIMEDOUT ? + "UNLOCK" : "LOCK", fe->dtv_property_cache.frequency, demod->time_passed); + demod->last_status = *status; + } +} + +int dtmb_tune(struct dvb_frontend *fe, bool re_tune, + unsigned int mode_flags, unsigned int *delay, enum fe_status *status) +{ + struct aml_dtvdemod *demod = (struct aml_dtvdemod *)fe->demodulator_priv; + + *delay = HZ / 20; + + if (re_tune) { + PR_INFO("%s [id %d]: re_tune.\n", __func__, demod->id); + demod->en_detect = 1; + + gxtv_demod_dtmb_set_frontend(fe); + dtmb_read_status(fe, status, re_tune, delay); + + *status = 0; + + return 0; + } + + dtmb_read_status(fe, status, re_tune, delay); + + return 0; +} + int Gxtv_Demod_Dtmb_Init(struct aml_dtvdemod *demod) { int ret = 0; diff --git a/drivers/media/dtv_demod/dtmb/dtmb_frontend.h b/drivers/media/dtv_demod/dtmb/dtmb_frontend.h index 2c2ffe8dc..fe76a0c4a 100644 --- a/drivers/media/dtv_demod/dtmb/dtmb_frontend.h +++ b/drivers/media/dtv_demod/dtmb/dtmb_frontend.h @@ -21,6 +21,8 @@ #define DTMBM_POLL_DELAY_NO_SIGNAL (120) #define DTMBM_POLL_DELAY_HAVE_SIGNAL (100) +extern unsigned char dtmb_new_driver; + void dtmb_save_status(struct aml_dtvdemod *demod, unsigned int s); void dtmb_poll_start(struct aml_dtvdemod *demod); void dtmb_poll_stop(struct aml_dtvdemod *demod); @@ -42,6 +44,8 @@ int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe); int gxtv_demod_dtmb_get_frontend(struct dvb_frontend *fe); int gxtv_demod_dtmb_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, enum fe_status *status); +int dtmb_tune(struct dvb_frontend *fe, bool re_tune, + unsigned int mode_flags, unsigned int *delay, enum fe_status *status); int Gxtv_Demod_Dtmb_Init(struct aml_dtvdemod *demod); int amdemod_stat_dtmb_islock(struct aml_dtvdemod *demod, enum fe_delivery_system delsys); diff --git a/drivers/media/dtv_demod/dtmb/dtmb_func.c b/drivers/media/dtv_demod/dtmb/dtmb_func.c index 6dc5dbc07..a306ecbb2 100644 --- a/drivers/media/dtv_demod/dtmb/dtmb_func.c +++ b/drivers/media/dtv_demod/dtmb/dtmb_func.c @@ -457,6 +457,51 @@ int dtmb_bch_check(struct dvb_frontend *fe) return 0; } +void dtmb_bch_check_new(struct dvb_frontend *fe, bool reset) +{ + struct aml_dtvdemod *demod = (struct aml_dtvdemod *)fe->demodulator_priv; + struct amldtvdemod_device_s *devp = (struct amldtvdemod_device_s *)demod->priv; + int fec_bch; + static int last_fec_bch; + union DTMB_TOP_CTRL_SW_RST_BITS sw_rst; + unsigned int val; + + if (reset) { + last_fec_bch = -1; + return; + } + + fec_bch = dtmb_reg_r_bch(); + if (last_fec_bch != -1 && (fec_bch - last_fec_bch) > 50) { + PR_DTMB("fec lock, but bch add, need reset\n"); + if (devp->data->hw_ver == DTVDEMOD_HW_T3) { + val = dtmb_read_reg(0x7); + PR_INFO("dtmb set ddr\n"); + dtmb_write_reg(0x7, 0x6ffffd); + //dtmb_write_reg(0x47, 0xed33221); + dtmb_write_reg_bits(0x47, 0x1, 22, 1); + dtmb_write_reg_bits(0x47, 0x1, 23, 1); + msleep(20); + } + + sw_rst.b.ctrl_sw_rst = 1; + sw_rst.b.ctrl_sw_rst_noreg = 1; + dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); + + if (devp->data->hw_ver == DTVDEMOD_HW_T3) { + clear_ddr_bus_data(demod); + dtmb_write_reg(0x7, val); + dtmb_write_reg_bits(0x47, 0x0, 22, 1); + dtmb_write_reg_bits(0x47, 0x0, 23, 1); + } + + sw_rst.b.ctrl_sw_rst = 0; + sw_rst.b.ctrl_sw_rst_noreg = 0; + dtmb_write_reg(DTMB_TOP_CTRL_SW_RST, sw_rst.d32); + } + last_fec_bch = fec_bch; +} + int dtmb_constell_check(void) { int constell; diff --git a/drivers/media/dtv_demod/include/amlfrontend.h b/drivers/media/dtv_demod/include/amlfrontend.h index e93038cb5..95fb10d1d 100644 --- a/drivers/media/dtv_demod/include/amlfrontend.h +++ b/drivers/media/dtv_demod/include/amlfrontend.h @@ -156,6 +156,7 @@ /* V3.5.029 fix atsc-c signal strength issue */ /* V3.5.030 fix dvbt overflow when 6M 1/4 and other param */ /* V3.5.031 calibrate dvbc signal strength read from R842 */ +/* V3.5.032 rebuild dtmb driver */ /****************************************************/ /****************************************************************/ /* AMLDTVDEMOD_VER Description: */ @@ -172,8 +173,8 @@ /*->The last four digits indicate the release time */ /****************************************************************/ #define KERNEL_4_9_EN 1 -#define AMLDTVDEMOD_VER "V3.5.031" -#define DTVDEMOD_VER "2024/01/03: calibrate dvbc signal strength read from R842" +#define AMLDTVDEMOD_VER "V3.5.032" +#define DTVDEMOD_VER "2024/02/27: rebuild dtmb driver" #define AMLDTVDEMOD_T2_FW_VER "20231019_141000" #define DEMOD_DEVICE_NAME "dtvdemod" @@ -201,6 +202,7 @@ #ifdef AML_DEMOD_SUPPORT_DTMB #define THRD_TUNER_STRENGTH_DTMB (-100) +#define TIMEOUT_DTMB 2500 #endif #ifdef AML_DEMOD_SUPPORT_DVBC diff --git a/drivers/media/dtv_demod/include/demod_func.h b/drivers/media/dtv_demod/include/demod_func.h index 46ee0b3cd..3afda5a5c 100644 --- a/drivers/media/dtv_demod/include/demod_func.h +++ b/drivers/media/dtv_demod/include/demod_func.h @@ -755,6 +755,7 @@ void dtmb_reset(void); int dtmb_check_status_gxtv(struct dvb_frontend *fe); int dtmb_check_status_txl(struct dvb_frontend *fe); int dtmb_bch_check(struct dvb_frontend *fe); +void dtmb_bch_check_new(struct dvb_frontend *fe, bool reset); void dtmb_write_reg(unsigned int reg_addr, unsigned int reg_data); unsigned int dtmb_read_reg(unsigned int reg_addr); void dtmb_write_reg_bits(u32 addr, const u32 data, const u32 start, const u32 len);