18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B 48c2ecf20Sopenharmony_ci * DiBcom (http://www.dibcom.fr/) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * based on GPL code from DibCom, which has 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 2004 Amaury Demol for DiBcom 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Acknowledgements 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Amaury Demol from DiBcom for providing specs and driver 158c2ecf20Sopenharmony_ci * sources, on which this driver (and the dvb-dibusb) are based. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <linux/kernel.h> 238c2ecf20Sopenharmony_ci#include <linux/module.h> 248c2ecf20Sopenharmony_ci#include <linux/init.h> 258c2ecf20Sopenharmony_ci#include <linux/delay.h> 268c2ecf20Sopenharmony_ci#include <linux/string.h> 278c2ecf20Sopenharmony_ci#include <linux/slab.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include "dib3000.h" 328c2ecf20Sopenharmony_ci#include "dib3000mb_priv.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* Version information */ 358c2ecf20Sopenharmony_ci#define DRIVER_VERSION "0.1" 368c2ecf20Sopenharmony_ci#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator" 378c2ecf20Sopenharmony_ci#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int debug; 408c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 418c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able))."); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define deb_info(args...) dprintk(0x01, args) 448c2ecf20Sopenharmony_ci#define deb_i2c(args...) dprintk(0x02, args) 458c2ecf20Sopenharmony_ci#define deb_srch(args...) dprintk(0x04, args) 468c2ecf20Sopenharmony_ci#define deb_info(args...) dprintk(0x01, args) 478c2ecf20Sopenharmony_ci#define deb_xfer(args...) dprintk(0x02, args) 488c2ecf20Sopenharmony_ci#define deb_setf(args...) dprintk(0x04, args) 498c2ecf20Sopenharmony_ci#define deb_getf(args...) dprintk(0x08, args) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int dib3000_read_reg(struct dib3000_state *state, u16 reg) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; 548c2ecf20Sopenharmony_ci u8 rb[2]; 558c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 568c2ecf20Sopenharmony_ci { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 }, 578c2ecf20Sopenharmony_ci { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 }, 588c2ecf20Sopenharmony_ci }; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c, msg, 2) != 2) 618c2ecf20Sopenharmony_ci deb_i2c("i2c read error\n"); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg, 648c2ecf20Sopenharmony_ci (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return (rb[0] << 8) | rb[1]; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci u8 b[] = { 728c2ecf20Sopenharmony_ci (reg >> 8) & 0xff, reg & 0xff, 738c2ecf20Sopenharmony_ci (val >> 8) & 0xff, val & 0xff, 748c2ecf20Sopenharmony_ci }; 758c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 768c2ecf20Sopenharmony_ci { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 } 778c2ecf20Sopenharmony_ci }; 788c2ecf20Sopenharmony_ci deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic int dib3000_search_status(u16 irq,u16 lock) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci if (irq & 0x02) { 868c2ecf20Sopenharmony_ci if (lock & 0x01) { 878c2ecf20Sopenharmony_ci deb_srch("auto search succeeded\n"); 888c2ecf20Sopenharmony_ci return 1; // auto search succeeded 898c2ecf20Sopenharmony_ci } else { 908c2ecf20Sopenharmony_ci deb_srch("auto search not successful\n"); 918c2ecf20Sopenharmony_ci return 0; // auto search failed 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci } else if (irq & 0x01) { 948c2ecf20Sopenharmony_ci deb_srch("auto search failed\n"); 958c2ecf20Sopenharmony_ci return 0; // auto search failed 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci return -1; // try again 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* for auto search */ 1018c2ecf20Sopenharmony_cistatic u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ 1028c2ecf20Sopenharmony_ci { /* fft */ 1038c2ecf20Sopenharmony_ci { /* gua */ 1048c2ecf20Sopenharmony_ci { 0, 1 }, /* 0 0 { 0,1 } */ 1058c2ecf20Sopenharmony_ci { 3, 9 }, /* 0 1 { 0,1 } */ 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci { 1088c2ecf20Sopenharmony_ci { 2, 5 }, /* 1 0 { 0,1 } */ 1098c2ecf20Sopenharmony_ci { 6, 11 }, /* 1 1 { 0,1 } */ 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci }; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int dib3000mb_get_frontend(struct dvb_frontend* fe, 1148c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 1198c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1208c2ecf20Sopenharmony_ci enum fe_code_rate fe_cr = FEC_NONE; 1218c2ecf20Sopenharmony_ci int search_state, seq; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (tuner && fe->ops.tuner_ops.set_params) { 1248c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 1258c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci switch (c->bandwidth_hz) { 1288c2ecf20Sopenharmony_ci case 8000000: 1298c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]); 1308c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz); 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci case 7000000: 1338c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]); 1348c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz); 1358c2ecf20Sopenharmony_ci break; 1368c2ecf20Sopenharmony_ci case 6000000: 1378c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]); 1388c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz); 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci case 0: 1418c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1428c2ecf20Sopenharmony_ci default: 1438c2ecf20Sopenharmony_ci pr_err("unknown bandwidth value.\n"); 1448c2ecf20Sopenharmony_ci return -EINVAL; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci deb_setf("bandwidth: %d MHZ\n", c->bandwidth_hz / 1000000); 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci switch (c->transmission_mode) { 1518c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 1528c2ecf20Sopenharmony_ci deb_setf("transmission mode: 2k\n"); 1538c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K); 1548c2ecf20Sopenharmony_ci break; 1558c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 1568c2ecf20Sopenharmony_ci deb_setf("transmission mode: 8k\n"); 1578c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K); 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 1608c2ecf20Sopenharmony_ci deb_setf("transmission mode: auto\n"); 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci default: 1638c2ecf20Sopenharmony_ci return -EINVAL; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci switch (c->guard_interval) { 1678c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_32: 1688c2ecf20Sopenharmony_ci deb_setf("guard 1_32\n"); 1698c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32); 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_16: 1728c2ecf20Sopenharmony_ci deb_setf("guard 1_16\n"); 1738c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16); 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_8: 1768c2ecf20Sopenharmony_ci deb_setf("guard 1_8\n"); 1778c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8); 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_4: 1808c2ecf20Sopenharmony_ci deb_setf("guard 1_4\n"); 1818c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4); 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case GUARD_INTERVAL_AUTO: 1848c2ecf20Sopenharmony_ci deb_setf("guard auto\n"); 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci default: 1878c2ecf20Sopenharmony_ci return -EINVAL; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci switch (c->inversion) { 1918c2ecf20Sopenharmony_ci case INVERSION_OFF: 1928c2ecf20Sopenharmony_ci deb_setf("inversion off\n"); 1938c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF); 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci case INVERSION_AUTO: 1968c2ecf20Sopenharmony_ci deb_setf("inversion auto\n"); 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci case INVERSION_ON: 1998c2ecf20Sopenharmony_ci deb_setf("inversion on\n"); 2008c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON); 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci default: 2038c2ecf20Sopenharmony_ci return -EINVAL; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci switch (c->modulation) { 2078c2ecf20Sopenharmony_ci case QPSK: 2088c2ecf20Sopenharmony_ci deb_setf("modulation: qpsk\n"); 2098c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK); 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci case QAM_16: 2128c2ecf20Sopenharmony_ci deb_setf("modulation: qam16\n"); 2138c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM); 2148c2ecf20Sopenharmony_ci break; 2158c2ecf20Sopenharmony_ci case QAM_64: 2168c2ecf20Sopenharmony_ci deb_setf("modulation: qam64\n"); 2178c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci case QAM_AUTO: 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci default: 2228c2ecf20Sopenharmony_ci return -EINVAL; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci switch (c->hierarchy) { 2258c2ecf20Sopenharmony_ci case HIERARCHY_NONE: 2268c2ecf20Sopenharmony_ci deb_setf("hierarchy: none\n"); 2278c2ecf20Sopenharmony_ci fallthrough; 2288c2ecf20Sopenharmony_ci case HIERARCHY_1: 2298c2ecf20Sopenharmony_ci deb_setf("hierarchy: alpha=1\n"); 2308c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1); 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci case HIERARCHY_2: 2338c2ecf20Sopenharmony_ci deb_setf("hierarchy: alpha=2\n"); 2348c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2); 2358c2ecf20Sopenharmony_ci break; 2368c2ecf20Sopenharmony_ci case HIERARCHY_4: 2378c2ecf20Sopenharmony_ci deb_setf("hierarchy: alpha=4\n"); 2388c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4); 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci case HIERARCHY_AUTO: 2418c2ecf20Sopenharmony_ci deb_setf("hierarchy: alpha=auto\n"); 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci default: 2448c2ecf20Sopenharmony_ci return -EINVAL; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (c->hierarchy == HIERARCHY_NONE) { 2488c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF); 2498c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP); 2508c2ecf20Sopenharmony_ci fe_cr = c->code_rate_HP; 2518c2ecf20Sopenharmony_ci } else if (c->hierarchy != HIERARCHY_AUTO) { 2528c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON); 2538c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP); 2548c2ecf20Sopenharmony_ci fe_cr = c->code_rate_LP; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci switch (fe_cr) { 2578c2ecf20Sopenharmony_ci case FEC_1_2: 2588c2ecf20Sopenharmony_ci deb_setf("fec: 1_2\n"); 2598c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2); 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci case FEC_2_3: 2628c2ecf20Sopenharmony_ci deb_setf("fec: 2_3\n"); 2638c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3); 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case FEC_3_4: 2668c2ecf20Sopenharmony_ci deb_setf("fec: 3_4\n"); 2678c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4); 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci case FEC_5_6: 2708c2ecf20Sopenharmony_ci deb_setf("fec: 5_6\n"); 2718c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6); 2728c2ecf20Sopenharmony_ci break; 2738c2ecf20Sopenharmony_ci case FEC_7_8: 2748c2ecf20Sopenharmony_ci deb_setf("fec: 7_8\n"); 2758c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8); 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci case FEC_NONE: 2788c2ecf20Sopenharmony_ci deb_setf("fec: none\n"); 2798c2ecf20Sopenharmony_ci break; 2808c2ecf20Sopenharmony_ci case FEC_AUTO: 2818c2ecf20Sopenharmony_ci deb_setf("fec: auto\n"); 2828c2ecf20Sopenharmony_ci break; 2838c2ecf20Sopenharmony_ci default: 2848c2ecf20Sopenharmony_ci return -EINVAL; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci seq = dib3000_seq 2888c2ecf20Sopenharmony_ci [c->transmission_mode == TRANSMISSION_MODE_AUTO] 2898c2ecf20Sopenharmony_ci [c->guard_interval == GUARD_INTERVAL_AUTO] 2908c2ecf20Sopenharmony_ci [c->inversion == INVERSION_AUTO]; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci deb_setf("seq? %d\n", seq); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_SEQ, seq); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (c->transmission_mode == TRANSMISSION_MODE_2K) { 2998c2ecf20Sopenharmony_ci if (c->guard_interval == GUARD_INTERVAL_1_8) { 3008c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8); 3018c2ecf20Sopenharmony_ci } else { 3028c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K); 3068c2ecf20Sopenharmony_ci } else { 3078c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF); 3118c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF); 3128c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL); 3198c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* wait for AGC lock */ 3228c2ecf20Sopenharmony_ci msleep(70); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* something has to be auto searched */ 3278c2ecf20Sopenharmony_ci if (c->modulation == QAM_AUTO || 3288c2ecf20Sopenharmony_ci c->hierarchy == HIERARCHY_AUTO || 3298c2ecf20Sopenharmony_ci fe_cr == FEC_AUTO || 3308c2ecf20Sopenharmony_ci c->inversion == INVERSION_AUTO) { 3318c2ecf20Sopenharmony_ci int as_count=0; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci deb_setf("autosearch enabled.\n"); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH); 3388c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci while ((search_state = 3418c2ecf20Sopenharmony_ci dib3000_search_status( 3428c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_AS_IRQ_PENDING), 3438c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100) 3448c2ecf20Sopenharmony_ci msleep(1); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci deb_setf("search_state after autosearch %d after %d checks\n", 3478c2ecf20Sopenharmony_ci search_state, as_count); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (search_state == 1) { 3508c2ecf20Sopenharmony_ci if (dib3000mb_get_frontend(fe, c) == 0) { 3518c2ecf20Sopenharmony_ci deb_setf("reading tuning data from frontend succeeded.\n"); 3528c2ecf20Sopenharmony_ci return dib3000mb_set_frontend(fe, 0); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci } else { 3578c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL); 3588c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return 0; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci deb_info("dib3000mb is getting up.\n"); 3698c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE); 3748c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB); 3818c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_impulse_noise, 3868c2ecf20Sopenharmony_ci dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT); 3998c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4); 4008c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT); 4018c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68); 4068c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69); 4078c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71); 4088c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77); 4098c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78); 4108c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT); 4118c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92); 4128c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96); 4138c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97); 4148c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106); 4158c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107); 4168c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108); 4178c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122); 4188c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF); 4198c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON); 4248c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB); 4258c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142); 4308c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188); 4318c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE); 4328c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); 4338c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146); 4348c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci return 0; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic int dib3000mb_get_frontend(struct dvb_frontend* fe, 4428c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 4458c2ecf20Sopenharmony_ci enum fe_code_rate *cr; 4468c2ecf20Sopenharmony_ci u16 tps_val; 4478c2ecf20Sopenharmony_ci int inv_test1,inv_test2; 4488c2ecf20Sopenharmony_ci u32 dds_val, threshold = 0x800000; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if (!rd(DIB3000MB_REG_TPS_LOCK)) 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB); 4548c2ecf20Sopenharmony_ci deb_getf("DDS_VAL: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB)); 4558c2ecf20Sopenharmony_ci if (dds_val < threshold) 4568c2ecf20Sopenharmony_ci inv_test1 = 0; 4578c2ecf20Sopenharmony_ci else if (dds_val == threshold) 4588c2ecf20Sopenharmony_ci inv_test1 = 1; 4598c2ecf20Sopenharmony_ci else 4608c2ecf20Sopenharmony_ci inv_test1 = 2; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB); 4638c2ecf20Sopenharmony_ci deb_getf("DDS_FREQ: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB)); 4648c2ecf20Sopenharmony_ci if (dds_val < threshold) 4658c2ecf20Sopenharmony_ci inv_test2 = 0; 4668c2ecf20Sopenharmony_ci else if (dds_val == threshold) 4678c2ecf20Sopenharmony_ci inv_test2 = 1; 4688c2ecf20Sopenharmony_ci else 4698c2ecf20Sopenharmony_ci inv_test2 = 2; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci c->inversion = 4728c2ecf20Sopenharmony_ci ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) || 4738c2ecf20Sopenharmony_ci ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ? 4748c2ecf20Sopenharmony_ci INVERSION_ON : INVERSION_OFF; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) { 4798c2ecf20Sopenharmony_ci case DIB3000_CONSTELLATION_QPSK: 4808c2ecf20Sopenharmony_ci deb_getf("QPSK\n"); 4818c2ecf20Sopenharmony_ci c->modulation = QPSK; 4828c2ecf20Sopenharmony_ci break; 4838c2ecf20Sopenharmony_ci case DIB3000_CONSTELLATION_16QAM: 4848c2ecf20Sopenharmony_ci deb_getf("QAM16\n"); 4858c2ecf20Sopenharmony_ci c->modulation = QAM_16; 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci case DIB3000_CONSTELLATION_64QAM: 4888c2ecf20Sopenharmony_ci deb_getf("QAM64\n"); 4898c2ecf20Sopenharmony_ci c->modulation = QAM_64; 4908c2ecf20Sopenharmony_ci break; 4918c2ecf20Sopenharmony_ci default: 4928c2ecf20Sopenharmony_ci pr_err("Unexpected constellation returned by TPS (%d)\n", tps_val); 4938c2ecf20Sopenharmony_ci break; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci deb_getf("TPS: %d\n", tps_val); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (rd(DIB3000MB_REG_TPS_HRCH)) { 4988c2ecf20Sopenharmony_ci deb_getf("HRCH ON\n"); 4998c2ecf20Sopenharmony_ci cr = &c->code_rate_LP; 5008c2ecf20Sopenharmony_ci c->code_rate_HP = FEC_NONE; 5018c2ecf20Sopenharmony_ci switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) { 5028c2ecf20Sopenharmony_ci case DIB3000_ALPHA_0: 5038c2ecf20Sopenharmony_ci deb_getf("HIERARCHY_NONE\n"); 5048c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_NONE; 5058c2ecf20Sopenharmony_ci break; 5068c2ecf20Sopenharmony_ci case DIB3000_ALPHA_1: 5078c2ecf20Sopenharmony_ci deb_getf("HIERARCHY_1\n"); 5088c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_1; 5098c2ecf20Sopenharmony_ci break; 5108c2ecf20Sopenharmony_ci case DIB3000_ALPHA_2: 5118c2ecf20Sopenharmony_ci deb_getf("HIERARCHY_2\n"); 5128c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_2; 5138c2ecf20Sopenharmony_ci break; 5148c2ecf20Sopenharmony_ci case DIB3000_ALPHA_4: 5158c2ecf20Sopenharmony_ci deb_getf("HIERARCHY_4\n"); 5168c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_4; 5178c2ecf20Sopenharmony_ci break; 5188c2ecf20Sopenharmony_ci default: 5198c2ecf20Sopenharmony_ci pr_err("Unexpected ALPHA value returned by TPS (%d)\n", tps_val); 5208c2ecf20Sopenharmony_ci break; 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci deb_getf("TPS: %d\n", tps_val); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP); 5258c2ecf20Sopenharmony_ci } else { 5268c2ecf20Sopenharmony_ci deb_getf("HRCH OFF\n"); 5278c2ecf20Sopenharmony_ci cr = &c->code_rate_HP; 5288c2ecf20Sopenharmony_ci c->code_rate_LP = FEC_NONE; 5298c2ecf20Sopenharmony_ci c->hierarchy = HIERARCHY_NONE; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP); 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci switch (tps_val) { 5358c2ecf20Sopenharmony_ci case DIB3000_FEC_1_2: 5368c2ecf20Sopenharmony_ci deb_getf("FEC_1_2\n"); 5378c2ecf20Sopenharmony_ci *cr = FEC_1_2; 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci case DIB3000_FEC_2_3: 5408c2ecf20Sopenharmony_ci deb_getf("FEC_2_3\n"); 5418c2ecf20Sopenharmony_ci *cr = FEC_2_3; 5428c2ecf20Sopenharmony_ci break; 5438c2ecf20Sopenharmony_ci case DIB3000_FEC_3_4: 5448c2ecf20Sopenharmony_ci deb_getf("FEC_3_4\n"); 5458c2ecf20Sopenharmony_ci *cr = FEC_3_4; 5468c2ecf20Sopenharmony_ci break; 5478c2ecf20Sopenharmony_ci case DIB3000_FEC_5_6: 5488c2ecf20Sopenharmony_ci deb_getf("FEC_5_6\n"); 5498c2ecf20Sopenharmony_ci *cr = FEC_4_5; 5508c2ecf20Sopenharmony_ci break; 5518c2ecf20Sopenharmony_ci case DIB3000_FEC_7_8: 5528c2ecf20Sopenharmony_ci deb_getf("FEC_7_8\n"); 5538c2ecf20Sopenharmony_ci *cr = FEC_7_8; 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci default: 5568c2ecf20Sopenharmony_ci pr_err("Unexpected FEC returned by TPS (%d)\n", tps_val); 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci deb_getf("TPS: %d\n",tps_val); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) { 5628c2ecf20Sopenharmony_ci case DIB3000_GUARD_TIME_1_32: 5638c2ecf20Sopenharmony_ci deb_getf("GUARD_INTERVAL_1_32\n"); 5648c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_32; 5658c2ecf20Sopenharmony_ci break; 5668c2ecf20Sopenharmony_ci case DIB3000_GUARD_TIME_1_16: 5678c2ecf20Sopenharmony_ci deb_getf("GUARD_INTERVAL_1_16\n"); 5688c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_16; 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci case DIB3000_GUARD_TIME_1_8: 5718c2ecf20Sopenharmony_ci deb_getf("GUARD_INTERVAL_1_8\n"); 5728c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci case DIB3000_GUARD_TIME_1_4: 5758c2ecf20Sopenharmony_ci deb_getf("GUARD_INTERVAL_1_4\n"); 5768c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_4; 5778c2ecf20Sopenharmony_ci break; 5788c2ecf20Sopenharmony_ci default: 5798c2ecf20Sopenharmony_ci pr_err("Unexpected Guard Time returned by TPS (%d)\n", tps_val); 5808c2ecf20Sopenharmony_ci break; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci deb_getf("TPS: %d\n", tps_val); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) { 5858c2ecf20Sopenharmony_ci case DIB3000_TRANSMISSION_MODE_2K: 5868c2ecf20Sopenharmony_ci deb_getf("TRANSMISSION_MODE_2K\n"); 5878c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_2K; 5888c2ecf20Sopenharmony_ci break; 5898c2ecf20Sopenharmony_ci case DIB3000_TRANSMISSION_MODE_8K: 5908c2ecf20Sopenharmony_ci deb_getf("TRANSMISSION_MODE_8K\n"); 5918c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 5928c2ecf20Sopenharmony_ci break; 5938c2ecf20Sopenharmony_ci default: 5948c2ecf20Sopenharmony_ci pr_err("unexpected transmission mode return by TPS (%d)\n", tps_val); 5958c2ecf20Sopenharmony_ci break; 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci deb_getf("TPS: %d\n", tps_val); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic int dib3000mb_read_status(struct dvb_frontend *fe, 6038c2ecf20Sopenharmony_ci enum fe_status *stat) 6048c2ecf20Sopenharmony_ci{ 6058c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci *stat = 0; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (rd(DIB3000MB_REG_AGC_LOCK)) 6108c2ecf20Sopenharmony_ci *stat |= FE_HAS_SIGNAL; 6118c2ecf20Sopenharmony_ci if (rd(DIB3000MB_REG_CARRIER_LOCK)) 6128c2ecf20Sopenharmony_ci *stat |= FE_HAS_CARRIER; 6138c2ecf20Sopenharmony_ci if (rd(DIB3000MB_REG_VIT_LCK)) 6148c2ecf20Sopenharmony_ci *stat |= FE_HAS_VITERBI; 6158c2ecf20Sopenharmony_ci if (rd(DIB3000MB_REG_TS_SYNC_LOCK)) 6168c2ecf20Sopenharmony_ci *stat |= (FE_HAS_SYNC | FE_HAS_LOCK); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci deb_getf("actual status is %2x\n",*stat); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n", 6218c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_LOCK), 6228c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_QAM), 6238c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_HRCH), 6248c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_VIT_ALPHA), 6258c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_CODE_RATE_HP), 6268c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_CODE_RATE_LP), 6278c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_GUARD_TIME), 6288c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_FFT), 6298c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_TPS_CELL_ID)); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci //*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 6328c2ecf20Sopenharmony_ci return 0; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_cistatic int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB)); 6408c2ecf20Sopenharmony_ci return 0; 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */ 6448c2ecf20Sopenharmony_cistatic int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci *strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170; 6498c2ecf20Sopenharmony_ci return 0; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6558c2ecf20Sopenharmony_ci short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER); 6568c2ecf20Sopenharmony_ci int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) | 6578c2ecf20Sopenharmony_ci rd(DIB3000MB_REG_NOISE_POWER_LSB); 6588c2ecf20Sopenharmony_ci *snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1); 6598c2ecf20Sopenharmony_ci return 0; 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cistatic int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE); 6678c2ecf20Sopenharmony_ci return 0; 6688c2ecf20Sopenharmony_ci} 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_cistatic int dib3000mb_sleep(struct dvb_frontend* fe) 6718c2ecf20Sopenharmony_ci{ 6728c2ecf20Sopenharmony_ci struct dib3000_state* state = fe->demodulator_priv; 6738c2ecf20Sopenharmony_ci deb_info("dib3000mb is going to bed.\n"); 6748c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN); 6758c2ecf20Sopenharmony_ci return 0; 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 6798c2ecf20Sopenharmony_ci{ 6808c2ecf20Sopenharmony_ci tune->min_delay_ms = 800; 6818c2ecf20Sopenharmony_ci return 0; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci return dib3000mb_fe_init(fe, 0); 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci return dib3000mb_set_frontend(fe, 1); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic void dib3000mb_release(struct dvb_frontend* fe) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci struct dib3000_state *state = fe->demodulator_priv; 6978c2ecf20Sopenharmony_ci kfree(state); 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci/* pid filter and transfer stuff */ 7018c2ecf20Sopenharmony_cistatic int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci struct dib3000_state *state = fe->demodulator_priv; 7048c2ecf20Sopenharmony_ci pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0); 7058c2ecf20Sopenharmony_ci wr(index+DIB3000MB_REG_FIRST_PID,pid); 7068c2ecf20Sopenharmony_ci return 0; 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cistatic int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff) 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci struct dib3000_state *state = fe->demodulator_priv; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling"); 7148c2ecf20Sopenharmony_ci if (onoff) { 7158c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE); 7168c2ecf20Sopenharmony_ci } else { 7178c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci return 0; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct dib3000_state *state = fe->demodulator_priv; 7258c2ecf20Sopenharmony_ci deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling"); 7268c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_PID_PARSE,onoff); 7278c2ecf20Sopenharmony_ci return 0; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_cistatic int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci struct dib3000_state *state = fe->demodulator_priv; 7338c2ecf20Sopenharmony_ci if (onoff) { 7348c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr)); 7358c2ecf20Sopenharmony_ci } else { 7368c2ecf20Sopenharmony_ci wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr)); 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci return 0; 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dib3000mb_ops; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistruct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, 7448c2ecf20Sopenharmony_ci struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci struct dib3000_state* state = NULL; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 7498c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL); 7508c2ecf20Sopenharmony_ci if (state == NULL) 7518c2ecf20Sopenharmony_ci goto error; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* setup the state */ 7548c2ecf20Sopenharmony_ci state->i2c = i2c; 7558c2ecf20Sopenharmony_ci memcpy(&state->config,config,sizeof(struct dib3000_config)); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci /* check for the correct demod */ 7588c2ecf20Sopenharmony_ci if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) 7598c2ecf20Sopenharmony_ci goto error; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID) 7628c2ecf20Sopenharmony_ci goto error; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* create dvb_frontend */ 7658c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops)); 7668c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci /* set the xfer operations */ 7698c2ecf20Sopenharmony_ci xfer_ops->pid_parse = dib3000mb_pid_parse; 7708c2ecf20Sopenharmony_ci xfer_ops->fifo_ctrl = dib3000mb_fifo_control; 7718c2ecf20Sopenharmony_ci xfer_ops->pid_ctrl = dib3000mb_pid_control; 7728c2ecf20Sopenharmony_ci xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci return &state->frontend; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_cierror: 7778c2ecf20Sopenharmony_ci kfree(state); 7788c2ecf20Sopenharmony_ci return NULL; 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dib3000mb_ops = { 7828c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT }, 7838c2ecf20Sopenharmony_ci .info = { 7848c2ecf20Sopenharmony_ci .name = "DiBcom 3000M-B DVB-T", 7858c2ecf20Sopenharmony_ci .frequency_min_hz = 44250 * kHz, 7868c2ecf20Sopenharmony_ci .frequency_max_hz = 867250 * kHz, 7878c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 7888c2ecf20Sopenharmony_ci .caps = FE_CAN_INVERSION_AUTO | 7898c2ecf20Sopenharmony_ci FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 7908c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 7918c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 7928c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 7938c2ecf20Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO | 7948c2ecf20Sopenharmony_ci FE_CAN_RECOVER | 7958c2ecf20Sopenharmony_ci FE_CAN_HIERARCHY_AUTO, 7968c2ecf20Sopenharmony_ci }, 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci .release = dib3000mb_release, 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci .init = dib3000mb_fe_init_nonmobile, 8018c2ecf20Sopenharmony_ci .sleep = dib3000mb_sleep, 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci .set_frontend = dib3000mb_set_frontend_and_tuner, 8048c2ecf20Sopenharmony_ci .get_frontend = dib3000mb_get_frontend, 8058c2ecf20Sopenharmony_ci .get_tune_settings = dib3000mb_fe_get_tune_settings, 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci .read_status = dib3000mb_read_status, 8088c2ecf20Sopenharmony_ci .read_ber = dib3000mb_read_ber, 8098c2ecf20Sopenharmony_ci .read_signal_strength = dib3000mb_read_signal_strength, 8108c2ecf20Sopenharmony_ci .read_snr = dib3000mb_read_snr, 8118c2ecf20Sopenharmony_ci .read_ucblocks = dib3000mb_read_unc_blocks, 8128c2ecf20Sopenharmony_ci}; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ciMODULE_AUTHOR(DRIVER_AUTHOR); 8158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 8168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dib3000mb_attach); 819