1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29a0bf528SMauro Carvalho Chehab /* 39a0bf528SMauro Carvalho Chehab * Linux-DVB Driver for DiBcom's DiB7000M and 49a0bf528SMauro Carvalho Chehab * first generation DiB7000P-demodulator-family. 59a0bf528SMauro Carvalho Chehab * 69a0bf528SMauro Carvalho Chehab * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) 79a0bf528SMauro Carvalho Chehab */ 875702277SMauro Carvalho Chehab 975702277SMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1075702277SMauro Carvalho Chehab 119a0bf528SMauro Carvalho Chehab #include <linux/kernel.h> 129a0bf528SMauro Carvalho Chehab #include <linux/slab.h> 139a0bf528SMauro Carvalho Chehab #include <linux/i2c.h> 149a0bf528SMauro Carvalho Chehab #include <linux/mutex.h> 159a0bf528SMauro Carvalho Chehab 16fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 179a0bf528SMauro Carvalho Chehab 189a0bf528SMauro Carvalho Chehab #include "dib7000m.h" 199a0bf528SMauro Carvalho Chehab 209a0bf528SMauro Carvalho Chehab static int debug; 219a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644); 229a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 239a0bf528SMauro Carvalho Chehab 2475702277SMauro Carvalho Chehab #define dprintk(fmt, arg...) do { \ 2575702277SMauro Carvalho Chehab if (debug) \ 2675702277SMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 2775702277SMauro Carvalho Chehab __func__, ##arg); \ 2875702277SMauro Carvalho Chehab } while (0) 299a0bf528SMauro Carvalho Chehab 309a0bf528SMauro Carvalho Chehab struct dib7000m_state { 319a0bf528SMauro Carvalho Chehab struct dvb_frontend demod; 329a0bf528SMauro Carvalho Chehab struct dib7000m_config cfg; 339a0bf528SMauro Carvalho Chehab 349a0bf528SMauro Carvalho Chehab u8 i2c_addr; 359a0bf528SMauro Carvalho Chehab struct i2c_adapter *i2c_adap; 369a0bf528SMauro Carvalho Chehab 379a0bf528SMauro Carvalho Chehab struct dibx000_i2c_master i2c_master; 389a0bf528SMauro Carvalho Chehab 399a0bf528SMauro Carvalho Chehab /* offset is 1 in case of the 7000MC */ 409a0bf528SMauro Carvalho Chehab u8 reg_offs; 419a0bf528SMauro Carvalho Chehab 429a0bf528SMauro Carvalho Chehab u16 wbd_ref; 439a0bf528SMauro Carvalho Chehab 449a0bf528SMauro Carvalho Chehab u8 current_band; 459a0bf528SMauro Carvalho Chehab u32 current_bandwidth; 469a0bf528SMauro Carvalho Chehab struct dibx000_agc_config *current_agc; 479a0bf528SMauro Carvalho Chehab u32 timf; 489a0bf528SMauro Carvalho Chehab u32 timf_default; 499a0bf528SMauro Carvalho Chehab u32 internal_clk; 509a0bf528SMauro Carvalho Chehab 519a0bf528SMauro Carvalho Chehab u8 div_force_off : 1; 529a0bf528SMauro Carvalho Chehab u8 div_state : 1; 539a0bf528SMauro Carvalho Chehab u16 div_sync_wait; 549a0bf528SMauro Carvalho Chehab 559a0bf528SMauro Carvalho Chehab u16 revision; 569a0bf528SMauro Carvalho Chehab 579a0bf528SMauro Carvalho Chehab u8 agc_state; 589a0bf528SMauro Carvalho Chehab 599a0bf528SMauro Carvalho Chehab /* for the I2C transfer */ 609a0bf528SMauro Carvalho Chehab struct i2c_msg msg[2]; 619a0bf528SMauro Carvalho Chehab u8 i2c_write_buffer[4]; 629a0bf528SMauro Carvalho Chehab u8 i2c_read_buffer[2]; 639a0bf528SMauro Carvalho Chehab struct mutex i2c_buffer_lock; 649a0bf528SMauro Carvalho Chehab }; 659a0bf528SMauro Carvalho Chehab 669a0bf528SMauro Carvalho Chehab enum dib7000m_power_mode { 679a0bf528SMauro Carvalho Chehab DIB7000M_POWER_ALL = 0, 689a0bf528SMauro Carvalho Chehab 699a0bf528SMauro Carvalho Chehab DIB7000M_POWER_NO, 709a0bf528SMauro Carvalho Chehab DIB7000M_POWER_INTERF_ANALOG_AGC, 719a0bf528SMauro Carvalho Chehab DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, 729a0bf528SMauro Carvalho Chehab DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, 739a0bf528SMauro Carvalho Chehab DIB7000M_POWER_INTERFACE_ONLY, 749a0bf528SMauro Carvalho Chehab }; 759a0bf528SMauro Carvalho Chehab 769a0bf528SMauro Carvalho Chehab static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) 779a0bf528SMauro Carvalho Chehab { 789a0bf528SMauro Carvalho Chehab u16 ret; 799a0bf528SMauro Carvalho Chehab 809a0bf528SMauro Carvalho Chehab if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 8175702277SMauro Carvalho Chehab dprintk("could not acquire lock\n"); 829a0bf528SMauro Carvalho Chehab return 0; 839a0bf528SMauro Carvalho Chehab } 849a0bf528SMauro Carvalho Chehab 859a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[0] = (reg >> 8) | 0x80; 869a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[1] = reg & 0xff; 879a0bf528SMauro Carvalho Chehab 889a0bf528SMauro Carvalho Chehab memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); 899a0bf528SMauro Carvalho Chehab state->msg[0].addr = state->i2c_addr >> 1; 909a0bf528SMauro Carvalho Chehab state->msg[0].flags = 0; 919a0bf528SMauro Carvalho Chehab state->msg[0].buf = state->i2c_write_buffer; 929a0bf528SMauro Carvalho Chehab state->msg[0].len = 2; 939a0bf528SMauro Carvalho Chehab state->msg[1].addr = state->i2c_addr >> 1; 949a0bf528SMauro Carvalho Chehab state->msg[1].flags = I2C_M_RD; 959a0bf528SMauro Carvalho Chehab state->msg[1].buf = state->i2c_read_buffer; 969a0bf528SMauro Carvalho Chehab state->msg[1].len = 2; 979a0bf528SMauro Carvalho Chehab 989a0bf528SMauro Carvalho Chehab if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2) 9975702277SMauro Carvalho Chehab dprintk("i2c read error on %d\n", reg); 1009a0bf528SMauro Carvalho Chehab 1019a0bf528SMauro Carvalho Chehab ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; 1029a0bf528SMauro Carvalho Chehab mutex_unlock(&state->i2c_buffer_lock); 1039a0bf528SMauro Carvalho Chehab 1049a0bf528SMauro Carvalho Chehab return ret; 1059a0bf528SMauro Carvalho Chehab } 1069a0bf528SMauro Carvalho Chehab 1079a0bf528SMauro Carvalho Chehab static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) 1089a0bf528SMauro Carvalho Chehab { 1099a0bf528SMauro Carvalho Chehab int ret; 1109a0bf528SMauro Carvalho Chehab 1119a0bf528SMauro Carvalho Chehab if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 11275702277SMauro Carvalho Chehab dprintk("could not acquire lock\n"); 1139a0bf528SMauro Carvalho Chehab return -EINVAL; 1149a0bf528SMauro Carvalho Chehab } 1159a0bf528SMauro Carvalho Chehab 1169a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[0] = (reg >> 8) & 0xff; 1179a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[1] = reg & 0xff; 1189a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[2] = (val >> 8) & 0xff; 1199a0bf528SMauro Carvalho Chehab state->i2c_write_buffer[3] = val & 0xff; 1209a0bf528SMauro Carvalho Chehab 1219a0bf528SMauro Carvalho Chehab memset(&state->msg[0], 0, sizeof(struct i2c_msg)); 1229a0bf528SMauro Carvalho Chehab state->msg[0].addr = state->i2c_addr >> 1; 1239a0bf528SMauro Carvalho Chehab state->msg[0].flags = 0; 1249a0bf528SMauro Carvalho Chehab state->msg[0].buf = state->i2c_write_buffer; 1259a0bf528SMauro Carvalho Chehab state->msg[0].len = 4; 1269a0bf528SMauro Carvalho Chehab 1279a0bf528SMauro Carvalho Chehab ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? 1289a0bf528SMauro Carvalho Chehab -EREMOTEIO : 0); 1299a0bf528SMauro Carvalho Chehab mutex_unlock(&state->i2c_buffer_lock); 1309a0bf528SMauro Carvalho Chehab return ret; 1319a0bf528SMauro Carvalho Chehab } 1329a0bf528SMauro Carvalho Chehab static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf) 1339a0bf528SMauro Carvalho Chehab { 1349a0bf528SMauro Carvalho Chehab u16 l = 0, r, *n; 1359a0bf528SMauro Carvalho Chehab n = buf; 1369a0bf528SMauro Carvalho Chehab l = *n++; 1379a0bf528SMauro Carvalho Chehab while (l) { 1389a0bf528SMauro Carvalho Chehab r = *n++; 1399a0bf528SMauro Carvalho Chehab 1409a0bf528SMauro Carvalho Chehab if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC 1419a0bf528SMauro Carvalho Chehab r++; 1429a0bf528SMauro Carvalho Chehab 1439a0bf528SMauro Carvalho Chehab do { 1449a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, r, *n++); 1459a0bf528SMauro Carvalho Chehab r++; 1469a0bf528SMauro Carvalho Chehab } while (--l); 1479a0bf528SMauro Carvalho Chehab l = *n++; 1489a0bf528SMauro Carvalho Chehab } 1499a0bf528SMauro Carvalho Chehab } 1509a0bf528SMauro Carvalho Chehab 1519a0bf528SMauro Carvalho Chehab static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) 1529a0bf528SMauro Carvalho Chehab { 1539a0bf528SMauro Carvalho Chehab int ret = 0; 1549a0bf528SMauro Carvalho Chehab u16 outreg, fifo_threshold, smo_mode, 1559a0bf528SMauro Carvalho Chehab sram = 0x0005; /* by default SRAM output is disabled */ 1569a0bf528SMauro Carvalho Chehab 1579a0bf528SMauro Carvalho Chehab outreg = 0; 1589a0bf528SMauro Carvalho Chehab fifo_threshold = 1792; 1599a0bf528SMauro Carvalho Chehab smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); 1609a0bf528SMauro Carvalho Chehab 16175702277SMauro Carvalho Chehab dprintk("setting output mode for demod %p to %d\n", &state->demod, mode); 1629a0bf528SMauro Carvalho Chehab 1639a0bf528SMauro Carvalho Chehab switch (mode) { 1649a0bf528SMauro Carvalho Chehab case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock 1659a0bf528SMauro Carvalho Chehab outreg = (1 << 10); /* 0x0400 */ 1669a0bf528SMauro Carvalho Chehab break; 1679a0bf528SMauro Carvalho Chehab case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock 1689a0bf528SMauro Carvalho Chehab outreg = (1 << 10) | (1 << 6); /* 0x0440 */ 1699a0bf528SMauro Carvalho Chehab break; 1709a0bf528SMauro Carvalho Chehab case OUTMODE_MPEG2_SERIAL: // STBs with serial input 1719a0bf528SMauro Carvalho Chehab outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ 1729a0bf528SMauro Carvalho Chehab break; 1739a0bf528SMauro Carvalho Chehab case OUTMODE_DIVERSITY: 1749a0bf528SMauro Carvalho Chehab if (state->cfg.hostbus_diversity) 1759a0bf528SMauro Carvalho Chehab outreg = (1 << 10) | (4 << 6); /* 0x0500 */ 1769a0bf528SMauro Carvalho Chehab else 1779a0bf528SMauro Carvalho Chehab sram |= 0x0c00; 1789a0bf528SMauro Carvalho Chehab break; 1799a0bf528SMauro Carvalho Chehab case OUTMODE_MPEG2_FIFO: // e.g. USB feeding 1809a0bf528SMauro Carvalho Chehab smo_mode |= (3 << 1); 1819a0bf528SMauro Carvalho Chehab fifo_threshold = 512; 1829a0bf528SMauro Carvalho Chehab outreg = (1 << 10) | (5 << 6); 1839a0bf528SMauro Carvalho Chehab break; 1849a0bf528SMauro Carvalho Chehab case OUTMODE_HIGH_Z: // disable 1859a0bf528SMauro Carvalho Chehab outreg = 0; 1869a0bf528SMauro Carvalho Chehab break; 1879a0bf528SMauro Carvalho Chehab default: 18875702277SMauro Carvalho Chehab dprintk("Unhandled output_mode passed to be set for demod %p\n", &state->demod); 1899a0bf528SMauro Carvalho Chehab break; 1909a0bf528SMauro Carvalho Chehab } 1919a0bf528SMauro Carvalho Chehab 1929a0bf528SMauro Carvalho Chehab if (state->cfg.output_mpeg2_in_188_bytes) 1939a0bf528SMauro Carvalho Chehab smo_mode |= (1 << 5) ; 1949a0bf528SMauro Carvalho Chehab 1959a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); 1969a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ 1979a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 1795, outreg); 1989a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 1805, sram); 1999a0bf528SMauro Carvalho Chehab 2009a0bf528SMauro Carvalho Chehab if (state->revision == 0x4003) { 2019a0bf528SMauro Carvalho Chehab u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd; 2029a0bf528SMauro Carvalho Chehab if (mode == OUTMODE_DIVERSITY) 2039a0bf528SMauro Carvalho Chehab clk_cfg1 |= (1 << 1); // P_O_CLK_en 2049a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 909, clk_cfg1); 2059a0bf528SMauro Carvalho Chehab } 2069a0bf528SMauro Carvalho Chehab return ret; 2079a0bf528SMauro Carvalho Chehab } 2089a0bf528SMauro Carvalho Chehab 2099a0bf528SMauro Carvalho Chehab static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) 2109a0bf528SMauro Carvalho Chehab { 2119a0bf528SMauro Carvalho Chehab /* by default everything is going to be powered off */ 2129a0bf528SMauro Carvalho Chehab u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; 2139a0bf528SMauro Carvalho Chehab u8 offset = 0; 2149a0bf528SMauro Carvalho Chehab 2159a0bf528SMauro Carvalho Chehab /* now, depending on the requested mode, we power on */ 2169a0bf528SMauro Carvalho Chehab switch (mode) { 2179a0bf528SMauro Carvalho Chehab /* power up everything in the demod */ 2189a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_ALL: 2199a0bf528SMauro Carvalho Chehab reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; 2209a0bf528SMauro Carvalho Chehab break; 2219a0bf528SMauro Carvalho Chehab 2229a0bf528SMauro Carvalho Chehab /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ 2239a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ 2249a0bf528SMauro Carvalho Chehab reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); 2259a0bf528SMauro Carvalho Chehab break; 2269a0bf528SMauro Carvalho Chehab 2279a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_INTERF_ANALOG_AGC: 2289a0bf528SMauro Carvalho Chehab reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); 2299a0bf528SMauro Carvalho Chehab reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); 2309a0bf528SMauro Carvalho Chehab reg_906 &= ~((1 << 0)); 2319a0bf528SMauro Carvalho Chehab break; 2329a0bf528SMauro Carvalho Chehab 2339a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: 2349a0bf528SMauro Carvalho Chehab reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; 2359a0bf528SMauro Carvalho Chehab break; 2369a0bf528SMauro Carvalho Chehab 2379a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: 2389a0bf528SMauro Carvalho Chehab reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; 2399a0bf528SMauro Carvalho Chehab break; 2409a0bf528SMauro Carvalho Chehab case DIB7000M_POWER_NO: 2419a0bf528SMauro Carvalho Chehab break; 2429a0bf528SMauro Carvalho Chehab } 2439a0bf528SMauro Carvalho Chehab 2449a0bf528SMauro Carvalho Chehab /* always power down unused parts */ 2459a0bf528SMauro Carvalho Chehab if (!state->cfg.mobile_mode) 2469a0bf528SMauro Carvalho Chehab reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); 2479a0bf528SMauro Carvalho Chehab 2489a0bf528SMauro Carvalho Chehab /* P_sdio_select_clk = 0 on MC and after*/ 2499a0bf528SMauro Carvalho Chehab if (state->revision != 0x4000) 2509a0bf528SMauro Carvalho Chehab reg_906 <<= 1; 2519a0bf528SMauro Carvalho Chehab 2529a0bf528SMauro Carvalho Chehab if (state->revision == 0x4003) 2539a0bf528SMauro Carvalho Chehab offset = 1; 2549a0bf528SMauro Carvalho Chehab 2559a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 903 + offset, reg_903); 2569a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 904 + offset, reg_904); 2579a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 905 + offset, reg_905); 2589a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 906 + offset, reg_906); 2599a0bf528SMauro Carvalho Chehab } 2609a0bf528SMauro Carvalho Chehab 2619a0bf528SMauro Carvalho Chehab static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) 2629a0bf528SMauro Carvalho Chehab { 2639a0bf528SMauro Carvalho Chehab int ret = 0; 2649a0bf528SMauro Carvalho Chehab u16 reg_913 = dib7000m_read_word(state, 913), 2659a0bf528SMauro Carvalho Chehab reg_914 = dib7000m_read_word(state, 914); 2669a0bf528SMauro Carvalho Chehab 2679a0bf528SMauro Carvalho Chehab switch (no) { 2689a0bf528SMauro Carvalho Chehab case DIBX000_SLOW_ADC_ON: 2699a0bf528SMauro Carvalho Chehab reg_914 |= (1 << 1) | (1 << 0); 2709a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 914, reg_914); 2719a0bf528SMauro Carvalho Chehab reg_914 &= ~(1 << 1); 2729a0bf528SMauro Carvalho Chehab break; 2739a0bf528SMauro Carvalho Chehab 2749a0bf528SMauro Carvalho Chehab case DIBX000_SLOW_ADC_OFF: 2759a0bf528SMauro Carvalho Chehab reg_914 |= (1 << 1) | (1 << 0); 2769a0bf528SMauro Carvalho Chehab break; 2779a0bf528SMauro Carvalho Chehab 2789a0bf528SMauro Carvalho Chehab case DIBX000_ADC_ON: 2799a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000) { // workaround for PA/MA 2809a0bf528SMauro Carvalho Chehab // power-up ADC 2819a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 913, 0); 2829a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 914, reg_914 & 0x3); 2839a0bf528SMauro Carvalho Chehab // power-down bandgag 2849a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 913, (1 << 15)); 2859a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 914, reg_914 & 0x3); 2869a0bf528SMauro Carvalho Chehab } 2879a0bf528SMauro Carvalho Chehab 2889a0bf528SMauro Carvalho Chehab reg_913 &= 0x0fff; 2899a0bf528SMauro Carvalho Chehab reg_914 &= 0x0003; 2909a0bf528SMauro Carvalho Chehab break; 2919a0bf528SMauro Carvalho Chehab 2929a0bf528SMauro Carvalho Chehab case DIBX000_ADC_OFF: // leave the VBG voltage on 2939a0bf528SMauro Carvalho Chehab reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); 2949a0bf528SMauro Carvalho Chehab reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); 2959a0bf528SMauro Carvalho Chehab break; 2969a0bf528SMauro Carvalho Chehab 2979a0bf528SMauro Carvalho Chehab case DIBX000_VBG_ENABLE: 2989a0bf528SMauro Carvalho Chehab reg_913 &= ~(1 << 15); 2999a0bf528SMauro Carvalho Chehab break; 3009a0bf528SMauro Carvalho Chehab 3019a0bf528SMauro Carvalho Chehab case DIBX000_VBG_DISABLE: 3029a0bf528SMauro Carvalho Chehab reg_913 |= (1 << 15); 3039a0bf528SMauro Carvalho Chehab break; 3049a0bf528SMauro Carvalho Chehab 3059a0bf528SMauro Carvalho Chehab default: 3069a0bf528SMauro Carvalho Chehab break; 3079a0bf528SMauro Carvalho Chehab } 3089a0bf528SMauro Carvalho Chehab 30975702277SMauro Carvalho Chehab // dprintk("913: %x, 914: %x\n", reg_913, reg_914); 3109a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 913, reg_913); 3119a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 914, reg_914); 3129a0bf528SMauro Carvalho Chehab 3139a0bf528SMauro Carvalho Chehab return ret; 3149a0bf528SMauro Carvalho Chehab } 3159a0bf528SMauro Carvalho Chehab 3169a0bf528SMauro Carvalho Chehab static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw) 3179a0bf528SMauro Carvalho Chehab { 3189a0bf528SMauro Carvalho Chehab u32 timf; 3199a0bf528SMauro Carvalho Chehab 3209a0bf528SMauro Carvalho Chehab if (!bw) 3219a0bf528SMauro Carvalho Chehab bw = 8000; 3229a0bf528SMauro Carvalho Chehab 3239a0bf528SMauro Carvalho Chehab // store the current bandwidth for later use 3249a0bf528SMauro Carvalho Chehab state->current_bandwidth = bw; 3259a0bf528SMauro Carvalho Chehab 3269a0bf528SMauro Carvalho Chehab if (state->timf == 0) { 32775702277SMauro Carvalho Chehab dprintk("using default timf\n"); 3289a0bf528SMauro Carvalho Chehab timf = state->timf_default; 3299a0bf528SMauro Carvalho Chehab } else { 33075702277SMauro Carvalho Chehab dprintk("using updated timf\n"); 3319a0bf528SMauro Carvalho Chehab timf = state->timf; 3329a0bf528SMauro Carvalho Chehab } 3339a0bf528SMauro Carvalho Chehab 3349a0bf528SMauro Carvalho Chehab timf = timf * (bw / 50) / 160; 3359a0bf528SMauro Carvalho Chehab 3369a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff)); 3379a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff)); 3389a0bf528SMauro Carvalho Chehab 3399a0bf528SMauro Carvalho Chehab return 0; 3409a0bf528SMauro Carvalho Chehab } 3419a0bf528SMauro Carvalho Chehab 3429a0bf528SMauro Carvalho Chehab static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff) 3439a0bf528SMauro Carvalho Chehab { 3449a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 3459a0bf528SMauro Carvalho Chehab 3469a0bf528SMauro Carvalho Chehab if (state->div_force_off) { 34775702277SMauro Carvalho Chehab dprintk("diversity combination deactivated - forced by COFDM parameters\n"); 3489a0bf528SMauro Carvalho Chehab onoff = 0; 3499a0bf528SMauro Carvalho Chehab } 3509a0bf528SMauro Carvalho Chehab state->div_state = (u8)onoff; 3519a0bf528SMauro Carvalho Chehab 3529a0bf528SMauro Carvalho Chehab if (onoff) { 3539a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 263 + state->reg_offs, 6); 3549a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 264 + state->reg_offs, 6); 3559a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0)); 3569a0bf528SMauro Carvalho Chehab } else { 3579a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 263 + state->reg_offs, 1); 3589a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 264 + state->reg_offs, 0); 3599a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 266 + state->reg_offs, 0); 3609a0bf528SMauro Carvalho Chehab } 3619a0bf528SMauro Carvalho Chehab 3629a0bf528SMauro Carvalho Chehab return 0; 3639a0bf528SMauro Carvalho Chehab } 3649a0bf528SMauro Carvalho Chehab 3659a0bf528SMauro Carvalho Chehab static int dib7000m_sad_calib(struct dib7000m_state *state) 3669a0bf528SMauro Carvalho Chehab { 3679a0bf528SMauro Carvalho Chehab 3689a0bf528SMauro Carvalho Chehab /* internal */ 369868c9a17SMauro Carvalho Chehab // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writing in set_bandwidth 3709a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); 3719a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 3729a0bf528SMauro Carvalho Chehab 3739a0bf528SMauro Carvalho Chehab /* do the calibration */ 3749a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 929, (1 << 0)); 3759a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 929, (0 << 0)); 3769a0bf528SMauro Carvalho Chehab 3779a0bf528SMauro Carvalho Chehab msleep(1); 3789a0bf528SMauro Carvalho Chehab 3799a0bf528SMauro Carvalho Chehab return 0; 3809a0bf528SMauro Carvalho Chehab } 3819a0bf528SMauro Carvalho Chehab 3829a0bf528SMauro Carvalho Chehab static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) 3839a0bf528SMauro Carvalho Chehab { 3849a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff)); 3859a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff)); 3869a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff)); 3879a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff)); 3889a0bf528SMauro Carvalho Chehab 3899a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 928, bw->sad_cfg); 3909a0bf528SMauro Carvalho Chehab } 3919a0bf528SMauro Carvalho Chehab 3929a0bf528SMauro Carvalho Chehab static void dib7000m_reset_pll(struct dib7000m_state *state) 3939a0bf528SMauro Carvalho Chehab { 3949a0bf528SMauro Carvalho Chehab const struct dibx000_bandwidth_config *bw = state->cfg.bw; 3959a0bf528SMauro Carvalho Chehab u16 reg_907,reg_910; 3969a0bf528SMauro Carvalho Chehab 3979a0bf528SMauro Carvalho Chehab /* default */ 3989a0bf528SMauro Carvalho Chehab reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | 3999a0bf528SMauro Carvalho Chehab (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | 4009a0bf528SMauro Carvalho Chehab (bw->enable_refdiv << 1) | (0 << 0); 4019a0bf528SMauro Carvalho Chehab reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; 4029a0bf528SMauro Carvalho Chehab 4039a0bf528SMauro Carvalho Chehab // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) 4049a0bf528SMauro Carvalho Chehab // this is only working only for 30 MHz crystals 4059a0bf528SMauro Carvalho Chehab if (!state->cfg.quartz_direct) { 4069a0bf528SMauro Carvalho Chehab reg_910 |= (1 << 5); // forcing the predivider to 1 4079a0bf528SMauro Carvalho Chehab 4089a0bf528SMauro Carvalho Chehab // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) 4099a0bf528SMauro Carvalho Chehab if(state->cfg.input_clk_is_div_2) 4109a0bf528SMauro Carvalho Chehab reg_907 |= (16 << 9); 4119a0bf528SMauro Carvalho Chehab else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary 4129a0bf528SMauro Carvalho Chehab reg_907 |= (8 << 9); 4139a0bf528SMauro Carvalho Chehab } else { 4149a0bf528SMauro Carvalho Chehab reg_907 |= (bw->pll_ratio & 0x3f) << 9; 4159a0bf528SMauro Carvalho Chehab reg_910 |= (bw->pll_prediv << 5); 4169a0bf528SMauro Carvalho Chehab } 4179a0bf528SMauro Carvalho Chehab 4189a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 910, reg_910); // pll cfg 4199a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 907, reg_907); // clk cfg0 4209a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 4219a0bf528SMauro Carvalho Chehab 4229a0bf528SMauro Carvalho Chehab dib7000m_reset_pll_common(state, bw); 4239a0bf528SMauro Carvalho Chehab } 4249a0bf528SMauro Carvalho Chehab 4259a0bf528SMauro Carvalho Chehab static void dib7000mc_reset_pll(struct dib7000m_state *state) 4269a0bf528SMauro Carvalho Chehab { 4279a0bf528SMauro Carvalho Chehab const struct dibx000_bandwidth_config *bw = state->cfg.bw; 4289a0bf528SMauro Carvalho Chehab u16 clk_cfg1; 4299a0bf528SMauro Carvalho Chehab 4309a0bf528SMauro Carvalho Chehab // clk_cfg0 4319a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); 4329a0bf528SMauro Carvalho Chehab 4339a0bf528SMauro Carvalho Chehab // clk_cfg1 4349a0bf528SMauro Carvalho Chehab //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | 4359a0bf528SMauro Carvalho Chehab clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) | 4369a0bf528SMauro Carvalho Chehab (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | 4379a0bf528SMauro Carvalho Chehab (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0); 4389a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 908, clk_cfg1); 4399a0bf528SMauro Carvalho Chehab clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3); 4409a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 908, clk_cfg1); 4419a0bf528SMauro Carvalho Chehab 4429a0bf528SMauro Carvalho Chehab // smpl_cfg 4439a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); 4449a0bf528SMauro Carvalho Chehab 4459a0bf528SMauro Carvalho Chehab dib7000m_reset_pll_common(state, bw); 4469a0bf528SMauro Carvalho Chehab } 4479a0bf528SMauro Carvalho Chehab 4489a0bf528SMauro Carvalho Chehab static int dib7000m_reset_gpio(struct dib7000m_state *st) 4499a0bf528SMauro Carvalho Chehab { 4509a0bf528SMauro Carvalho Chehab /* reset the GPIOs */ 4519a0bf528SMauro Carvalho Chehab dib7000m_write_word(st, 773, st->cfg.gpio_dir); 4529a0bf528SMauro Carvalho Chehab dib7000m_write_word(st, 774, st->cfg.gpio_val); 4539a0bf528SMauro Carvalho Chehab 4549a0bf528SMauro Carvalho Chehab /* TODO 782 is P_gpio_od */ 4559a0bf528SMauro Carvalho Chehab 4569a0bf528SMauro Carvalho Chehab dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); 4579a0bf528SMauro Carvalho Chehab 4589a0bf528SMauro Carvalho Chehab dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); 4599a0bf528SMauro Carvalho Chehab return 0; 4609a0bf528SMauro Carvalho Chehab } 4619a0bf528SMauro Carvalho Chehab 4629a0bf528SMauro Carvalho Chehab static u16 dib7000m_defaults_common[] = 4639a0bf528SMauro Carvalho Chehab 4649a0bf528SMauro Carvalho Chehab { 4659a0bf528SMauro Carvalho Chehab // auto search configuration 4669a0bf528SMauro Carvalho Chehab 3, 2, 4679a0bf528SMauro Carvalho Chehab 0x0004, 4689a0bf528SMauro Carvalho Chehab 0x1000, 4699a0bf528SMauro Carvalho Chehab 0x0814, 4709a0bf528SMauro Carvalho Chehab 4719a0bf528SMauro Carvalho Chehab 12, 6, 4729a0bf528SMauro Carvalho Chehab 0x001b, 4739a0bf528SMauro Carvalho Chehab 0x7740, 4749a0bf528SMauro Carvalho Chehab 0x005b, 4759a0bf528SMauro Carvalho Chehab 0x8d80, 4769a0bf528SMauro Carvalho Chehab 0x01c9, 4779a0bf528SMauro Carvalho Chehab 0xc380, 4789a0bf528SMauro Carvalho Chehab 0x0000, 4799a0bf528SMauro Carvalho Chehab 0x0080, 4809a0bf528SMauro Carvalho Chehab 0x0000, 4819a0bf528SMauro Carvalho Chehab 0x0090, 4829a0bf528SMauro Carvalho Chehab 0x0001, 4839a0bf528SMauro Carvalho Chehab 0xd4c0, 4849a0bf528SMauro Carvalho Chehab 4859a0bf528SMauro Carvalho Chehab 1, 26, 4869a0bf528SMauro Carvalho Chehab 0x6680, // P_corm_thres Lock algorithms configuration 4879a0bf528SMauro Carvalho Chehab 4889a0bf528SMauro Carvalho Chehab 1, 170, 4899a0bf528SMauro Carvalho Chehab 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on 4909a0bf528SMauro Carvalho Chehab 4919a0bf528SMauro Carvalho Chehab 8, 173, 4929a0bf528SMauro Carvalho Chehab 0, 4939a0bf528SMauro Carvalho Chehab 0, 4949a0bf528SMauro Carvalho Chehab 0, 4959a0bf528SMauro Carvalho Chehab 0, 4969a0bf528SMauro Carvalho Chehab 0, 4979a0bf528SMauro Carvalho Chehab 0, 4989a0bf528SMauro Carvalho Chehab 0, 4999a0bf528SMauro Carvalho Chehab 0, 5009a0bf528SMauro Carvalho Chehab 5019a0bf528SMauro Carvalho Chehab 1, 182, 5029a0bf528SMauro Carvalho Chehab 8192, // P_fft_nb_to_cut 5039a0bf528SMauro Carvalho Chehab 5049a0bf528SMauro Carvalho Chehab 2, 195, 5059a0bf528SMauro Carvalho Chehab 0x0ccd, // P_pha3_thres 5069a0bf528SMauro Carvalho Chehab 0, // P_cti_use_cpe, P_cti_use_prog 5079a0bf528SMauro Carvalho Chehab 5089a0bf528SMauro Carvalho Chehab 1, 205, 5099a0bf528SMauro Carvalho Chehab 0x200f, // P_cspu_regul, P_cspu_win_cut 5109a0bf528SMauro Carvalho Chehab 5119a0bf528SMauro Carvalho Chehab 5, 214, 5129a0bf528SMauro Carvalho Chehab 0x023d, // P_adp_regul_cnt 5139a0bf528SMauro Carvalho Chehab 0x00a4, // P_adp_noise_cnt 5149a0bf528SMauro Carvalho Chehab 0x00a4, // P_adp_regul_ext 5159a0bf528SMauro Carvalho Chehab 0x7ff0, // P_adp_noise_ext 5169a0bf528SMauro Carvalho Chehab 0x3ccc, // P_adp_fil 5179a0bf528SMauro Carvalho Chehab 5189a0bf528SMauro Carvalho Chehab 1, 226, 5199a0bf528SMauro Carvalho Chehab 0, // P_2d_byp_ti_num 5209a0bf528SMauro Carvalho Chehab 5219a0bf528SMauro Carvalho Chehab 1, 255, 5229a0bf528SMauro Carvalho Chehab 0x800, // P_equal_thres_wgn 5239a0bf528SMauro Carvalho Chehab 5249a0bf528SMauro Carvalho Chehab 1, 263, 5259a0bf528SMauro Carvalho Chehab 0x0001, 5269a0bf528SMauro Carvalho Chehab 5279a0bf528SMauro Carvalho Chehab 1, 281, 5289a0bf528SMauro Carvalho Chehab 0x0010, // P_fec_* 5299a0bf528SMauro Carvalho Chehab 5309a0bf528SMauro Carvalho Chehab 1, 294, 5319a0bf528SMauro Carvalho Chehab 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard 5329a0bf528SMauro Carvalho Chehab 5339a0bf528SMauro Carvalho Chehab 0 5349a0bf528SMauro Carvalho Chehab }; 5359a0bf528SMauro Carvalho Chehab 5369a0bf528SMauro Carvalho Chehab static u16 dib7000m_defaults[] = 5379a0bf528SMauro Carvalho Chehab 5389a0bf528SMauro Carvalho Chehab { 5399a0bf528SMauro Carvalho Chehab /* set ADC level to -16 */ 5409a0bf528SMauro Carvalho Chehab 11, 76, 5419a0bf528SMauro Carvalho Chehab (1 << 13) - 825 - 117, 5429a0bf528SMauro Carvalho Chehab (1 << 13) - 837 - 117, 5439a0bf528SMauro Carvalho Chehab (1 << 13) - 811 - 117, 5449a0bf528SMauro Carvalho Chehab (1 << 13) - 766 - 117, 5459a0bf528SMauro Carvalho Chehab (1 << 13) - 737 - 117, 5469a0bf528SMauro Carvalho Chehab (1 << 13) - 693 - 117, 5479a0bf528SMauro Carvalho Chehab (1 << 13) - 648 - 117, 5489a0bf528SMauro Carvalho Chehab (1 << 13) - 619 - 117, 5499a0bf528SMauro Carvalho Chehab (1 << 13) - 575 - 117, 5509a0bf528SMauro Carvalho Chehab (1 << 13) - 531 - 117, 5519a0bf528SMauro Carvalho Chehab (1 << 13) - 501 - 117, 5529a0bf528SMauro Carvalho Chehab 5539a0bf528SMauro Carvalho Chehab // Tuner IO bank: max drive (14mA) 5549a0bf528SMauro Carvalho Chehab 1, 912, 5559a0bf528SMauro Carvalho Chehab 0x2c8a, 5569a0bf528SMauro Carvalho Chehab 5579a0bf528SMauro Carvalho Chehab 1, 1817, 5589a0bf528SMauro Carvalho Chehab 1, 5599a0bf528SMauro Carvalho Chehab 5609a0bf528SMauro Carvalho Chehab 0, 5619a0bf528SMauro Carvalho Chehab }; 5629a0bf528SMauro Carvalho Chehab 5639a0bf528SMauro Carvalho Chehab static int dib7000m_demod_reset(struct dib7000m_state *state) 5649a0bf528SMauro Carvalho Chehab { 5659a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); 5669a0bf528SMauro Carvalho Chehab 5679a0bf528SMauro Carvalho Chehab /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ 5689a0bf528SMauro Carvalho Chehab dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); 5699a0bf528SMauro Carvalho Chehab 5709a0bf528SMauro Carvalho Chehab /* restart all parts */ 5719a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 898, 0xffff); 5729a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 899, 0xffff); 5739a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 900, 0xff0f); 5749a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 901, 0xfffc); 5759a0bf528SMauro Carvalho Chehab 5769a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 898, 0); 5779a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 899, 0); 5789a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 900, 0); 5799a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 901, 0); 5809a0bf528SMauro Carvalho Chehab 5819a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000) 5829a0bf528SMauro Carvalho Chehab dib7000m_reset_pll(state); 5839a0bf528SMauro Carvalho Chehab else 5849a0bf528SMauro Carvalho Chehab dib7000mc_reset_pll(state); 5859a0bf528SMauro Carvalho Chehab 5869a0bf528SMauro Carvalho Chehab if (dib7000m_reset_gpio(state) != 0) 58775702277SMauro Carvalho Chehab dprintk("GPIO reset was not successful.\n"); 5889a0bf528SMauro Carvalho Chehab 5899a0bf528SMauro Carvalho Chehab if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) 59075702277SMauro Carvalho Chehab dprintk("OUTPUT_MODE could not be reset.\n"); 5919a0bf528SMauro Carvalho Chehab 5929a0bf528SMauro Carvalho Chehab /* unforce divstr regardless whether i2c enumeration was done or not */ 5939a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); 5949a0bf528SMauro Carvalho Chehab 5959a0bf528SMauro Carvalho Chehab dib7000m_set_bandwidth(state, 8000); 5969a0bf528SMauro Carvalho Chehab 5979a0bf528SMauro Carvalho Chehab dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); 5989a0bf528SMauro Carvalho Chehab dib7000m_sad_calib(state); 5999a0bf528SMauro Carvalho Chehab dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); 6009a0bf528SMauro Carvalho Chehab 6019a0bf528SMauro Carvalho Chehab if (state->cfg.dvbt_mode) 6029a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 1796, 0x0); // select DVB-T output 6039a0bf528SMauro Carvalho Chehab 6049a0bf528SMauro Carvalho Chehab if (state->cfg.mobile_mode) 6059a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 261 + state->reg_offs, 2); 6069a0bf528SMauro Carvalho Chehab else 6079a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 224 + state->reg_offs, 1); 6089a0bf528SMauro Carvalho Chehab 6099a0bf528SMauro Carvalho Chehab // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... 6109a0bf528SMauro Carvalho Chehab if(state->cfg.tuner_is_baseband) 6119a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 36, 0x0755); 6129a0bf528SMauro Carvalho Chehab else 6139a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 36, 0x1f55); 6149a0bf528SMauro Carvalho Chehab 6159a0bf528SMauro Carvalho Chehab // P_divclksel=3 P_divbitsel=1 6169a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000) 6179a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); 6189a0bf528SMauro Carvalho Chehab else 6199a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 909, (3 << 4) | 1); 6209a0bf528SMauro Carvalho Chehab 6219a0bf528SMauro Carvalho Chehab dib7000m_write_tab(state, dib7000m_defaults_common); 6229a0bf528SMauro Carvalho Chehab dib7000m_write_tab(state, dib7000m_defaults); 6239a0bf528SMauro Carvalho Chehab 6249a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); 6259a0bf528SMauro Carvalho Chehab 6269a0bf528SMauro Carvalho Chehab state->internal_clk = state->cfg.bw->internal; 6279a0bf528SMauro Carvalho Chehab 6289a0bf528SMauro Carvalho Chehab return 0; 6299a0bf528SMauro Carvalho Chehab } 6309a0bf528SMauro Carvalho Chehab 6319a0bf528SMauro Carvalho Chehab static void dib7000m_restart_agc(struct dib7000m_state *state) 6329a0bf528SMauro Carvalho Chehab { 6339a0bf528SMauro Carvalho Chehab // P_restart_iqc & P_restart_agc 6349a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 898, 0x0c00); 6359a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 898, 0x0000); 6369a0bf528SMauro Carvalho Chehab } 6379a0bf528SMauro Carvalho Chehab 6389a0bf528SMauro Carvalho Chehab static int dib7000m_agc_soft_split(struct dib7000m_state *state) 6399a0bf528SMauro Carvalho Chehab { 6409a0bf528SMauro Carvalho Chehab u16 agc,split_offset; 6419a0bf528SMauro Carvalho Chehab 6429a0bf528SMauro Carvalho Chehab if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) 6439a0bf528SMauro Carvalho Chehab return 0; 6449a0bf528SMauro Carvalho Chehab 6459a0bf528SMauro Carvalho Chehab // n_agc_global 6469a0bf528SMauro Carvalho Chehab agc = dib7000m_read_word(state, 390); 6479a0bf528SMauro Carvalho Chehab 6489a0bf528SMauro Carvalho Chehab if (agc > state->current_agc->split.min_thres) 6499a0bf528SMauro Carvalho Chehab split_offset = state->current_agc->split.min; 6509a0bf528SMauro Carvalho Chehab else if (agc < state->current_agc->split.max_thres) 6519a0bf528SMauro Carvalho Chehab split_offset = state->current_agc->split.max; 6529a0bf528SMauro Carvalho Chehab else 6539a0bf528SMauro Carvalho Chehab split_offset = state->current_agc->split.max * 6549a0bf528SMauro Carvalho Chehab (agc - state->current_agc->split.min_thres) / 6559a0bf528SMauro Carvalho Chehab (state->current_agc->split.max_thres - state->current_agc->split.min_thres); 6569a0bf528SMauro Carvalho Chehab 65775702277SMauro Carvalho Chehab dprintk("AGC split_offset: %d\n", split_offset); 6589a0bf528SMauro Carvalho Chehab 6599a0bf528SMauro Carvalho Chehab // P_agc_force_split and P_agc_split_offset 6609a0bf528SMauro Carvalho Chehab return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); 6619a0bf528SMauro Carvalho Chehab } 6629a0bf528SMauro Carvalho Chehab 6639a0bf528SMauro Carvalho Chehab static int dib7000m_update_lna(struct dib7000m_state *state) 6649a0bf528SMauro Carvalho Chehab { 6659a0bf528SMauro Carvalho Chehab u16 dyn_gain; 6669a0bf528SMauro Carvalho Chehab 6679a0bf528SMauro Carvalho Chehab if (state->cfg.update_lna) { 6689a0bf528SMauro Carvalho Chehab // read dyn_gain here (because it is demod-dependent and not fe) 6699a0bf528SMauro Carvalho Chehab dyn_gain = dib7000m_read_word(state, 390); 6709a0bf528SMauro Carvalho Chehab 6719a0bf528SMauro Carvalho Chehab if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed 6729a0bf528SMauro Carvalho Chehab dib7000m_restart_agc(state); 6739a0bf528SMauro Carvalho Chehab return 1; 6749a0bf528SMauro Carvalho Chehab } 6759a0bf528SMauro Carvalho Chehab } 6769a0bf528SMauro Carvalho Chehab return 0; 6779a0bf528SMauro Carvalho Chehab } 6789a0bf528SMauro Carvalho Chehab 6799a0bf528SMauro Carvalho Chehab static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) 6809a0bf528SMauro Carvalho Chehab { 6819a0bf528SMauro Carvalho Chehab struct dibx000_agc_config *agc = NULL; 6829a0bf528SMauro Carvalho Chehab int i; 6839a0bf528SMauro Carvalho Chehab if (state->current_band == band && state->current_agc != NULL) 6849a0bf528SMauro Carvalho Chehab return 0; 6859a0bf528SMauro Carvalho Chehab state->current_band = band; 6869a0bf528SMauro Carvalho Chehab 6879a0bf528SMauro Carvalho Chehab for (i = 0; i < state->cfg.agc_config_count; i++) 6889a0bf528SMauro Carvalho Chehab if (state->cfg.agc[i].band_caps & band) { 6899a0bf528SMauro Carvalho Chehab agc = &state->cfg.agc[i]; 6909a0bf528SMauro Carvalho Chehab break; 6919a0bf528SMauro Carvalho Chehab } 6929a0bf528SMauro Carvalho Chehab 6939a0bf528SMauro Carvalho Chehab if (agc == NULL) { 69475702277SMauro Carvalho Chehab dprintk("no valid AGC configuration found for band 0x%02x\n", band); 6959a0bf528SMauro Carvalho Chehab return -EINVAL; 6969a0bf528SMauro Carvalho Chehab } 6979a0bf528SMauro Carvalho Chehab 6989a0bf528SMauro Carvalho Chehab state->current_agc = agc; 6999a0bf528SMauro Carvalho Chehab 7009a0bf528SMauro Carvalho Chehab /* AGC */ 7019a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 72 , agc->setup); 7029a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 73 , agc->inv_gain); 7039a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 74 , agc->time_stabiliz); 7049a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); 7059a0bf528SMauro Carvalho Chehab 7069a0bf528SMauro Carvalho Chehab // Demod AGC loop configuration 7079a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); 7089a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); 7099a0bf528SMauro Carvalho Chehab 71075702277SMauro Carvalho Chehab dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", 7119a0bf528SMauro Carvalho Chehab state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); 7129a0bf528SMauro Carvalho Chehab 7139a0bf528SMauro Carvalho Chehab /* AGC continued */ 7149a0bf528SMauro Carvalho Chehab if (state->wbd_ref != 0) 7159a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 102, state->wbd_ref); 7169a0bf528SMauro Carvalho Chehab else // use default 7179a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 102, agc->wbd_ref); 7189a0bf528SMauro Carvalho Chehab 7199a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); 7209a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 104, agc->agc1_max); 7219a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 105, agc->agc1_min); 7229a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 106, agc->agc2_max); 7239a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 107, agc->agc2_min); 7249a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); 7259a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); 7269a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); 7279a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); 7289a0bf528SMauro Carvalho Chehab 7299a0bf528SMauro Carvalho Chehab if (state->revision > 0x4000) { // settings for the MC 7309a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 71, agc->agc1_pt3); 73175702277SMauro Carvalho Chehab // dprintk("929: %x %d %d\n", 7329a0bf528SMauro Carvalho Chehab // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); 7339a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); 7349a0bf528SMauro Carvalho Chehab } else { 7359a0bf528SMauro Carvalho Chehab // wrong default values 7369a0bf528SMauro Carvalho Chehab u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; 7379a0bf528SMauro Carvalho Chehab for (i = 0; i < 9; i++) 7389a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 88 + i, b[i]); 7399a0bf528SMauro Carvalho Chehab } 7409a0bf528SMauro Carvalho Chehab return 0; 7419a0bf528SMauro Carvalho Chehab } 7429a0bf528SMauro Carvalho Chehab 7439a0bf528SMauro Carvalho Chehab static void dib7000m_update_timf(struct dib7000m_state *state) 7449a0bf528SMauro Carvalho Chehab { 7459a0bf528SMauro Carvalho Chehab u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); 7469a0bf528SMauro Carvalho Chehab state->timf = timf * 160 / (state->current_bandwidth / 50); 7479a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 23, (u16) (timf >> 16)); 7489a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); 74975702277SMauro Carvalho Chehab dprintk("updated timf_frequency: %d (default: %d)\n", state->timf, state->timf_default); 7509a0bf528SMauro Carvalho Chehab } 7519a0bf528SMauro Carvalho Chehab 7529a0bf528SMauro Carvalho Chehab static int dib7000m_agc_startup(struct dvb_frontend *demod) 7539a0bf528SMauro Carvalho Chehab { 7549a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *ch = &demod->dtv_property_cache; 7559a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 7569a0bf528SMauro Carvalho Chehab u16 cfg_72 = dib7000m_read_word(state, 72); 7579a0bf528SMauro Carvalho Chehab int ret = -1; 7589a0bf528SMauro Carvalho Chehab u8 *agc_state = &state->agc_state; 7599a0bf528SMauro Carvalho Chehab u8 agc_split; 7609a0bf528SMauro Carvalho Chehab 7619a0bf528SMauro Carvalho Chehab switch (state->agc_state) { 7629a0bf528SMauro Carvalho Chehab case 0: 7639a0bf528SMauro Carvalho Chehab // set power-up level: interf+analog+AGC 7649a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); 7659a0bf528SMauro Carvalho Chehab dib7000m_set_adc_state(state, DIBX000_ADC_ON); 7669a0bf528SMauro Carvalho Chehab 7679a0bf528SMauro Carvalho Chehab if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0) 7689a0bf528SMauro Carvalho Chehab return -1; 7699a0bf528SMauro Carvalho Chehab 7709a0bf528SMauro Carvalho Chehab ret = 7; /* ADC power up */ 7719a0bf528SMauro Carvalho Chehab (*agc_state)++; 7729a0bf528SMauro Carvalho Chehab break; 7739a0bf528SMauro Carvalho Chehab 7749a0bf528SMauro Carvalho Chehab case 1: 7759a0bf528SMauro Carvalho Chehab /* AGC initialization */ 7769a0bf528SMauro Carvalho Chehab if (state->cfg.agc_control) 7779a0bf528SMauro Carvalho Chehab state->cfg.agc_control(&state->demod, 1); 7789a0bf528SMauro Carvalho Chehab 7799a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 75, 32768); 7809a0bf528SMauro Carvalho Chehab if (!state->current_agc->perform_agc_softsplit) { 7819a0bf528SMauro Carvalho Chehab /* we are using the wbd - so slow AGC startup */ 7829a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */ 7839a0bf528SMauro Carvalho Chehab (*agc_state)++; 7849a0bf528SMauro Carvalho Chehab ret = 5; 7859a0bf528SMauro Carvalho Chehab } else { 7869a0bf528SMauro Carvalho Chehab /* default AGC startup */ 7879a0bf528SMauro Carvalho Chehab (*agc_state) = 4; 7889a0bf528SMauro Carvalho Chehab /* wait AGC rough lock time */ 7899a0bf528SMauro Carvalho Chehab ret = 7; 7909a0bf528SMauro Carvalho Chehab } 7919a0bf528SMauro Carvalho Chehab 7929a0bf528SMauro Carvalho Chehab dib7000m_restart_agc(state); 7939a0bf528SMauro Carvalho Chehab break; 7949a0bf528SMauro Carvalho Chehab 7959a0bf528SMauro Carvalho Chehab case 2: /* fast split search path after 5sec */ 7969a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */ 7979a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */ 7989a0bf528SMauro Carvalho Chehab (*agc_state)++; 7999a0bf528SMauro Carvalho Chehab ret = 14; 8009a0bf528SMauro Carvalho Chehab break; 8019a0bf528SMauro Carvalho Chehab 8029a0bf528SMauro Carvalho Chehab case 3: /* split search ended */ 8039a0bf528SMauro Carvalho Chehab agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */ 8049a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */ 8059a0bf528SMauro Carvalho Chehab 8069a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */ 8079a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */ 8089a0bf528SMauro Carvalho Chehab 8099a0bf528SMauro Carvalho Chehab dib7000m_restart_agc(state); 8109a0bf528SMauro Carvalho Chehab 81175702277SMauro Carvalho Chehab dprintk("SPLIT %p: %hd\n", demod, agc_split); 8129a0bf528SMauro Carvalho Chehab 8139a0bf528SMauro Carvalho Chehab (*agc_state)++; 8149a0bf528SMauro Carvalho Chehab ret = 5; 8159a0bf528SMauro Carvalho Chehab break; 8169a0bf528SMauro Carvalho Chehab 8179a0bf528SMauro Carvalho Chehab case 4: /* LNA startup */ 8189a0bf528SMauro Carvalho Chehab /* wait AGC accurate lock time */ 8199a0bf528SMauro Carvalho Chehab ret = 7; 8209a0bf528SMauro Carvalho Chehab 8219a0bf528SMauro Carvalho Chehab if (dib7000m_update_lna(state)) 8229a0bf528SMauro Carvalho Chehab // wait only AGC rough lock time 8239a0bf528SMauro Carvalho Chehab ret = 5; 8249a0bf528SMauro Carvalho Chehab else 8259a0bf528SMauro Carvalho Chehab (*agc_state)++; 8269a0bf528SMauro Carvalho Chehab break; 8279a0bf528SMauro Carvalho Chehab 8289a0bf528SMauro Carvalho Chehab case 5: 8299a0bf528SMauro Carvalho Chehab dib7000m_agc_soft_split(state); 8309a0bf528SMauro Carvalho Chehab 8319a0bf528SMauro Carvalho Chehab if (state->cfg.agc_control) 8329a0bf528SMauro Carvalho Chehab state->cfg.agc_control(&state->demod, 0); 8339a0bf528SMauro Carvalho Chehab 8349a0bf528SMauro Carvalho Chehab (*agc_state)++; 8359a0bf528SMauro Carvalho Chehab break; 8369a0bf528SMauro Carvalho Chehab 8379a0bf528SMauro Carvalho Chehab default: 8389a0bf528SMauro Carvalho Chehab break; 8399a0bf528SMauro Carvalho Chehab } 8409a0bf528SMauro Carvalho Chehab return ret; 8419a0bf528SMauro Carvalho Chehab } 8429a0bf528SMauro Carvalho Chehab 8439a0bf528SMauro Carvalho Chehab static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch, 8449a0bf528SMauro Carvalho Chehab u8 seq) 8459a0bf528SMauro Carvalho Chehab { 8469a0bf528SMauro Carvalho Chehab u16 value, est[4]; 8479a0bf528SMauro Carvalho Chehab 8489a0bf528SMauro Carvalho Chehab dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); 8499a0bf528SMauro Carvalho Chehab 8509a0bf528SMauro Carvalho Chehab /* nfft, guard, qam, alpha */ 8519a0bf528SMauro Carvalho Chehab value = 0; 8529a0bf528SMauro Carvalho Chehab switch (ch->transmission_mode) { 8539a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_2K: value |= (0 << 7); break; 8549a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_4K: value |= (2 << 7); break; 8559a0bf528SMauro Carvalho Chehab default: 8569a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_8K: value |= (1 << 7); break; 8579a0bf528SMauro Carvalho Chehab } 8589a0bf528SMauro Carvalho Chehab switch (ch->guard_interval) { 8599a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_32: value |= (0 << 5); break; 8609a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_16: value |= (1 << 5); break; 8619a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_4: value |= (3 << 5); break; 8629a0bf528SMauro Carvalho Chehab default: 8639a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_8: value |= (2 << 5); break; 8649a0bf528SMauro Carvalho Chehab } 8659a0bf528SMauro Carvalho Chehab switch (ch->modulation) { 8669a0bf528SMauro Carvalho Chehab case QPSK: value |= (0 << 3); break; 8679a0bf528SMauro Carvalho Chehab case QAM_16: value |= (1 << 3); break; 8689a0bf528SMauro Carvalho Chehab default: 8699a0bf528SMauro Carvalho Chehab case QAM_64: value |= (2 << 3); break; 8709a0bf528SMauro Carvalho Chehab } 8719a0bf528SMauro Carvalho Chehab switch (HIERARCHY_1) { 8729a0bf528SMauro Carvalho Chehab case HIERARCHY_2: value |= 2; break; 8739a0bf528SMauro Carvalho Chehab case HIERARCHY_4: value |= 4; break; 8749a0bf528SMauro Carvalho Chehab default: 8759a0bf528SMauro Carvalho Chehab case HIERARCHY_1: value |= 1; break; 8769a0bf528SMauro Carvalho Chehab } 8779a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 0, value); 8789a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 5, (seq << 4)); 8799a0bf528SMauro Carvalho Chehab 8809a0bf528SMauro Carvalho Chehab /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */ 8819a0bf528SMauro Carvalho Chehab value = 0; 8829a0bf528SMauro Carvalho Chehab if (1 != 0) 8839a0bf528SMauro Carvalho Chehab value |= (1 << 6); 8849a0bf528SMauro Carvalho Chehab if (ch->hierarchy == 1) 8859a0bf528SMauro Carvalho Chehab value |= (1 << 4); 8869a0bf528SMauro Carvalho Chehab if (1 == 1) 8879a0bf528SMauro Carvalho Chehab value |= 1; 8889a0bf528SMauro Carvalho Chehab switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) { 8899a0bf528SMauro Carvalho Chehab case FEC_2_3: value |= (2 << 1); break; 8909a0bf528SMauro Carvalho Chehab case FEC_3_4: value |= (3 << 1); break; 8919a0bf528SMauro Carvalho Chehab case FEC_5_6: value |= (5 << 1); break; 8929a0bf528SMauro Carvalho Chehab case FEC_7_8: value |= (7 << 1); break; 8939a0bf528SMauro Carvalho Chehab default: 8949a0bf528SMauro Carvalho Chehab case FEC_1_2: value |= (1 << 1); break; 8959a0bf528SMauro Carvalho Chehab } 8969a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 267 + state->reg_offs, value); 8979a0bf528SMauro Carvalho Chehab 8989a0bf528SMauro Carvalho Chehab /* offset loop parameters */ 8999a0bf528SMauro Carvalho Chehab 9009a0bf528SMauro Carvalho Chehab /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ 9019a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); 9029a0bf528SMauro Carvalho Chehab 9039a0bf528SMauro Carvalho Chehab /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ 9049a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); 9059a0bf528SMauro Carvalho Chehab 9069a0bf528SMauro Carvalho Chehab /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ 9079a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 32, (0 << 4) | 0x3); 9089a0bf528SMauro Carvalho Chehab 9099a0bf528SMauro Carvalho Chehab /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ 9109a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 33, (0 << 4) | 0x5); 9119a0bf528SMauro Carvalho Chehab 9129a0bf528SMauro Carvalho Chehab /* P_dvsy_sync_wait */ 9139a0bf528SMauro Carvalho Chehab switch (ch->transmission_mode) { 9149a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_8K: value = 256; break; 9159a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_4K: value = 128; break; 9169a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_2K: 9179a0bf528SMauro Carvalho Chehab default: value = 64; break; 9189a0bf528SMauro Carvalho Chehab } 9199a0bf528SMauro Carvalho Chehab switch (ch->guard_interval) { 9209a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_16: value *= 2; break; 9219a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_8: value *= 4; break; 9229a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_4: value *= 8; break; 9239a0bf528SMauro Carvalho Chehab default: 9249a0bf528SMauro Carvalho Chehab case GUARD_INTERVAL_1_32: value *= 1; break; 9259a0bf528SMauro Carvalho Chehab } 9269a0bf528SMauro Carvalho Chehab state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO 9279a0bf528SMauro Carvalho Chehab 928868c9a17SMauro Carvalho Chehab /* deactivate the possibility of diversity reception if extended interleave - not for 7000MC */ 9299a0bf528SMauro Carvalho Chehab /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ 9309a0bf528SMauro Carvalho Chehab if (1 == 1 || state->revision > 0x4000) 9319a0bf528SMauro Carvalho Chehab state->div_force_off = 0; 9329a0bf528SMauro Carvalho Chehab else 9339a0bf528SMauro Carvalho Chehab state->div_force_off = 1; 9349a0bf528SMauro Carvalho Chehab dib7000m_set_diversity_in(&state->demod, state->div_state); 9359a0bf528SMauro Carvalho Chehab 9369a0bf528SMauro Carvalho Chehab /* channel estimation fine configuration */ 9379a0bf528SMauro Carvalho Chehab switch (ch->modulation) { 9389a0bf528SMauro Carvalho Chehab case QAM_64: 9399a0bf528SMauro Carvalho Chehab est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ 9409a0bf528SMauro Carvalho Chehab est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ 9419a0bf528SMauro Carvalho Chehab est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ 9429a0bf528SMauro Carvalho Chehab est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ 9439a0bf528SMauro Carvalho Chehab break; 9449a0bf528SMauro Carvalho Chehab case QAM_16: 9459a0bf528SMauro Carvalho Chehab est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ 9469a0bf528SMauro Carvalho Chehab est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ 9479a0bf528SMauro Carvalho Chehab est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ 9489a0bf528SMauro Carvalho Chehab est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ 9499a0bf528SMauro Carvalho Chehab break; 9509a0bf528SMauro Carvalho Chehab default: 9519a0bf528SMauro Carvalho Chehab est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ 9529a0bf528SMauro Carvalho Chehab est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ 9539a0bf528SMauro Carvalho Chehab est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ 9549a0bf528SMauro Carvalho Chehab est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ 9559a0bf528SMauro Carvalho Chehab break; 9569a0bf528SMauro Carvalho Chehab } 9579a0bf528SMauro Carvalho Chehab for (value = 0; value < 4; value++) 9589a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); 9599a0bf528SMauro Carvalho Chehab 9609a0bf528SMauro Carvalho Chehab // set power-up level: autosearch 9619a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); 9629a0bf528SMauro Carvalho Chehab } 9639a0bf528SMauro Carvalho Chehab 9649a0bf528SMauro Carvalho Chehab static int dib7000m_autosearch_start(struct dvb_frontend *demod) 9659a0bf528SMauro Carvalho Chehab { 9669a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *ch = &demod->dtv_property_cache; 9679a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 9689a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties schan; 9699a0bf528SMauro Carvalho Chehab int ret = 0; 9709a0bf528SMauro Carvalho Chehab u32 value, factor; 9719a0bf528SMauro Carvalho Chehab 9729a0bf528SMauro Carvalho Chehab schan = *ch; 9739a0bf528SMauro Carvalho Chehab 9749a0bf528SMauro Carvalho Chehab schan.modulation = QAM_64; 9759a0bf528SMauro Carvalho Chehab schan.guard_interval = GUARD_INTERVAL_1_32; 9769a0bf528SMauro Carvalho Chehab schan.transmission_mode = TRANSMISSION_MODE_8K; 9779a0bf528SMauro Carvalho Chehab schan.code_rate_HP = FEC_2_3; 9789a0bf528SMauro Carvalho Chehab schan.code_rate_LP = FEC_3_4; 9799a0bf528SMauro Carvalho Chehab schan.hierarchy = 0; 9809a0bf528SMauro Carvalho Chehab 9819a0bf528SMauro Carvalho Chehab dib7000m_set_channel(state, &schan, 7); 9829a0bf528SMauro Carvalho Chehab 9839a0bf528SMauro Carvalho Chehab factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz); 9849a0bf528SMauro Carvalho Chehab if (factor >= 5000) 9859a0bf528SMauro Carvalho Chehab factor = 1; 9869a0bf528SMauro Carvalho Chehab else 9879a0bf528SMauro Carvalho Chehab factor = 6; 9889a0bf528SMauro Carvalho Chehab 9899a0bf528SMauro Carvalho Chehab // always use the setting for 8MHz here lock_time for 7,6 MHz are longer 9909a0bf528SMauro Carvalho Chehab value = 30 * state->internal_clk * factor; 9919a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time 9929a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time 9939a0bf528SMauro Carvalho Chehab value = 100 * state->internal_clk * factor; 9949a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time 9959a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time 9969a0bf528SMauro Carvalho Chehab value = 500 * state->internal_clk * factor; 9979a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time 9989a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time 9999a0bf528SMauro Carvalho Chehab 10009a0bf528SMauro Carvalho Chehab // start search 10019a0bf528SMauro Carvalho Chehab value = dib7000m_read_word(state, 0); 10029a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9))); 10039a0bf528SMauro Carvalho Chehab 10049a0bf528SMauro Carvalho Chehab /* clear n_irq_pending */ 10059a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000) 10069a0bf528SMauro Carvalho Chehab dib7000m_write_word(state, 1793, 0); 10079a0bf528SMauro Carvalho Chehab else 10089a0bf528SMauro Carvalho Chehab dib7000m_read_word(state, 537); 10099a0bf528SMauro Carvalho Chehab 10109a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 0, (u16) value); 10119a0bf528SMauro Carvalho Chehab 10129a0bf528SMauro Carvalho Chehab return ret; 10139a0bf528SMauro Carvalho Chehab } 10149a0bf528SMauro Carvalho Chehab 10159a0bf528SMauro Carvalho Chehab static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) 10169a0bf528SMauro Carvalho Chehab { 10179a0bf528SMauro Carvalho Chehab u16 irq_pending = dib7000m_read_word(state, reg); 10189a0bf528SMauro Carvalho Chehab 10199a0bf528SMauro Carvalho Chehab if (irq_pending & 0x1) { // failed 102075702277SMauro Carvalho Chehab dprintk("autosearch failed\n"); 10219a0bf528SMauro Carvalho Chehab return 1; 10229a0bf528SMauro Carvalho Chehab } 10239a0bf528SMauro Carvalho Chehab 10249a0bf528SMauro Carvalho Chehab if (irq_pending & 0x2) { // succeeded 102575702277SMauro Carvalho Chehab dprintk("autosearch succeeded\n"); 10269a0bf528SMauro Carvalho Chehab return 2; 10279a0bf528SMauro Carvalho Chehab } 10289a0bf528SMauro Carvalho Chehab return 0; // still pending 10299a0bf528SMauro Carvalho Chehab } 10309a0bf528SMauro Carvalho Chehab 10319a0bf528SMauro Carvalho Chehab static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) 10329a0bf528SMauro Carvalho Chehab { 10339a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 10349a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000) 10359a0bf528SMauro Carvalho Chehab return dib7000m_autosearch_irq(state, 1793); 10369a0bf528SMauro Carvalho Chehab else 10379a0bf528SMauro Carvalho Chehab return dib7000m_autosearch_irq(state, 537); 10389a0bf528SMauro Carvalho Chehab } 10399a0bf528SMauro Carvalho Chehab 10409a0bf528SMauro Carvalho Chehab static int dib7000m_tune(struct dvb_frontend *demod) 10419a0bf528SMauro Carvalho Chehab { 10429a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *ch = &demod->dtv_property_cache; 10439a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 10449a0bf528SMauro Carvalho Chehab int ret = 0; 10459a0bf528SMauro Carvalho Chehab u16 value; 10469a0bf528SMauro Carvalho Chehab 10479a0bf528SMauro Carvalho Chehab // we are already tuned - just resuming from suspend 10489a0bf528SMauro Carvalho Chehab dib7000m_set_channel(state, ch, 0); 10499a0bf528SMauro Carvalho Chehab 10509a0bf528SMauro Carvalho Chehab // restart demod 10519a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 898, 0x4000); 10529a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 898, 0x0000); 10539a0bf528SMauro Carvalho Chehab msleep(45); 10549a0bf528SMauro Carvalho Chehab 10559a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); 10569a0bf528SMauro Carvalho Chehab /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ 10579a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); 10589a0bf528SMauro Carvalho Chehab 10599a0bf528SMauro Carvalho Chehab // never achieved a lock before - wait for timfreq to update 10609a0bf528SMauro Carvalho Chehab if (state->timf == 0) 10619a0bf528SMauro Carvalho Chehab msleep(200); 10629a0bf528SMauro Carvalho Chehab 10639a0bf528SMauro Carvalho Chehab //dump_reg(state); 10649a0bf528SMauro Carvalho Chehab /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ 10659a0bf528SMauro Carvalho Chehab value = (6 << 8) | 0x80; 10669a0bf528SMauro Carvalho Chehab switch (ch->transmission_mode) { 10679a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_2K: value |= (7 << 12); break; 10689a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_4K: value |= (8 << 12); break; 10699a0bf528SMauro Carvalho Chehab default: 10709a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_8K: value |= (9 << 12); break; 10719a0bf528SMauro Carvalho Chehab } 10729a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 26, value); 10739a0bf528SMauro Carvalho Chehab 10749a0bf528SMauro Carvalho Chehab /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ 10759a0bf528SMauro Carvalho Chehab value = (0 << 4); 10769a0bf528SMauro Carvalho Chehab switch (ch->transmission_mode) { 10779a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_2K: value |= 0x6; break; 10789a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_4K: value |= 0x7; break; 10799a0bf528SMauro Carvalho Chehab default: 10809a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_8K: value |= 0x8; break; 10819a0bf528SMauro Carvalho Chehab } 10829a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 32, value); 10839a0bf528SMauro Carvalho Chehab 10849a0bf528SMauro Carvalho Chehab /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ 10859a0bf528SMauro Carvalho Chehab value = (0 << 4); 10869a0bf528SMauro Carvalho Chehab switch (ch->transmission_mode) { 10879a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_2K: value |= 0x6; break; 10889a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_4K: value |= 0x7; break; 10899a0bf528SMauro Carvalho Chehab default: 10909a0bf528SMauro Carvalho Chehab case TRANSMISSION_MODE_8K: value |= 0x8; break; 10919a0bf528SMauro Carvalho Chehab } 10929a0bf528SMauro Carvalho Chehab ret |= dib7000m_write_word(state, 33, value); 10939a0bf528SMauro Carvalho Chehab 10949a0bf528SMauro Carvalho Chehab // we achieved a lock - it's time to update the timf freq 10959a0bf528SMauro Carvalho Chehab if ((dib7000m_read_word(state, 535) >> 6) & 0x1) 10969a0bf528SMauro Carvalho Chehab dib7000m_update_timf(state); 10979a0bf528SMauro Carvalho Chehab 10989a0bf528SMauro Carvalho Chehab dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz)); 10999a0bf528SMauro Carvalho Chehab return ret; 11009a0bf528SMauro Carvalho Chehab } 11019a0bf528SMauro Carvalho Chehab 11029a0bf528SMauro Carvalho Chehab static int dib7000m_wakeup(struct dvb_frontend *demod) 11039a0bf528SMauro Carvalho Chehab { 11049a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = demod->demodulator_priv; 11059a0bf528SMauro Carvalho Chehab 11069a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); 11079a0bf528SMauro Carvalho Chehab 11089a0bf528SMauro Carvalho Chehab if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) 110975702277SMauro Carvalho Chehab dprintk("could not start Slow ADC\n"); 11109a0bf528SMauro Carvalho Chehab 11119a0bf528SMauro Carvalho Chehab return 0; 11129a0bf528SMauro Carvalho Chehab } 11139a0bf528SMauro Carvalho Chehab 11149a0bf528SMauro Carvalho Chehab static int dib7000m_sleep(struct dvb_frontend *demod) 11159a0bf528SMauro Carvalho Chehab { 11169a0bf528SMauro Carvalho Chehab struct dib7000m_state *st = demod->demodulator_priv; 11179a0bf528SMauro Carvalho Chehab dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); 11189a0bf528SMauro Carvalho Chehab dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY); 11199a0bf528SMauro Carvalho Chehab return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | 11209a0bf528SMauro Carvalho Chehab dib7000m_set_adc_state(st, DIBX000_ADC_OFF); 11219a0bf528SMauro Carvalho Chehab } 11229a0bf528SMauro Carvalho Chehab 11239a0bf528SMauro Carvalho Chehab static int dib7000m_identify(struct dib7000m_state *state) 11249a0bf528SMauro Carvalho Chehab { 11259a0bf528SMauro Carvalho Chehab u16 value; 11269a0bf528SMauro Carvalho Chehab 11279a0bf528SMauro Carvalho Chehab if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { 112875702277SMauro Carvalho Chehab dprintk("wrong Vendor ID (0x%x)\n", value); 11299a0bf528SMauro Carvalho Chehab return -EREMOTEIO; 11309a0bf528SMauro Carvalho Chehab } 11319a0bf528SMauro Carvalho Chehab 11329a0bf528SMauro Carvalho Chehab state->revision = dib7000m_read_word(state, 897); 11339a0bf528SMauro Carvalho Chehab if (state->revision != 0x4000 && 11349a0bf528SMauro Carvalho Chehab state->revision != 0x4001 && 11359a0bf528SMauro Carvalho Chehab state->revision != 0x4002 && 11369a0bf528SMauro Carvalho Chehab state->revision != 0x4003) { 113775702277SMauro Carvalho Chehab dprintk("wrong Device ID (0x%x)\n", value); 11389a0bf528SMauro Carvalho Chehab return -EREMOTEIO; 11399a0bf528SMauro Carvalho Chehab } 11409a0bf528SMauro Carvalho Chehab 11419a0bf528SMauro Carvalho Chehab /* protect this driver to be used with 7000PC */ 11429a0bf528SMauro Carvalho Chehab if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { 114375702277SMauro Carvalho Chehab dprintk("this driver does not work with DiB7000PC\n"); 11449a0bf528SMauro Carvalho Chehab return -EREMOTEIO; 11459a0bf528SMauro Carvalho Chehab } 11469a0bf528SMauro Carvalho Chehab 11479a0bf528SMauro Carvalho Chehab switch (state->revision) { 114875702277SMauro Carvalho Chehab case 0x4000: dprintk("found DiB7000MA/PA/MB/PB\n"); break; 114975702277SMauro Carvalho Chehab case 0x4001: state->reg_offs = 1; dprintk("found DiB7000HC\n"); break; 115075702277SMauro Carvalho Chehab case 0x4002: state->reg_offs = 1; dprintk("found DiB7000MC\n"); break; 115175702277SMauro Carvalho Chehab case 0x4003: state->reg_offs = 1; dprintk("found DiB9000\n"); break; 11529a0bf528SMauro Carvalho Chehab } 11539a0bf528SMauro Carvalho Chehab 11549a0bf528SMauro Carvalho Chehab return 0; 11559a0bf528SMauro Carvalho Chehab } 11569a0bf528SMauro Carvalho Chehab 11579a0bf528SMauro Carvalho Chehab 11587e3e68bcSMauro Carvalho Chehab static int dib7000m_get_frontend(struct dvb_frontend* fe, 11597e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *fep) 11609a0bf528SMauro Carvalho Chehab { 11619a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 11629a0bf528SMauro Carvalho Chehab u16 tps = dib7000m_read_word(state,480); 11639a0bf528SMauro Carvalho Chehab 11649a0bf528SMauro Carvalho Chehab fep->inversion = INVERSION_AUTO; 11659a0bf528SMauro Carvalho Chehab 11669a0bf528SMauro Carvalho Chehab fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth); 11679a0bf528SMauro Carvalho Chehab 11689a0bf528SMauro Carvalho Chehab switch ((tps >> 8) & 0x3) { 11699a0bf528SMauro Carvalho Chehab case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break; 11709a0bf528SMauro Carvalho Chehab case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break; 11719a0bf528SMauro Carvalho Chehab /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */ 11729a0bf528SMauro Carvalho Chehab } 11739a0bf528SMauro Carvalho Chehab 11749a0bf528SMauro Carvalho Chehab switch (tps & 0x3) { 11759a0bf528SMauro Carvalho Chehab case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break; 11769a0bf528SMauro Carvalho Chehab case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break; 11779a0bf528SMauro Carvalho Chehab case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break; 11789a0bf528SMauro Carvalho Chehab case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break; 11799a0bf528SMauro Carvalho Chehab } 11809a0bf528SMauro Carvalho Chehab 11819a0bf528SMauro Carvalho Chehab switch ((tps >> 14) & 0x3) { 11829a0bf528SMauro Carvalho Chehab case 0: fep->modulation = QPSK; break; 11839a0bf528SMauro Carvalho Chehab case 1: fep->modulation = QAM_16; break; 11849a0bf528SMauro Carvalho Chehab case 2: 11859a0bf528SMauro Carvalho Chehab default: fep->modulation = QAM_64; break; 11869a0bf528SMauro Carvalho Chehab } 11879a0bf528SMauro Carvalho Chehab 11889a0bf528SMauro Carvalho Chehab /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ 11899a0bf528SMauro Carvalho Chehab /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ 11909a0bf528SMauro Carvalho Chehab 11919a0bf528SMauro Carvalho Chehab fep->hierarchy = HIERARCHY_NONE; 11929a0bf528SMauro Carvalho Chehab switch ((tps >> 5) & 0x7) { 11939a0bf528SMauro Carvalho Chehab case 1: fep->code_rate_HP = FEC_1_2; break; 11949a0bf528SMauro Carvalho Chehab case 2: fep->code_rate_HP = FEC_2_3; break; 11959a0bf528SMauro Carvalho Chehab case 3: fep->code_rate_HP = FEC_3_4; break; 11969a0bf528SMauro Carvalho Chehab case 5: fep->code_rate_HP = FEC_5_6; break; 11979a0bf528SMauro Carvalho Chehab case 7: 11989a0bf528SMauro Carvalho Chehab default: fep->code_rate_HP = FEC_7_8; break; 11999a0bf528SMauro Carvalho Chehab 12009a0bf528SMauro Carvalho Chehab } 12019a0bf528SMauro Carvalho Chehab 12029a0bf528SMauro Carvalho Chehab switch ((tps >> 2) & 0x7) { 12039a0bf528SMauro Carvalho Chehab case 1: fep->code_rate_LP = FEC_1_2; break; 12049a0bf528SMauro Carvalho Chehab case 2: fep->code_rate_LP = FEC_2_3; break; 12059a0bf528SMauro Carvalho Chehab case 3: fep->code_rate_LP = FEC_3_4; break; 12069a0bf528SMauro Carvalho Chehab case 5: fep->code_rate_LP = FEC_5_6; break; 12079a0bf528SMauro Carvalho Chehab case 7: 12089a0bf528SMauro Carvalho Chehab default: fep->code_rate_LP = FEC_7_8; break; 12099a0bf528SMauro Carvalho Chehab } 12109a0bf528SMauro Carvalho Chehab 12119a0bf528SMauro Carvalho Chehab /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */ 12129a0bf528SMauro Carvalho Chehab 12139a0bf528SMauro Carvalho Chehab return 0; 12149a0bf528SMauro Carvalho Chehab } 12159a0bf528SMauro Carvalho Chehab 12169a0bf528SMauro Carvalho Chehab static int dib7000m_set_frontend(struct dvb_frontend *fe) 12179a0bf528SMauro Carvalho Chehab { 12189a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *fep = &fe->dtv_property_cache; 12199a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 12209a0bf528SMauro Carvalho Chehab int time, ret; 12219a0bf528SMauro Carvalho Chehab 12229a0bf528SMauro Carvalho Chehab dib7000m_set_output_mode(state, OUTMODE_HIGH_Z); 12239a0bf528SMauro Carvalho Chehab 12249a0bf528SMauro Carvalho Chehab dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz)); 12259a0bf528SMauro Carvalho Chehab 12269a0bf528SMauro Carvalho Chehab if (fe->ops.tuner_ops.set_params) 12279a0bf528SMauro Carvalho Chehab fe->ops.tuner_ops.set_params(fe); 12289a0bf528SMauro Carvalho Chehab 12299a0bf528SMauro Carvalho Chehab /* start up the AGC */ 12309a0bf528SMauro Carvalho Chehab state->agc_state = 0; 12319a0bf528SMauro Carvalho Chehab do { 12329a0bf528SMauro Carvalho Chehab time = dib7000m_agc_startup(fe); 12339a0bf528SMauro Carvalho Chehab if (time != -1) 12349a0bf528SMauro Carvalho Chehab msleep(time); 12359a0bf528SMauro Carvalho Chehab } while (time != -1); 12369a0bf528SMauro Carvalho Chehab 12379a0bf528SMauro Carvalho Chehab if (fep->transmission_mode == TRANSMISSION_MODE_AUTO || 12389a0bf528SMauro Carvalho Chehab fep->guard_interval == GUARD_INTERVAL_AUTO || 12399a0bf528SMauro Carvalho Chehab fep->modulation == QAM_AUTO || 12409a0bf528SMauro Carvalho Chehab fep->code_rate_HP == FEC_AUTO) { 12419a0bf528SMauro Carvalho Chehab int i = 800, found; 12429a0bf528SMauro Carvalho Chehab 12439a0bf528SMauro Carvalho Chehab dib7000m_autosearch_start(fe); 12449a0bf528SMauro Carvalho Chehab do { 12459a0bf528SMauro Carvalho Chehab msleep(1); 12469a0bf528SMauro Carvalho Chehab found = dib7000m_autosearch_is_irq(fe); 12479a0bf528SMauro Carvalho Chehab } while (found == 0 && i--); 12489a0bf528SMauro Carvalho Chehab 124975702277SMauro Carvalho Chehab dprintk("autosearch returns: %d\n", found); 12509a0bf528SMauro Carvalho Chehab if (found == 0 || found == 1) 12519a0bf528SMauro Carvalho Chehab return 0; // no channel found 12529a0bf528SMauro Carvalho Chehab 12537e3e68bcSMauro Carvalho Chehab dib7000m_get_frontend(fe, fep); 12549a0bf528SMauro Carvalho Chehab } 12559a0bf528SMauro Carvalho Chehab 12569a0bf528SMauro Carvalho Chehab ret = dib7000m_tune(fe); 12579a0bf528SMauro Carvalho Chehab 12589a0bf528SMauro Carvalho Chehab /* make this a config parameter */ 12599a0bf528SMauro Carvalho Chehab dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); 12609a0bf528SMauro Carvalho Chehab return ret; 12619a0bf528SMauro Carvalho Chehab } 12629a0bf528SMauro Carvalho Chehab 12630df289a2SMauro Carvalho Chehab static int dib7000m_read_status(struct dvb_frontend *fe, enum fe_status *stat) 12649a0bf528SMauro Carvalho Chehab { 12659a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 12669a0bf528SMauro Carvalho Chehab u16 lock = dib7000m_read_word(state, 535); 12679a0bf528SMauro Carvalho Chehab 12689a0bf528SMauro Carvalho Chehab *stat = 0; 12699a0bf528SMauro Carvalho Chehab 12709a0bf528SMauro Carvalho Chehab if (lock & 0x8000) 12719a0bf528SMauro Carvalho Chehab *stat |= FE_HAS_SIGNAL; 12729a0bf528SMauro Carvalho Chehab if (lock & 0x3000) 12739a0bf528SMauro Carvalho Chehab *stat |= FE_HAS_CARRIER; 12749a0bf528SMauro Carvalho Chehab if (lock & 0x0100) 12759a0bf528SMauro Carvalho Chehab *stat |= FE_HAS_VITERBI; 12769a0bf528SMauro Carvalho Chehab if (lock & 0x0010) 12779a0bf528SMauro Carvalho Chehab *stat |= FE_HAS_SYNC; 12789a0bf528SMauro Carvalho Chehab if (lock & 0x0008) 12799a0bf528SMauro Carvalho Chehab *stat |= FE_HAS_LOCK; 12809a0bf528SMauro Carvalho Chehab 12819a0bf528SMauro Carvalho Chehab return 0; 12829a0bf528SMauro Carvalho Chehab } 12839a0bf528SMauro Carvalho Chehab 12849a0bf528SMauro Carvalho Chehab static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber) 12859a0bf528SMauro Carvalho Chehab { 12869a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 12879a0bf528SMauro Carvalho Chehab *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527); 12889a0bf528SMauro Carvalho Chehab return 0; 12899a0bf528SMauro Carvalho Chehab } 12909a0bf528SMauro Carvalho Chehab 12919a0bf528SMauro Carvalho Chehab static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) 12929a0bf528SMauro Carvalho Chehab { 12939a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 12949a0bf528SMauro Carvalho Chehab *unc = dib7000m_read_word(state, 534); 12959a0bf528SMauro Carvalho Chehab return 0; 12969a0bf528SMauro Carvalho Chehab } 12979a0bf528SMauro Carvalho Chehab 12989a0bf528SMauro Carvalho Chehab static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 12999a0bf528SMauro Carvalho Chehab { 13009a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 13019a0bf528SMauro Carvalho Chehab u16 val = dib7000m_read_word(state, 390); 13029a0bf528SMauro Carvalho Chehab *strength = 65535 - val; 13039a0bf528SMauro Carvalho Chehab return 0; 13049a0bf528SMauro Carvalho Chehab } 13059a0bf528SMauro Carvalho Chehab 13069a0bf528SMauro Carvalho Chehab static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr) 13079a0bf528SMauro Carvalho Chehab { 13089a0bf528SMauro Carvalho Chehab *snr = 0x0000; 13099a0bf528SMauro Carvalho Chehab return 0; 13109a0bf528SMauro Carvalho Chehab } 13119a0bf528SMauro Carvalho Chehab 13129a0bf528SMauro Carvalho Chehab static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 13139a0bf528SMauro Carvalho Chehab { 13149a0bf528SMauro Carvalho Chehab tune->min_delay_ms = 1000; 13159a0bf528SMauro Carvalho Chehab return 0; 13169a0bf528SMauro Carvalho Chehab } 13179a0bf528SMauro Carvalho Chehab 13189a0bf528SMauro Carvalho Chehab static void dib7000m_release(struct dvb_frontend *demod) 13199a0bf528SMauro Carvalho Chehab { 13209a0bf528SMauro Carvalho Chehab struct dib7000m_state *st = demod->demodulator_priv; 13219a0bf528SMauro Carvalho Chehab dibx000_exit_i2c_master(&st->i2c_master); 13229a0bf528SMauro Carvalho Chehab kfree(st); 13239a0bf528SMauro Carvalho Chehab } 13249a0bf528SMauro Carvalho Chehab 13259a0bf528SMauro Carvalho Chehab struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) 13269a0bf528SMauro Carvalho Chehab { 13279a0bf528SMauro Carvalho Chehab struct dib7000m_state *st = demod->demodulator_priv; 13289a0bf528SMauro Carvalho Chehab return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); 13299a0bf528SMauro Carvalho Chehab } 13309a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000m_get_i2c_master); 13319a0bf528SMauro Carvalho Chehab 13329a0bf528SMauro Carvalho Chehab int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) 13339a0bf528SMauro Carvalho Chehab { 13349a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 13359a0bf528SMauro Carvalho Chehab u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef; 13369a0bf528SMauro Carvalho Chehab val |= (onoff & 0x1) << 4; 133775702277SMauro Carvalho Chehab dprintk("PID filter enabled %d\n", onoff); 13389a0bf528SMauro Carvalho Chehab return dib7000m_write_word(state, 294 + state->reg_offs, val); 13399a0bf528SMauro Carvalho Chehab } 13409a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000m_pid_filter_ctrl); 13419a0bf528SMauro Carvalho Chehab 13429a0bf528SMauro Carvalho Chehab int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) 13439a0bf528SMauro Carvalho Chehab { 13449a0bf528SMauro Carvalho Chehab struct dib7000m_state *state = fe->demodulator_priv; 134575702277SMauro Carvalho Chehab dprintk("PID filter: index %x, PID %d, OnOff %d\n", id, pid, onoff); 13469a0bf528SMauro Carvalho Chehab return dib7000m_write_word(state, 300 + state->reg_offs + id, 13479a0bf528SMauro Carvalho Chehab onoff ? (1 << 13) | pid : 0); 13489a0bf528SMauro Carvalho Chehab } 13499a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000m_pid_filter); 13509a0bf528SMauro Carvalho Chehab 13519a0bf528SMauro Carvalho Chehab #if 0 13529a0bf528SMauro Carvalho Chehab /* used with some prototype boards */ 13539a0bf528SMauro Carvalho Chehab int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, 13549a0bf528SMauro Carvalho Chehab u8 default_addr, struct dib7000m_config cfg[]) 13559a0bf528SMauro Carvalho Chehab { 13569a0bf528SMauro Carvalho Chehab struct dib7000m_state st = { .i2c_adap = i2c }; 13579a0bf528SMauro Carvalho Chehab int k = 0; 13589a0bf528SMauro Carvalho Chehab u8 new_addr = 0; 13599a0bf528SMauro Carvalho Chehab 13609a0bf528SMauro Carvalho Chehab for (k = no_of_demods-1; k >= 0; k--) { 13619a0bf528SMauro Carvalho Chehab st.cfg = cfg[k]; 13629a0bf528SMauro Carvalho Chehab 13639a0bf528SMauro Carvalho Chehab /* designated i2c address */ 13649a0bf528SMauro Carvalho Chehab new_addr = (0x40 + k) << 1; 13659a0bf528SMauro Carvalho Chehab st.i2c_addr = new_addr; 13669a0bf528SMauro Carvalho Chehab if (dib7000m_identify(&st) != 0) { 13679a0bf528SMauro Carvalho Chehab st.i2c_addr = default_addr; 13689a0bf528SMauro Carvalho Chehab if (dib7000m_identify(&st) != 0) { 136975702277SMauro Carvalho Chehab dprintk("DiB7000M #%d: not identified\n", k); 13709a0bf528SMauro Carvalho Chehab return -EIO; 13719a0bf528SMauro Carvalho Chehab } 13729a0bf528SMauro Carvalho Chehab } 13739a0bf528SMauro Carvalho Chehab 13749a0bf528SMauro Carvalho Chehab /* start diversity to pull_down div_str - just for i2c-enumeration */ 13759a0bf528SMauro Carvalho Chehab dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); 13769a0bf528SMauro Carvalho Chehab 13779a0bf528SMauro Carvalho Chehab dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output 13789a0bf528SMauro Carvalho Chehab 13799a0bf528SMauro Carvalho Chehab /* set new i2c address and force divstart */ 13809a0bf528SMauro Carvalho Chehab dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); 13819a0bf528SMauro Carvalho Chehab 138275702277SMauro Carvalho Chehab dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); 13839a0bf528SMauro Carvalho Chehab } 13849a0bf528SMauro Carvalho Chehab 13859a0bf528SMauro Carvalho Chehab for (k = 0; k < no_of_demods; k++) { 13869a0bf528SMauro Carvalho Chehab st.cfg = cfg[k]; 13879a0bf528SMauro Carvalho Chehab st.i2c_addr = (0x40 + k) << 1; 13889a0bf528SMauro Carvalho Chehab 13899a0bf528SMauro Carvalho Chehab // unforce divstr 13909a0bf528SMauro Carvalho Chehab dib7000m_write_word(&st,1794, st.i2c_addr << 2); 13919a0bf528SMauro Carvalho Chehab 13929a0bf528SMauro Carvalho Chehab /* deactivate div - it was just for i2c-enumeration */ 13939a0bf528SMauro Carvalho Chehab dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); 13949a0bf528SMauro Carvalho Chehab } 13959a0bf528SMauro Carvalho Chehab 13969a0bf528SMauro Carvalho Chehab return 0; 13979a0bf528SMauro Carvalho Chehab } 13989a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000m_i2c_enumeration); 13999a0bf528SMauro Carvalho Chehab #endif 14009a0bf528SMauro Carvalho Chehab 1401bd336e63SMax Kellermann static const struct dvb_frontend_ops dib7000m_ops; 14029a0bf528SMauro Carvalho Chehab struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) 14039a0bf528SMauro Carvalho Chehab { 14049a0bf528SMauro Carvalho Chehab struct dvb_frontend *demod; 14059a0bf528SMauro Carvalho Chehab struct dib7000m_state *st; 14069a0bf528SMauro Carvalho Chehab st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); 14079a0bf528SMauro Carvalho Chehab if (st == NULL) 14089a0bf528SMauro Carvalho Chehab return NULL; 14099a0bf528SMauro Carvalho Chehab 14109a0bf528SMauro Carvalho Chehab memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); 14119a0bf528SMauro Carvalho Chehab st->i2c_adap = i2c_adap; 14129a0bf528SMauro Carvalho Chehab st->i2c_addr = i2c_addr; 14139a0bf528SMauro Carvalho Chehab 14149a0bf528SMauro Carvalho Chehab demod = &st->demod; 14159a0bf528SMauro Carvalho Chehab demod->demodulator_priv = st; 14169a0bf528SMauro Carvalho Chehab memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); 14179a0bf528SMauro Carvalho Chehab mutex_init(&st->i2c_buffer_lock); 14189a0bf528SMauro Carvalho Chehab 14199a0bf528SMauro Carvalho Chehab st->timf_default = cfg->bw->timf; 14209a0bf528SMauro Carvalho Chehab 14219a0bf528SMauro Carvalho Chehab if (dib7000m_identify(st) != 0) 14229a0bf528SMauro Carvalho Chehab goto error; 14239a0bf528SMauro Carvalho Chehab 14249a0bf528SMauro Carvalho Chehab if (st->revision == 0x4000) 14259a0bf528SMauro Carvalho Chehab dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); 14269a0bf528SMauro Carvalho Chehab else 14279a0bf528SMauro Carvalho Chehab dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); 14289a0bf528SMauro Carvalho Chehab 14299a0bf528SMauro Carvalho Chehab dib7000m_demod_reset(st); 14309a0bf528SMauro Carvalho Chehab 14319a0bf528SMauro Carvalho Chehab return demod; 14329a0bf528SMauro Carvalho Chehab 14339a0bf528SMauro Carvalho Chehab error: 14349a0bf528SMauro Carvalho Chehab kfree(st); 14359a0bf528SMauro Carvalho Chehab return NULL; 14369a0bf528SMauro Carvalho Chehab } 14379a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(dib7000m_attach); 14389a0bf528SMauro Carvalho Chehab 1439bd336e63SMax Kellermann static const struct dvb_frontend_ops dib7000m_ops = { 14409a0bf528SMauro Carvalho Chehab .delsys = { SYS_DVBT }, 14419a0bf528SMauro Carvalho Chehab .info = { 14429a0bf528SMauro Carvalho Chehab .name = "DiBcom 7000MA/MB/PA/PB/MC", 1443f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 44250 * kHz, 1444f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 867250 * kHz, 1445f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 14469a0bf528SMauro Carvalho Chehab .caps = FE_CAN_INVERSION_AUTO | 14479a0bf528SMauro Carvalho Chehab FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 14489a0bf528SMauro Carvalho Chehab FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 14499a0bf528SMauro Carvalho Chehab FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 14509a0bf528SMauro Carvalho Chehab FE_CAN_TRANSMISSION_MODE_AUTO | 14519a0bf528SMauro Carvalho Chehab FE_CAN_GUARD_INTERVAL_AUTO | 14529a0bf528SMauro Carvalho Chehab FE_CAN_RECOVER | 14539a0bf528SMauro Carvalho Chehab FE_CAN_HIERARCHY_AUTO, 14549a0bf528SMauro Carvalho Chehab }, 14559a0bf528SMauro Carvalho Chehab 14569a0bf528SMauro Carvalho Chehab .release = dib7000m_release, 14579a0bf528SMauro Carvalho Chehab 14589a0bf528SMauro Carvalho Chehab .init = dib7000m_wakeup, 14599a0bf528SMauro Carvalho Chehab .sleep = dib7000m_sleep, 14609a0bf528SMauro Carvalho Chehab 14619a0bf528SMauro Carvalho Chehab .set_frontend = dib7000m_set_frontend, 14629a0bf528SMauro Carvalho Chehab .get_tune_settings = dib7000m_fe_get_tune_settings, 14639a0bf528SMauro Carvalho Chehab .get_frontend = dib7000m_get_frontend, 14649a0bf528SMauro Carvalho Chehab 14659a0bf528SMauro Carvalho Chehab .read_status = dib7000m_read_status, 14669a0bf528SMauro Carvalho Chehab .read_ber = dib7000m_read_ber, 14679a0bf528SMauro Carvalho Chehab .read_signal_strength = dib7000m_read_signal_strength, 14689a0bf528SMauro Carvalho Chehab .read_snr = dib7000m_read_snr, 14699a0bf528SMauro Carvalho Chehab .read_ucblocks = dib7000m_read_unc_blocks, 14709a0bf528SMauro Carvalho Chehab }; 14719a0bf528SMauro Carvalho Chehab 147299e44da7SPatrick Boettcher MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 14739a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); 14749a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1475