18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci STB0899 Multistandard Frontend driver 48c2ecf20Sopenharmony_ci Copyright (C) Manu Abraham (abraham.manu@gmail.com) 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci Copyright (C) ST Microelectronics 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci*/ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bitops.h> 118c2ecf20Sopenharmony_ci#include "stb0899_drv.h" 128c2ecf20Sopenharmony_ci#include "stb0899_priv.h" 138c2ecf20Sopenharmony_ci#include "stb0899_reg.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic inline u32 stb0899_do_div(u64 n, u32 d) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci /* wrap do_div() for ease of use */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci do_div(n, d); 208c2ecf20Sopenharmony_ci return n; 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#if 0 248c2ecf20Sopenharmony_ci/* These functions are currently unused */ 258c2ecf20Sopenharmony_ci/* 268c2ecf20Sopenharmony_ci * stb0899_calc_srate 278c2ecf20Sopenharmony_ci * Compute symbol rate 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_cistatic u32 stb0899_calc_srate(u32 master_clk, u8 *sfr) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci u64 tmp; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* srate = (SFR * master_clk) >> 20 */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* sfr is of size 20 bit, stored with an offset of 4 bit */ 368c2ecf20Sopenharmony_ci tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2]; 378c2ecf20Sopenharmony_ci tmp &= ~0xf; 388c2ecf20Sopenharmony_ci tmp *= master_clk; 398c2ecf20Sopenharmony_ci tmp >>= 24; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci return tmp; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * stb0899_get_srate 468c2ecf20Sopenharmony_ci * Get the current symbol rate 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_cistatic u32 stb0899_get_srate(struct stb0899_state *state) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 518c2ecf20Sopenharmony_ci u8 sfr[3]; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_SFRH, sfr, 3); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return stb0899_calc_srate(internal->master_clk, sfr); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci#endif 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * stb0899_set_srate 618c2ecf20Sopenharmony_ci * Set symbol frequency 628c2ecf20Sopenharmony_ci * MasterClock: master clock frequency (hz) 638c2ecf20Sopenharmony_ci * SymbolRate: symbol rate (bauds) 648c2ecf20Sopenharmony_ci * return symbol frequency 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_cistatic u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci u32 tmp; 698c2ecf20Sopenharmony_ci u8 sfr[3]; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-->"); 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * in order to have the maximum precision, the symbol rate entered into 748c2ecf20Sopenharmony_ci * the chip is computed as the closest value of the "true value". 758c2ecf20Sopenharmony_ci * In this purpose, the symbol rate value is rounded (1 is added on the bit 768c2ecf20Sopenharmony_ci * below the LSB ) 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * srate = (SFR * master_clk) >> 20 798c2ecf20Sopenharmony_ci * <=> 808c2ecf20Sopenharmony_ci * SFR = srate << 20 / master_clk 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * rounded: 838c2ecf20Sopenharmony_ci * SFR = (srate << 21 + master_clk) / (2 * master_clk) 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * stored as 20 bit number with an offset of 4 bit: 868c2ecf20Sopenharmony_ci * sfr = SFR << 4; 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk); 908c2ecf20Sopenharmony_ci tmp <<= 4; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci sfr[0] = tmp >> 16; 938c2ecf20Sopenharmony_ci sfr[1] = tmp >> 8; 948c2ecf20Sopenharmony_ci sfr[2] = tmp; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_SFRH, sfr, 3); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return srate; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * stb0899_calc_derot_time 1038c2ecf20Sopenharmony_ci * Compute the amount of time needed by the derotator to lock 1048c2ecf20Sopenharmony_ci * SymbolRate: Symbol rate 1058c2ecf20Sopenharmony_ci * return: derotator time constant (ms) 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_cistatic long stb0899_calc_derot_time(long srate) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci if (srate > 0) 1108c2ecf20Sopenharmony_ci return (100000 / (srate / 1000)); 1118c2ecf20Sopenharmony_ci else 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci * stb0899_carr_width 1178c2ecf20Sopenharmony_ci * Compute the width of the carrier 1188c2ecf20Sopenharmony_ci * return: width of carrier (kHz or Mhz) 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_cilong stb0899_carr_width(struct stb0899_state *state) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return (internal->srate + (internal->srate * internal->rolloff) / 100); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* 1288c2ecf20Sopenharmony_ci * stb0899_first_subrange 1298c2ecf20Sopenharmony_ci * Compute the first subrange of the search 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_cistatic void stb0899_first_subrange(struct stb0899_state *state) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 1348c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 1358c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci int range = 0; 1388c2ecf20Sopenharmony_ci u32 bandwidth = 0; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (config->tuner_get_bandwidth) { 1418c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 1); 1428c2ecf20Sopenharmony_ci config->tuner_get_bandwidth(&state->frontend, &bandwidth); 1438c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 0); 1448c2ecf20Sopenharmony_ci range = bandwidth - stb0899_carr_width(state) / 2; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (range > 0) 1488c2ecf20Sopenharmony_ci internal->sub_range = min(internal->srch_range, range); 1498c2ecf20Sopenharmony_ci else 1508c2ecf20Sopenharmony_ci internal->sub_range = 0; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci internal->freq = params->freq; 1538c2ecf20Sopenharmony_ci internal->tuner_offst = 0L; 1548c2ecf20Sopenharmony_ci internal->sub_dir = 1; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci/* 1588c2ecf20Sopenharmony_ci * stb0899_check_tmg 1598c2ecf20Sopenharmony_ci * check for timing lock 1608c2ecf20Sopenharmony_ci * internal.Ttiming: time to wait for loop lock 1618c2ecf20Sopenharmony_ci */ 1628c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 1658c2ecf20Sopenharmony_ci int lock; 1668c2ecf20Sopenharmony_ci u8 reg; 1678c2ecf20Sopenharmony_ci s8 timing; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci msleep(internal->t_derot); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RTF, 0xf2); 1728c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TLIR); 1738c2ecf20Sopenharmony_ci lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg); 1748c2ecf20Sopenharmony_ci timing = stb0899_read_reg(state, STB0899_RTF); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (lock >= 42) { 1778c2ecf20Sopenharmony_ci if ((lock > 48) && (abs(timing) >= 110)) { 1788c2ecf20Sopenharmony_ci internal->status = ANALOGCARRIER; 1798c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); 1808c2ecf20Sopenharmony_ci } else { 1818c2ecf20Sopenharmony_ci internal->status = TIMINGOK; 1828c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !"); 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci } else { 1858c2ecf20Sopenharmony_ci internal->status = NOTIMING; 1868c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !"); 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci return internal->status; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci/* 1928c2ecf20Sopenharmony_ci * stb0899_search_tmg 1938c2ecf20Sopenharmony_ci * perform a fs/2 zig-zag to find timing 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 1988c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; 2018c2ecf20Sopenharmony_ci int index = 0; 2028c2ecf20Sopenharmony_ci u8 cfr[2]; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci internal->status = NOTIMING; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* timing loop computation & symbol rate optimisation */ 2078c2ecf20Sopenharmony_ci derot_limit = (internal->sub_range / 2L) / internal->mclk; 2088c2ecf20Sopenharmony_ci derot_step = (params->srate / 2L) / internal->mclk; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { 2118c2ecf20Sopenharmony_ci index++; 2128c2ecf20Sopenharmony_ci derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (abs(derot_freq) > derot_limit) 2158c2ecf20Sopenharmony_ci next_loop--; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (next_loop) { 2188c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); 2198c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); 2208c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci internal->direction = -internal->direction; /* Change zigzag direction */ 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (internal->status == TIMINGOK) { 2268c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 2278c2ecf20Sopenharmony_ci internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); 2288c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return internal->status; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/* 2358c2ecf20Sopenharmony_ci * stb0899_check_carrier 2368c2ecf20Sopenharmony_ci * Check for carrier found 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_check_carrier(struct stb0899_state *state) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 2418c2ecf20Sopenharmony_ci u8 reg; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci msleep(internal->t_derot); /* wait for derotator ok */ 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 2468c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 1); 2478c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DSTATUS); 2508c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg); 2518c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(CARRIER_FOUND, reg)) { 2528c2ecf20Sopenharmony_ci internal->status = CARRIEROK; 2538c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !"); 2548c2ecf20Sopenharmony_ci } else { 2558c2ecf20Sopenharmony_ci internal->status = NOCARRIER; 2568c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !"); 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci return internal->status; 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci/* 2638c2ecf20Sopenharmony_ci * stb0899_search_carrier 2648c2ecf20Sopenharmony_ci * Search for a QPSK carrier with the derotator 2658c2ecf20Sopenharmony_ci */ 2668c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; 2718c2ecf20Sopenharmony_ci int index = 0; 2728c2ecf20Sopenharmony_ci u8 cfr[2]; 2738c2ecf20Sopenharmony_ci u8 reg; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci internal->status = NOCARRIER; 2768c2ecf20Sopenharmony_ci derot_limit = (internal->sub_range / 2L) / internal->mclk; 2778c2ecf20Sopenharmony_ci derot_freq = internal->derot_freq; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 2808c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 1); 2818c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci do { 2848c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); 2858c2ecf20Sopenharmony_ci if (stb0899_check_carrier(state) == NOCARRIER) { 2868c2ecf20Sopenharmony_ci index++; 2878c2ecf20Sopenharmony_ci last_derot_freq = derot_freq; 2888c2ecf20Sopenharmony_ci derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if(abs(derot_freq) > derot_limit) 2918c2ecf20Sopenharmony_ci next_loop--; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (next_loop) { 2948c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 2958c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 1); 2968c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); 2998c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); 3008c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci internal->direction = -internal->direction; /* Change zigzag direction */ 3058c2ecf20Sopenharmony_ci } while ((internal->status != CARRIEROK) && next_loop); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (internal->status == CARRIEROK) { 3088c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 3098c2ecf20Sopenharmony_ci internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); 3108c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq); 3118c2ecf20Sopenharmony_ci } else { 3128c2ecf20Sopenharmony_ci internal->derot_freq = last_derot_freq; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return internal->status; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci/* 3198c2ecf20Sopenharmony_ci * stb0899_check_data 3208c2ecf20Sopenharmony_ci * Check for data found 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_check_data(struct stb0899_state *state) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 3258c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci int lock = 0, index = 0, dataTime = 500, loop; 3288c2ecf20Sopenharmony_ci u8 reg; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci internal->status = NODATA; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* RESET FEC */ 3338c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 3348c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESACS, reg, 1); 3358c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 3368c2ecf20Sopenharmony_ci msleep(1); 3378c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 3388c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESACS, reg, 0); 3398c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci if (params->srate <= 2000000) 3428c2ecf20Sopenharmony_ci dataTime = 2000; 3438c2ecf20Sopenharmony_ci else if (params->srate <= 5000000) 3448c2ecf20Sopenharmony_ci dataTime = 1500; 3458c2ecf20Sopenharmony_ci else if (params->srate <= 15000000) 3468c2ecf20Sopenharmony_ci dataTime = 1000; 3478c2ecf20Sopenharmony_ci else 3488c2ecf20Sopenharmony_ci dataTime = 500; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* clear previous failed END_LOOPVIT */ 3518c2ecf20Sopenharmony_ci stb0899_read_reg(state, STB0899_VSTATUS); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ 3548c2ecf20Sopenharmony_ci while (1) { 3558c2ecf20Sopenharmony_ci /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ 3568c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_VSTATUS); 3578c2ecf20Sopenharmony_ci lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); 3588c2ecf20Sopenharmony_ci loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (lock || loop || (index > dataTime)) 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci index++; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci if (lock) { /* DATA LOCK indicator */ 3668c2ecf20Sopenharmony_ci internal->status = DATAOK; 3678c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !"); 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci return internal->status; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* 3748c2ecf20Sopenharmony_ci * stb0899_search_data 3758c2ecf20Sopenharmony_ci * Search for a QPSK carrier with the derotator 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_search_data(struct stb0899_state *state) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci short int derot_freq, derot_step, derot_limit, next_loop = 3; 3808c2ecf20Sopenharmony_ci u8 cfr[2]; 3818c2ecf20Sopenharmony_ci u8 reg; 3828c2ecf20Sopenharmony_ci int index = 1; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 3858c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci derot_step = (params->srate / 4L) / internal->mclk; 3888c2ecf20Sopenharmony_ci derot_limit = (internal->sub_range / 2L) / internal->mclk; 3898c2ecf20Sopenharmony_ci derot_freq = internal->derot_freq; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci do { 3928c2ecf20Sopenharmony_ci if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ 3958c2ecf20Sopenharmony_ci if (abs(derot_freq) > derot_limit) 3968c2ecf20Sopenharmony_ci next_loop--; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (next_loop) { 3998c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk); 4008c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 4018c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 1); 4028c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); 4058c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); 4068c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci stb0899_check_carrier(state); 4098c2ecf20Sopenharmony_ci index++; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci internal->direction = -internal->direction; /* change zig zag direction */ 4138c2ecf20Sopenharmony_ci } while ((internal->status != DATAOK) && next_loop); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (internal->status == DATAOK) { 4168c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* store autodetected IQ swapping as default for DVB-S2 tuning */ 4198c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_IQSWAP); 4208c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(SYM, reg)) 4218c2ecf20Sopenharmony_ci internal->inversion = IQ_SWAP_ON; 4228c2ecf20Sopenharmony_ci else 4238c2ecf20Sopenharmony_ci internal->inversion = IQ_SWAP_OFF; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); 4268c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci return internal->status; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/* 4338c2ecf20Sopenharmony_ci * stb0899_check_range 4348c2ecf20Sopenharmony_ci * check if the found frequency is in the correct range 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_check_range(struct stb0899_state *state) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 4398c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci int range_offst, tp_freq; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci range_offst = internal->srch_range / 2000; 4448c2ecf20Sopenharmony_ci tp_freq = internal->freq - (internal->derot_freq * internal->mclk) / 1000; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) { 4478c2ecf20Sopenharmony_ci internal->status = RANGEOK; 4488c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !"); 4498c2ecf20Sopenharmony_ci } else { 4508c2ecf20Sopenharmony_ci internal->status = OUTOFRANGE; 4518c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !"); 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci return internal->status; 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci/* 4588c2ecf20Sopenharmony_ci * NextSubRange 4598c2ecf20Sopenharmony_ci * Compute the next subrange of the search 4608c2ecf20Sopenharmony_ci */ 4618c2ecf20Sopenharmony_cistatic void next_sub_range(struct stb0899_state *state) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 4648c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci long old_sub_range; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci if (internal->sub_dir > 0) { 4698c2ecf20Sopenharmony_ci old_sub_range = internal->sub_range; 4708c2ecf20Sopenharmony_ci internal->sub_range = min((internal->srch_range / 2) - 4718c2ecf20Sopenharmony_ci (internal->tuner_offst + internal->sub_range / 2), 4728c2ecf20Sopenharmony_ci internal->sub_range); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (internal->sub_range < 0) 4758c2ecf20Sopenharmony_ci internal->sub_range = 0; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci internal->tuner_offst += (old_sub_range + internal->sub_range) / 2; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000; 4818c2ecf20Sopenharmony_ci internal->sub_dir = -internal->sub_dir; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci/* 4858c2ecf20Sopenharmony_ci * stb0899_dvbs_algo 4868c2ecf20Sopenharmony_ci * Search for a signal, timing, carrier and data for a 4878c2ecf20Sopenharmony_ci * given frequency in a given range 4888c2ecf20Sopenharmony_ci */ 4898c2ecf20Sopenharmony_cienum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci struct stb0899_params *params = &state->params; 4928c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 4938c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci u8 bclc, reg; 4968c2ecf20Sopenharmony_ci u8 cfr[2]; 4978c2ecf20Sopenharmony_ci u8 eq_const[10]; 4988c2ecf20Sopenharmony_ci s32 clnI = 3; 4998c2ecf20Sopenharmony_ci u32 bandwidth = 0; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci /* BETA values rated @ 99MHz */ 5028c2ecf20Sopenharmony_ci s32 betaTab[5][4] = { 5038c2ecf20Sopenharmony_ci /* 5 10 20 30MBps */ 5048c2ecf20Sopenharmony_ci { 37, 34, 32, 31 }, /* QPSK 1/2 */ 5058c2ecf20Sopenharmony_ci { 37, 35, 33, 31 }, /* QPSK 2/3 */ 5068c2ecf20Sopenharmony_ci { 37, 35, 33, 31 }, /* QPSK 3/4 */ 5078c2ecf20Sopenharmony_ci { 37, 36, 33, 32 }, /* QPSK 5/6 */ 5088c2ecf20Sopenharmony_ci { 37, 36, 33, 32 } /* QPSK 7/8 */ 5098c2ecf20Sopenharmony_ci }; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci internal->direction = 1; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci stb0899_set_srate(state, internal->master_clk, params->srate); 5148c2ecf20Sopenharmony_ci /* Carrier loop optimization versus symbol rate for acquisition*/ 5158c2ecf20Sopenharmony_ci if (params->srate <= 5000000) { 5168c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACLC, 0x89); 5178c2ecf20Sopenharmony_ci bclc = stb0899_read_reg(state, STB0899_BCLC); 5188c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, bclc, 0x1c); 5198c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, bclc); 5208c2ecf20Sopenharmony_ci clnI = 0; 5218c2ecf20Sopenharmony_ci } else if (params->srate <= 15000000) { 5228c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACLC, 0xc9); 5238c2ecf20Sopenharmony_ci bclc = stb0899_read_reg(state, STB0899_BCLC); 5248c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, bclc, 0x22); 5258c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, bclc); 5268c2ecf20Sopenharmony_ci clnI = 1; 5278c2ecf20Sopenharmony_ci } else if(params->srate <= 25000000) { 5288c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACLC, 0x89); 5298c2ecf20Sopenharmony_ci bclc = stb0899_read_reg(state, STB0899_BCLC); 5308c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, bclc, 0x27); 5318c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, bclc); 5328c2ecf20Sopenharmony_ci clnI = 2; 5338c2ecf20Sopenharmony_ci } else { 5348c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACLC, 0xc8); 5358c2ecf20Sopenharmony_ci bclc = stb0899_read_reg(state, STB0899_BCLC); 5368c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, bclc, 0x29); 5378c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, bclc); 5388c2ecf20Sopenharmony_ci clnI = 3; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition"); 5428c2ecf20Sopenharmony_ci /* Set the timing loop to acquisition */ 5438c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RTC, 0x46); 5448c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, 0xee); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /* !! WARNING !! 5478c2ecf20Sopenharmony_ci * Do not read any status variables while acquisition, 5488c2ecf20Sopenharmony_ci * If any needed, read before the acquisition starts 5498c2ecf20Sopenharmony_ci * querying status while acquiring causes the 5508c2ecf20Sopenharmony_ci * acquisition to go bad and hence no locks. 5518c2ecf20Sopenharmony_ci */ 5528c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d", 5538c2ecf20Sopenharmony_ci internal->derot_percent, params->srate, internal->mclk); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Initial calculations */ 5568c2ecf20Sopenharmony_ci internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol */ 5578c2ecf20Sopenharmony_ci internal->t_derot = stb0899_calc_derot_time(params->srate); 5588c2ecf20Sopenharmony_ci internal->t_data = 500; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger"); 5618c2ecf20Sopenharmony_ci /* RESET Stream merger */ 5628c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 5638c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESRS, reg, 1); 5648c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* 5678c2ecf20Sopenharmony_ci * Set KDIVIDER to an intermediate value between 5688c2ecf20Sopenharmony_ci * 1/2 and 7/8 for acquisition 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DEMAPVIT); 5718c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60); 5728c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, reg); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */ 5758c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_VITSYNC, 0x19); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci stb0899_first_subrange(state); 5788c2ecf20Sopenharmony_ci do { 5798c2ecf20Sopenharmony_ci /* Initialisations */ 5808c2ecf20Sopenharmony_ci cfr[0] = cfr[1] = 0; 5818c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency */ 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RTF, 0); 5848c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 5858c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 1); 5868c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci internal->derot_freq = 0; 5898c2ecf20Sopenharmony_ci internal->status = NOAGC1; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* enable tuner I/O */ 5928c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 1); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* Move tuner to frequency */ 5958c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency"); 5968c2ecf20Sopenharmony_ci if (state->config->tuner_set_frequency) 5978c2ecf20Sopenharmony_ci state->config->tuner_set_frequency(&state->frontend, internal->freq); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci if (state->config->tuner_get_frequency) 6008c2ecf20Sopenharmony_ci state->config->tuner_get_frequency(&state->frontend, &internal->freq); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop */ 6038c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq); 6048c2ecf20Sopenharmony_ci internal->status = AGC1OK; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci /* There is signal in the band */ 6078c2ecf20Sopenharmony_ci if (config->tuner_get_bandwidth) 6088c2ecf20Sopenharmony_ci config->tuner_get_bandwidth(&state->frontend, &bandwidth); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /* disable tuner I/O */ 6118c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 0); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (params->srate <= bandwidth / 2) 6148c2ecf20Sopenharmony_ci stb0899_search_tmg(state); /* For low rates (SCPC) */ 6158c2ecf20Sopenharmony_ci else 6168c2ecf20Sopenharmony_ci stb0899_check_tmg(state); /* For high rates (MCPC) */ 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (internal->status == TIMINGOK) { 6198c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6208c2ecf20Sopenharmony_ci "TIMING OK ! Derot freq=%d, mclk=%d", 6218c2ecf20Sopenharmony_ci internal->derot_freq, internal->mclk); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */ 6248c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6258c2ecf20Sopenharmony_ci "CARRIER OK ! Derot freq=%d, mclk=%d", 6268c2ecf20Sopenharmony_ci internal->derot_freq, internal->mclk); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci if (stb0899_search_data(state) == DATAOK) { /* Check for data */ 6298c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6308c2ecf20Sopenharmony_ci "DATA OK ! Derot freq=%d, mclk=%d", 6318c2ecf20Sopenharmony_ci internal->derot_freq, internal->mclk); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (stb0899_check_range(state) == RANGEOK) { 6348c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6358c2ecf20Sopenharmony_ci "RANGE OK ! derot freq=%d, mclk=%d", 6368c2ecf20Sopenharmony_ci internal->derot_freq, internal->mclk); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci internal->freq = params->freq - ((internal->derot_freq * internal->mclk) / 1000); 6398c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_PLPARM); 6408c2ecf20Sopenharmony_ci internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); 6418c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6428c2ecf20Sopenharmony_ci "freq=%d, internal resultant freq=%d", 6438c2ecf20Sopenharmony_ci params->freq, internal->freq); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 6468c2ecf20Sopenharmony_ci "internal puncture rate=%d", 6478c2ecf20Sopenharmony_ci internal->fecrate); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci if (internal->status != RANGEOK) 6538c2ecf20Sopenharmony_ci next_sub_range(state); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci } while (internal->sub_range && internal->status != RANGEOK); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Set the timing loop to tracking */ 6588c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RTC, 0x33); 6598c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, 0xf7); 6608c2ecf20Sopenharmony_ci /* if locked and range ok, set Kdiv */ 6618c2ecf20Sopenharmony_ci if (internal->status == RANGEOK) { 6628c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !"); 6638c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_EQON, 0x41); /* Equalizer OFF while acquiring */ 6648c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_VITSYNC, 0x39); /* SN to b'11 for acquisition */ 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* 6678c2ecf20Sopenharmony_ci * Carrier loop optimization versus 6688c2ecf20Sopenharmony_ci * symbol Rate/Puncture Rate for Tracking 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_BCLC); 6718c2ecf20Sopenharmony_ci switch (internal->fecrate) { 6728c2ecf20Sopenharmony_ci case STB0899_FEC_1_2: /* 13 */ 6738c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a); 6748c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]); 6758c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, reg); 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci case STB0899_FEC_2_3: /* 18 */ 6788c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 44); 6798c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]); 6808c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, reg); 6818c2ecf20Sopenharmony_ci break; 6828c2ecf20Sopenharmony_ci case STB0899_FEC_3_4: /* 21 */ 6838c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 60); 6848c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]); 6858c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, reg); 6868c2ecf20Sopenharmony_ci break; 6878c2ecf20Sopenharmony_ci case STB0899_FEC_5_6: /* 24 */ 6888c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 75); 6898c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]); 6908c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, reg); 6918c2ecf20Sopenharmony_ci break; 6928c2ecf20Sopenharmony_ci case STB0899_FEC_6_7: /* 25 */ 6938c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 88); 6948c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACLC, 0x88); 6958c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, 0x9a); 6968c2ecf20Sopenharmony_ci break; 6978c2ecf20Sopenharmony_ci case STB0899_FEC_7_8: /* 26 */ 6988c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DEMAPVIT, 94); 6998c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]); 7008c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_BCLC, reg); 7018c2ecf20Sopenharmony_ci break; 7028c2ecf20Sopenharmony_ci default: 7038c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate"); 7048c2ecf20Sopenharmony_ci break; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci /* release stream merger RESET */ 7078c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 7088c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESRS, reg, 0); 7098c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* disable carrier detector */ 7128c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFD); 7138c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CFD_ON, reg, 0); 7148c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_CFD, reg); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10); 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci return internal->status; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci/* 7238c2ecf20Sopenharmony_ci * stb0899_dvbs2_config_uwp 7248c2ecf20Sopenharmony_ci * Configure UWP state machine 7258c2ecf20Sopenharmony_ci */ 7268c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_config_uwp(struct stb0899_state *state) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 7298c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 7308c2ecf20Sopenharmony_ci u32 uwp1, uwp2, uwp3, reg; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1); 7338c2ecf20Sopenharmony_ci uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2); 7348c2ecf20Sopenharmony_ci uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave); 7378c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant); 7388c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse); 7418c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine); 7428c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq); 7458c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1); 7488c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2); 7498c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO); 7528c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout); 7538c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg); 7548c2ecf20Sopenharmony_ci} 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci/* 7578c2ecf20Sopenharmony_ci * stb0899_dvbs2_config_csm_auto 7588c2ecf20Sopenharmony_ci * Set CSM to AUTO mode 7598c2ecf20Sopenharmony_ci */ 7608c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci u32 reg; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); 7658c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1); 7668c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg); 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_cistatic long Log2Int(int number) 7708c2ecf20Sopenharmony_ci{ 7718c2ecf20Sopenharmony_ci int i; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci i = 0; 7748c2ecf20Sopenharmony_ci while ((1 << i) <= abs(number)) 7758c2ecf20Sopenharmony_ci i++; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if (number == 0) 7788c2ecf20Sopenharmony_ci i = 1; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci return i - 1; 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci/* 7848c2ecf20Sopenharmony_ci * stb0899_dvbs2_calc_srate 7858c2ecf20Sopenharmony_ci * compute BTR_NOM_FREQ for the symbol rate 7868c2ecf20Sopenharmony_ci */ 7878c2ecf20Sopenharmony_cistatic u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 7908c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq; 7938c2ecf20Sopenharmony_ci u32 master_clk, srate; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); 7968c2ecf20Sopenharmony_ci dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; 7978c2ecf20Sopenharmony_ci dec_rate = Log2Int(dec_ratio); 7988c2ecf20Sopenharmony_ci decim = 1 << dec_rate; 7998c2ecf20Sopenharmony_ci master_clk = internal->master_clk / 1000; 8008c2ecf20Sopenharmony_ci srate = internal->srate / 1000; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci if (decim <= 4) { 8038c2ecf20Sopenharmony_ci intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk; 8048c2ecf20Sopenharmony_ci remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk; 8058c2ecf20Sopenharmony_ci } else { 8068c2ecf20Sopenharmony_ci intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100; 8078c2ecf20Sopenharmony_ci remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return btr_nom_freq; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci/* 8158c2ecf20Sopenharmony_ci * stb0899_dvbs2_calc_dev 8168c2ecf20Sopenharmony_ci * compute the correction to be applied to symbol rate 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_cistatic u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 8218c2ecf20Sopenharmony_ci u32 dec_ratio, correction, master_clk, srate; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); 8248c2ecf20Sopenharmony_ci dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci master_clk = internal->master_clk / 1000; /* for integer Calculation*/ 8278c2ecf20Sopenharmony_ci srate = internal->srate / 1000; /* for integer Calculation*/ 8288c2ecf20Sopenharmony_ci correction = (512 * master_clk) / (2 * dec_ratio * srate); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci return correction; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci/* 8348c2ecf20Sopenharmony_ci * stb0899_dvbs2_set_srate 8358c2ecf20Sopenharmony_ci * Set DVBS2 symbol rate 8368c2ecf20Sopenharmony_ci */ 8378c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_set_srate(struct stb0899_state *state) 8388c2ecf20Sopenharmony_ci{ 8398c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq; 8428c2ecf20Sopenharmony_ci u32 correction, freq_adj, band_lim, decim_cntrl, reg; 8438c2ecf20Sopenharmony_ci u8 anti_alias; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci /*set decimation to 1*/ 8468c2ecf20Sopenharmony_ci dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); 8478c2ecf20Sopenharmony_ci dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; 8488c2ecf20Sopenharmony_ci dec_rate = Log2Int(dec_ratio); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci win_sel = 0; 8518c2ecf20Sopenharmony_ci if (dec_rate >= 5) 8528c2ecf20Sopenharmony_ci win_sel = dec_rate - 4; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci decim = (1 << dec_rate); 8558c2ecf20Sopenharmony_ci /* (FSamp/Fsymbol *100) for integer Calculation */ 8568c2ecf20Sopenharmony_ci f_sym = internal->master_clk / ((decim * internal->srate) / 1000); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci if (f_sym <= 2250) /* don't band limit signal going into btr block*/ 8598c2ecf20Sopenharmony_ci band_lim = 1; 8608c2ecf20Sopenharmony_ci else 8618c2ecf20Sopenharmony_ci band_lim = 0; /* band limit signal going into btr block*/ 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7); 8648c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci if (f_sym <= 3450) 8678c2ecf20Sopenharmony_ci anti_alias = 0; 8688c2ecf20Sopenharmony_ci else if (f_sym <= 4250) 8698c2ecf20Sopenharmony_ci anti_alias = 1; 8708c2ecf20Sopenharmony_ci else 8718c2ecf20Sopenharmony_ci anti_alias = 2; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias); 8748c2ecf20Sopenharmony_ci btr_nom_freq = stb0899_dvbs2_calc_srate(state); 8758c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci correction = stb0899_dvbs2_calc_dev(state); 8788c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL); 8798c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction); 8808c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci /* scale UWP+CSM frequency to sample rate*/ 8838c2ecf20Sopenharmony_ci freq_adj = internal->srate / (internal->master_clk / 4096); 8848c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj); 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci/* 8888c2ecf20Sopenharmony_ci * stb0899_dvbs2_set_btr_loopbw 8898c2ecf20Sopenharmony_ci * set bit timing loop bandwidth as a percentage of the symbol rate 8908c2ecf20Sopenharmony_ci */ 8918c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 8948c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci u32 sym_peak = 23, zeta = 707, loopbw_percent = 60; 8978c2ecf20Sopenharmony_ci s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft; 8988c2ecf20Sopenharmony_ci s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift; 8998c2ecf20Sopenharmony_ci u32 decim, K, wn, k_direct, k_indirect; 9008c2ecf20Sopenharmony_ci u32 reg; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci dec_ratio = (internal->master_clk * 2) / (5 * internal->srate); 9038c2ecf20Sopenharmony_ci dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio; 9048c2ecf20Sopenharmony_ci dec_rate = Log2Int(dec_ratio); 9058c2ecf20Sopenharmony_ci decim = (1 << dec_rate); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci sym_peak *= 576000; 9088c2ecf20Sopenharmony_ci K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000); 9098c2ecf20Sopenharmony_ci K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/ 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (K != 0) { 9128c2ecf20Sopenharmony_ci K = sym_peak / K; 9138c2ecf20Sopenharmony_ci wn = (4 * zeta * zeta) + 1000000; 9148c2ecf20Sopenharmony_ci wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn; /*wn =wn 10^-8*/ 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci k_indirect = (wn * wn) / K; /*kindirect = kindirect 10^-6*/ 9178c2ecf20Sopenharmony_ci k_direct = (2 * wn * zeta) / K; /*kDirect = kDirect 10^-2*/ 9188c2ecf20Sopenharmony_ci k_direct *= 100; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2; 9218c2ecf20Sopenharmony_ci k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset; 9228c2ecf20Sopenharmony_ci k_btr1 = k_direct / (1 << k_direct_shift); 9238c2ecf20Sopenharmony_ci k_btr1 /= 10000; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/; 9268c2ecf20Sopenharmony_ci k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset; 9278c2ecf20Sopenharmony_ci k_btr0 = k_indirect * (1 << (-k_indirect_shift)); 9288c2ecf20Sopenharmony_ci k_btr0 /= 1000000; 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci k_btr2_rshft = 0; 9318c2ecf20Sopenharmony_ci if (k_btr0_rshft > 15) { 9328c2ecf20Sopenharmony_ci k_btr2_rshft = k_btr0_rshft - 15; 9338c2ecf20Sopenharmony_ci k_btr0_rshft = 15; 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN); 9368c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft); 9378c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0); 9388c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft); 9398c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1); 9408c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft); 9418c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg); 9428c2ecf20Sopenharmony_ci } else 9438c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f); 9448c2ecf20Sopenharmony_ci} 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci/* 9478c2ecf20Sopenharmony_ci * stb0899_dvbs2_set_carr_freq 9488c2ecf20Sopenharmony_ci * set nominal frequency for carrier search 9498c2ecf20Sopenharmony_ci */ 9508c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk) 9518c2ecf20Sopenharmony_ci{ 9528c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 9538c2ecf20Sopenharmony_ci s32 crl_nom_freq; 9548c2ecf20Sopenharmony_ci u32 reg; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci crl_nom_freq = (1 << config->crl_nco_bits) / master_clk; 9578c2ecf20Sopenharmony_ci crl_nom_freq *= carr_freq; 9588c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); 9598c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq); 9608c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci/* 9648c2ecf20Sopenharmony_ci * stb0899_dvbs2_init_calc 9658c2ecf20Sopenharmony_ci * Initialize DVBS2 UWP, CSM, carrier and timing loops 9668c2ecf20Sopenharmony_ci */ 9678c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_init_calc(struct stb0899_state *state) 9688c2ecf20Sopenharmony_ci{ 9698c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 9708c2ecf20Sopenharmony_ci s32 steps, step_size; 9718c2ecf20Sopenharmony_ci u32 range, reg; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* config uwp and csm */ 9748c2ecf20Sopenharmony_ci stb0899_dvbs2_config_uwp(state); 9758c2ecf20Sopenharmony_ci stb0899_dvbs2_config_csm_auto(state); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci /* initialize BTR */ 9788c2ecf20Sopenharmony_ci stb0899_dvbs2_set_srate(state); 9798c2ecf20Sopenharmony_ci stb0899_dvbs2_set_btr_loopbw(state); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (internal->srate / 1000000 >= 15) 9828c2ecf20Sopenharmony_ci step_size = (1 << 17) / 5; 9838c2ecf20Sopenharmony_ci else if (internal->srate / 1000000 >= 10) 9848c2ecf20Sopenharmony_ci step_size = (1 << 17) / 7; 9858c2ecf20Sopenharmony_ci else if (internal->srate / 1000000 >= 5) 9868c2ecf20Sopenharmony_ci step_size = (1 << 17) / 10; 9878c2ecf20Sopenharmony_ci else 9888c2ecf20Sopenharmony_ci step_size = (1 << 17) / 4; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci range = internal->srch_range / 1000000; 9918c2ecf20Sopenharmony_ci steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000)); 9928c2ecf20Sopenharmony_ci steps = (steps + 6) / 10; 9938c2ecf20Sopenharmony_ci steps = (steps == 0) ? 1 : steps; 9948c2ecf20Sopenharmony_ci if (steps % 2 == 0) 9958c2ecf20Sopenharmony_ci stb0899_dvbs2_set_carr_freq(state, internal->center_freq - 9968c2ecf20Sopenharmony_ci (internal->step_size * (internal->srate / 20000000)), 9978c2ecf20Sopenharmony_ci (internal->master_clk) / 1000000); 9988c2ecf20Sopenharmony_ci else 9998c2ecf20Sopenharmony_ci stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci /*Set Carrier Search params (zigzag, num steps and freq step size*/ 10028c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2); 10038c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(ZIGZAG, reg, 1); 10048c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps); 10058c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size); 10068c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci/* 10108c2ecf20Sopenharmony_ci * stb0899_dvbs2_btr_init 10118c2ecf20Sopenharmony_ci * initialize the timing loop 10128c2ecf20Sopenharmony_ci */ 10138c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_btr_init(struct stb0899_state *state) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci u32 reg; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci /* set enable BTR loopback */ 10188c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL); 10198c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1); 10208c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1); 10218c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci /* fix btr freq accum at 0 */ 10248c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000); 10258c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /* fix btr freq accum at 0 */ 10288c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000); 10298c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000); 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci/* 10338c2ecf20Sopenharmony_ci * stb0899_dvbs2_reacquire 10348c2ecf20Sopenharmony_ci * trigger a DVB-S2 acquisition 10358c2ecf20Sopenharmony_ci */ 10368c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_reacquire(struct stb0899_state *state) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci u32 reg = 0; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci /* demod soft reset */ 10418c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1); 10428c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg); 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci /*Reset Timing Loop */ 10458c2ecf20Sopenharmony_ci stb0899_dvbs2_btr_init(state); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* reset Carrier loop */ 10488c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30)); 10498c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0); 10508c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0); 10518c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30)); 10528c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /*release demod soft reset */ 10558c2ecf20Sopenharmony_ci reg = 0; 10568c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0); 10578c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci /* start acquisition process */ 10608c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1); 10618c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0); 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* equalizer Init */ 10648c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci /*Start equilizer */ 10678c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); 10708c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0); 10718c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0); 10728c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05); 10738c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01); 10748c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci /* RESET Packet delineator */ 10778c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a); 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci/* 10818c2ecf20Sopenharmony_ci * stb0899_dvbs2_get_dmd_status 10828c2ecf20Sopenharmony_ci * get DVB-S2 Demod LOCK status 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci int time = -10, lock = 0, uwp, csm; 10878c2ecf20Sopenharmony_ci u32 reg; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci do { 10908c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS); 10918c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg); 10928c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(IF_AGC_LOCK, reg)) 10938c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !"); 10948c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2); 10958c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg); 10968c2ecf20Sopenharmony_ci uwp = STB0899_GETFIELD(UWP_LOCK, reg); 10978c2ecf20Sopenharmony_ci csm = STB0899_GETFIELD(CSM_LOCK, reg); 10988c2ecf20Sopenharmony_ci if (uwp && csm) 10998c2ecf20Sopenharmony_ci lock = 1; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci time += 10; 11028c2ecf20Sopenharmony_ci msleep(10); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci } while ((!lock) && (time <= timeout)); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (lock) { 11078c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !"); 11088c2ecf20Sopenharmony_ci return DVBS2_DEMOD_LOCK; 11098c2ecf20Sopenharmony_ci } else { 11108c2ecf20Sopenharmony_ci return DVBS2_DEMOD_NOLOCK; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci/* 11158c2ecf20Sopenharmony_ci * stb0899_dvbs2_get_data_lock 11168c2ecf20Sopenharmony_ci * get FEC status 11178c2ecf20Sopenharmony_ci */ 11188c2ecf20Sopenharmony_cistatic int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci int time = 0, lock = 0; 11218c2ecf20Sopenharmony_ci u8 reg; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci while ((!lock) && (time < timeout)) { 11248c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1); 11258c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg); 11268c2ecf20Sopenharmony_ci lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg); 11278c2ecf20Sopenharmony_ci time++; 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci return lock; 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci/* 11348c2ecf20Sopenharmony_ci * stb0899_dvbs2_get_fec_status 11358c2ecf20Sopenharmony_ci * get DVB-S2 FEC LOCK status 11368c2ecf20Sopenharmony_ci */ 11378c2ecf20Sopenharmony_cistatic enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci int time = 0, Locked; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci do { 11428c2ecf20Sopenharmony_ci Locked = stb0899_dvbs2_get_data_lock(state, 1); 11438c2ecf20Sopenharmony_ci time++; 11448c2ecf20Sopenharmony_ci msleep(1); 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci } while ((!Locked) && (time < timeout)); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci if (Locked) { 11498c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !"); 11508c2ecf20Sopenharmony_ci return DVBS2_FEC_LOCK; 11518c2ecf20Sopenharmony_ci } else { 11528c2ecf20Sopenharmony_ci return DVBS2_FEC_NOLOCK; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci/* 11588c2ecf20Sopenharmony_ci * stb0899_dvbs2_init_csm 11598c2ecf20Sopenharmony_ci * set parameters for manual mode 11608c2ecf20Sopenharmony_ci */ 11618c2ecf20Sopenharmony_cistatic void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80; 11668c2ecf20Sopenharmony_ci s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr; 11678c2ecf20Sopenharmony_ci u32 csm1, csm2, csm3, csm4; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) { 11708c2ecf20Sopenharmony_ci switch (modcod) { 11718c2ecf20Sopenharmony_ci case STB0899_QPSK_12: 11728c2ecf20Sopenharmony_ci gamma_acq = 25; 11738c2ecf20Sopenharmony_ci gamma_rho_acq = 2700; 11748c2ecf20Sopenharmony_ci gamma_trk = 12; 11758c2ecf20Sopenharmony_ci gamma_rho_trk = 180; 11768c2ecf20Sopenharmony_ci lock_count_thr = 8; 11778c2ecf20Sopenharmony_ci break; 11788c2ecf20Sopenharmony_ci case STB0899_QPSK_35: 11798c2ecf20Sopenharmony_ci gamma_acq = 38; 11808c2ecf20Sopenharmony_ci gamma_rho_acq = 7182; 11818c2ecf20Sopenharmony_ci gamma_trk = 14; 11828c2ecf20Sopenharmony_ci gamma_rho_trk = 308; 11838c2ecf20Sopenharmony_ci lock_count_thr = 8; 11848c2ecf20Sopenharmony_ci break; 11858c2ecf20Sopenharmony_ci case STB0899_QPSK_23: 11868c2ecf20Sopenharmony_ci gamma_acq = 42; 11878c2ecf20Sopenharmony_ci gamma_rho_acq = 9408; 11888c2ecf20Sopenharmony_ci gamma_trk = 17; 11898c2ecf20Sopenharmony_ci gamma_rho_trk = 476; 11908c2ecf20Sopenharmony_ci lock_count_thr = 8; 11918c2ecf20Sopenharmony_ci break; 11928c2ecf20Sopenharmony_ci case STB0899_QPSK_34: 11938c2ecf20Sopenharmony_ci gamma_acq = 53; 11948c2ecf20Sopenharmony_ci gamma_rho_acq = 16642; 11958c2ecf20Sopenharmony_ci gamma_trk = 19; 11968c2ecf20Sopenharmony_ci gamma_rho_trk = 646; 11978c2ecf20Sopenharmony_ci lock_count_thr = 8; 11988c2ecf20Sopenharmony_ci break; 11998c2ecf20Sopenharmony_ci case STB0899_QPSK_45: 12008c2ecf20Sopenharmony_ci gamma_acq = 53; 12018c2ecf20Sopenharmony_ci gamma_rho_acq = 17119; 12028c2ecf20Sopenharmony_ci gamma_trk = 22; 12038c2ecf20Sopenharmony_ci gamma_rho_trk = 880; 12048c2ecf20Sopenharmony_ci lock_count_thr = 8; 12058c2ecf20Sopenharmony_ci break; 12068c2ecf20Sopenharmony_ci case STB0899_QPSK_56: 12078c2ecf20Sopenharmony_ci gamma_acq = 55; 12088c2ecf20Sopenharmony_ci gamma_rho_acq = 19250; 12098c2ecf20Sopenharmony_ci gamma_trk = 23; 12108c2ecf20Sopenharmony_ci gamma_rho_trk = 989; 12118c2ecf20Sopenharmony_ci lock_count_thr = 8; 12128c2ecf20Sopenharmony_ci break; 12138c2ecf20Sopenharmony_ci case STB0899_QPSK_89: 12148c2ecf20Sopenharmony_ci gamma_acq = 60; 12158c2ecf20Sopenharmony_ci gamma_rho_acq = 24240; 12168c2ecf20Sopenharmony_ci gamma_trk = 24; 12178c2ecf20Sopenharmony_ci gamma_rho_trk = 1176; 12188c2ecf20Sopenharmony_ci lock_count_thr = 8; 12198c2ecf20Sopenharmony_ci break; 12208c2ecf20Sopenharmony_ci case STB0899_QPSK_910: 12218c2ecf20Sopenharmony_ci gamma_acq = 66; 12228c2ecf20Sopenharmony_ci gamma_rho_acq = 29634; 12238c2ecf20Sopenharmony_ci gamma_trk = 24; 12248c2ecf20Sopenharmony_ci gamma_rho_trk = 1176; 12258c2ecf20Sopenharmony_ci lock_count_thr = 8; 12268c2ecf20Sopenharmony_ci break; 12278c2ecf20Sopenharmony_ci default: 12288c2ecf20Sopenharmony_ci gamma_acq = 66; 12298c2ecf20Sopenharmony_ci gamma_rho_acq = 29634; 12308c2ecf20Sopenharmony_ci gamma_trk = 24; 12318c2ecf20Sopenharmony_ci gamma_rho_trk = 1176; 12328c2ecf20Sopenharmony_ci lock_count_thr = 8; 12338c2ecf20Sopenharmony_ci break; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); 12378c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0); 12388c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); 12418c2ecf20Sopenharmony_ci csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2); 12428c2ecf20Sopenharmony_ci csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3); 12438c2ecf20Sopenharmony_ci csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl); 12468c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass); 12478c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain); 12488c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift); 12498c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift); 12508c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq); 12518c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq); 12528c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk); 12538c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk); 12548c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr); 12558c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); 12588c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2); 12598c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3); 12608c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4); 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci} 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci/* 12658c2ecf20Sopenharmony_ci * stb0899_dvbs2_get_srate 12668c2ecf20Sopenharmony_ci * get DVB-S2 Symbol Rate 12678c2ecf20Sopenharmony_ci */ 12688c2ecf20Sopenharmony_cistatic u32 stb0899_dvbs2_get_srate(struct stb0899_state *state) 12698c2ecf20Sopenharmony_ci{ 12708c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 12718c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg; 12748c2ecf20Sopenharmony_ci int div1, div2, rem1, rem2; 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci div1 = config->btr_nco_bits / 2; 12778c2ecf20Sopenharmony_ci div2 = config->btr_nco_bits - div1 - 1; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL); 12828c2ecf20Sopenharmony_ci decimRate = STB0899_GETFIELD(DECIM_RATE, reg); 12838c2ecf20Sopenharmony_ci decimRate = (1 << decimRate); 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci intval1 = internal->master_clk / (1 << div1); 12868c2ecf20Sopenharmony_ci intval2 = bTrNomFreq / (1 << div2); 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci rem1 = internal->master_clk % (1 << div1); 12898c2ecf20Sopenharmony_ci rem2 = bTrNomFreq % (1 << div2); 12908c2ecf20Sopenharmony_ci /* only for integer calculation */ 12918c2ecf20Sopenharmony_ci srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1)); 12928c2ecf20Sopenharmony_ci srate /= decimRate; /*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */ 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci return srate; 12958c2ecf20Sopenharmony_ci} 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci/* 12988c2ecf20Sopenharmony_ci * stb0899_dvbs2_algo 12998c2ecf20Sopenharmony_ci * Search for signal, timing, carrier and data for a given 13008c2ecf20Sopenharmony_ci * frequency in a given range 13018c2ecf20Sopenharmony_ci */ 13028c2ecf20Sopenharmony_cienum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) 13038c2ecf20Sopenharmony_ci{ 13048c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 13058c2ecf20Sopenharmony_ci enum stb0899_modcod modcod; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum; 13088c2ecf20Sopenharmony_ci int i = 0; 13098c2ecf20Sopenharmony_ci u32 reg, csm1; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci if (internal->srate <= 2000000) { 13128c2ecf20Sopenharmony_ci searchTime = 5000; /* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs */ 13138c2ecf20Sopenharmony_ci FecLockTime = 350; /* 350 ms max time to lock FEC, SYMB <= 2Mbs */ 13148c2ecf20Sopenharmony_ci } else if (internal->srate <= 5000000) { 13158c2ecf20Sopenharmony_ci searchTime = 2500; /* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs */ 13168c2ecf20Sopenharmony_ci FecLockTime = 170; /* 170 ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs */ 13178c2ecf20Sopenharmony_ci } else if (internal->srate <= 10000000) { 13188c2ecf20Sopenharmony_ci searchTime = 1500; /* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs */ 13198c2ecf20Sopenharmony_ci FecLockTime = 80; /* 80 ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs */ 13208c2ecf20Sopenharmony_ci } else if (internal->srate <= 15000000) { 13218c2ecf20Sopenharmony_ci searchTime = 500; /* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs */ 13228c2ecf20Sopenharmony_ci FecLockTime = 50; /* 50 ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs */ 13238c2ecf20Sopenharmony_ci } else if (internal->srate <= 20000000) { 13248c2ecf20Sopenharmony_ci searchTime = 300; /* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs */ 13258c2ecf20Sopenharmony_ci FecLockTime = 30; /* 50 ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs */ 13268c2ecf20Sopenharmony_ci } else if (internal->srate <= 25000000) { 13278c2ecf20Sopenharmony_ci searchTime = 250; /* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs */ 13288c2ecf20Sopenharmony_ci FecLockTime = 25; /* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */ 13298c2ecf20Sopenharmony_ci } else { 13308c2ecf20Sopenharmony_ci searchTime = 150; /* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs */ 13318c2ecf20Sopenharmony_ci FecLockTime = 20; /* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs */ 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci /* Maintain Stream Merger in reset during acquisition */ 13358c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 13368c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESRS, reg, 1); 13378c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci /* enable tuner I/O */ 13408c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 1); 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci /* Move tuner to frequency */ 13438c2ecf20Sopenharmony_ci if (state->config->tuner_set_frequency) 13448c2ecf20Sopenharmony_ci state->config->tuner_set_frequency(&state->frontend, internal->freq); 13458c2ecf20Sopenharmony_ci if (state->config->tuner_get_frequency) 13468c2ecf20Sopenharmony_ci state->config->tuner_get_frequency(&state->frontend, &internal->freq); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci /* disable tuner I/O */ 13498c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 0); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci /* Set IF AGC to acquisition */ 13528c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL); 13538c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 4); 13548c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32); 13558c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2); 13588c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0); 13598c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci /* Initialisation */ 13628c2ecf20Sopenharmony_ci stb0899_dvbs2_init_calc(state); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); 13658c2ecf20Sopenharmony_ci switch (internal->inversion) { 13668c2ecf20Sopenharmony_ci case IQ_SWAP_OFF: 13678c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0); 13688c2ecf20Sopenharmony_ci break; 13698c2ecf20Sopenharmony_ci case IQ_SWAP_ON: 13708c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); 13718c2ecf20Sopenharmony_ci break; 13728c2ecf20Sopenharmony_ci } 13738c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); 13748c2ecf20Sopenharmony_ci stb0899_dvbs2_reacquire(state); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci /* Wait for demod lock (UWP and CSM) */ 13778c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci if (internal->status == DVBS2_DEMOD_LOCK) { 13808c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !"); 13818c2ecf20Sopenharmony_ci i = 0; 13828c2ecf20Sopenharmony_ci /* Demod Locked, check FEC status */ 13838c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci /*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/ 13868c2ecf20Sopenharmony_ci while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { 13878c2ecf20Sopenharmony_ci /* Read the frequency offset*/ 13888c2ecf20Sopenharmony_ci offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ 13918c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); 13928c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); 13938c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); 13948c2ecf20Sopenharmony_ci stb0899_dvbs2_reacquire(state); 13958c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); 13968c2ecf20Sopenharmony_ci i++; 13978c2ecf20Sopenharmony_ci } 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci if (internal->status != DVBS2_FEC_LOCK) { 14018c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); 14028c2ecf20Sopenharmony_ci iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); 14038c2ecf20Sopenharmony_ci /* IQ Spectrum Inversion */ 14048c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); 14058c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); 14068c2ecf20Sopenharmony_ci /* start acquistion process */ 14078c2ecf20Sopenharmony_ci stb0899_dvbs2_reacquire(state); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci /* Wait for demod lock (UWP and CSM) */ 14108c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); 14118c2ecf20Sopenharmony_ci if (internal->status == DVBS2_DEMOD_LOCK) { 14128c2ecf20Sopenharmony_ci i = 0; 14138c2ecf20Sopenharmony_ci /* Demod Locked, check FEC */ 14148c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); 14158c2ecf20Sopenharmony_ci /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ 14168c2ecf20Sopenharmony_ci while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { 14178c2ecf20Sopenharmony_ci /* Read the frequency offset*/ 14188c2ecf20Sopenharmony_ci offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ 14218c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); 14228c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); 14238c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci stb0899_dvbs2_reacquire(state); 14268c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); 14278c2ecf20Sopenharmony_ci i++; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci/* 14318c2ecf20Sopenharmony_ci if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) 14328c2ecf20Sopenharmony_ci pParams->IQLocked = !iqSpectrum; 14338c2ecf20Sopenharmony_ci*/ 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci if (internal->status == DVBS2_FEC_LOCK) { 14368c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !"); 14378c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); 14388c2ecf20Sopenharmony_ci modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2; 14398c2ecf20Sopenharmony_ci pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) && 14428c2ecf20Sopenharmony_ci (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) && 14438c2ecf20Sopenharmony_ci (pilots == 1)) { 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci stb0899_dvbs2_init_csm(state, pilots, modcod); 14468c2ecf20Sopenharmony_ci /* Wait for UWP,CSM and data LOCK 20ms max */ 14478c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci i = 0; 14508c2ecf20Sopenharmony_ci while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { 14518c2ecf20Sopenharmony_ci csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); 14528c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1); 14538c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); 14548c2ecf20Sopenharmony_ci csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1); 14558c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0); 14568c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1); 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); 14598c2ecf20Sopenharmony_ci i++; 14608c2ecf20Sopenharmony_ci } 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) && 14648c2ecf20Sopenharmony_ci (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) && 14658c2ecf20Sopenharmony_ci (pilots == 1)) { 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* Equalizer Disable update */ 14688c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); 14698c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1); 14708c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci /* slow down the Equalizer once locked */ 14748c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL); 14758c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02); 14768c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci /* Store signal parameters */ 14798c2ecf20Sopenharmony_ci offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci offsetfreq = sign_extend32(offsetfreq, 29); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci offsetfreq = offsetfreq / ((1 << 30) / 1000); 14848c2ecf20Sopenharmony_ci offsetfreq *= (internal->master_clk / 1000000); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* store current inversion for next run */ 14878c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); 14888c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) 14898c2ecf20Sopenharmony_ci internal->inversion = IQ_SWAP_ON; 14908c2ecf20Sopenharmony_ci else 14918c2ecf20Sopenharmony_ci internal->inversion = IQ_SWAP_OFF; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci internal->freq = internal->freq + offsetfreq; 14948c2ecf20Sopenharmony_ci internal->srate = stb0899_dvbs2_get_srate(state); 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); 14978c2ecf20Sopenharmony_ci internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2; 14988c2ecf20Sopenharmony_ci internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01; 14998c2ecf20Sopenharmony_ci internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci /* Set IF AGC to tracking */ 15028c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL); 15038c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg, 3); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci /* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/ 15068c2ecf20Sopenharmony_ci if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23)) 15078c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg); 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2); 15128c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7); 15138c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg); 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci /* Release Stream Merger Reset */ 15178c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 15188c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESRS, reg, 0); 15198c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci return internal->status; 15228c2ecf20Sopenharmony_ci} 1523