^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This code is more or less generated from another driver, please
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * excuse some codingstyle oddities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "dib0070.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "dibx000_common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define dprintk(fmt, arg...) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) printk(KERN_DEBUG pr_fmt("%s: " fmt), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) __func__, ##arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DIB0070_P1D 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DIB0070_P1F 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DIB0070_P1G 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DIB0070S_P1A 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct dib0070_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct dvb_frontend *fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const struct dib0070_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u16 wbd_ff_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u8 revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) enum frontend_tune_state tune_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u32 current_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* for the captrim binary search */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) s8 step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u16 adc_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) s8 captrim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) s8 fcaptrim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u16 lo4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct dib0070_tuning *current_tune_table_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) const struct dib0070_lna_match *lna_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 wbd_gain_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u16 wbd_offset_3_3[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* for the I2C transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct i2c_msg msg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u8 i2c_write_buffer[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u8 i2c_read_buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct mutex i2c_buffer_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u16 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dprintk("could not acquire lock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) state->i2c_write_buffer[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) state->msg[0].addr = state->cfg->i2c_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) state->msg[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) state->msg[0].buf = state->i2c_write_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) state->msg[0].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) state->msg[1].addr = state->cfg->i2c_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) state->msg[1].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) state->msg[1].buf = state->i2c_read_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) state->msg[1].len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pr_warn("DiB0070 I2C read failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ret = (state->i2c_read_buffer[0] << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) | state->i2c_read_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mutex_unlock(&state->i2c_buffer_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dprintk("could not acquire lock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) state->i2c_write_buffer[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) state->i2c_write_buffer[1] = val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) state->i2c_write_buffer[2] = val & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) memset(state->msg, 0, sizeof(struct i2c_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) state->msg[0].addr = state->cfg->i2c_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) state->msg[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) state->msg[0].buf = state->i2c_write_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) state->msg[0].len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pr_warn("DiB0070 I2C write failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mutex_unlock(&state->i2c_buffer_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define HARD_RESET(state) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) state->cfg->sleep(state->fe, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (state->cfg->reset) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) state->cfg->reset(state->fe,1); msleep(10); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) state->cfg->reset(state->fe,0); msleep(10); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int dib0070_set_bandwidth(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) tmp |= (0 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) tmp |= (1 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tmp |= (2 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) tmp |= (3 << 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dib0070_write_reg(state, 0x02, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u16 value = dib0070_read_reg(state, 0x17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dib0070_write_reg(state, 0x17, value & 0xfffc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dib0070_write_reg(state, 0x01, tmp | (60 << 9));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dib0070_write_reg(state, 0x17, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int8_t step_sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u16 adc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (*tune_state == CT_TUNER_STEP_0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dib0070_write_reg(state, 0x0f, 0xed10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dib0070_write_reg(state, 0x17, 0x0034);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dib0070_write_reg(state, 0x18, 0x0032);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) state->step = state->captrim = state->fcaptrim = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) state->adc_diff = 3000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ret = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) *tune_state = CT_TUNER_STEP_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) } else if (*tune_state == CT_TUNER_STEP_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) state->step /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *tune_state = CT_TUNER_STEP_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) } else if (*tune_state == CT_TUNER_STEP_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) adc = dib0070_read_reg(state, 0x19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dprintk("CAPTRIM=%d; ADC = %hd (ADC) & %dmV\n", state->captrim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) adc, (u32)adc * (u32)1800 / (u32)1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (adc >= 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) adc -= 400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) step_sign = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) adc = 400 - adc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) step_sign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (adc < state->adc_diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dprintk("CAPTRIM=%d is closer to target (%hd/%hd)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) state->captrim, adc, state->adc_diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) state->adc_diff = adc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) state->fcaptrim = state->captrim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) state->captrim += (step_sign * state->step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (state->step >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *tune_state = CT_TUNER_STEP_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *tune_state = CT_TUNER_STEP_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else if (*tune_state == CT_TUNER_STEP_3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) dib0070_write_reg(state, 0x18, 0x07ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *tune_state = CT_TUNER_STEP_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dprintk("CTRL_LO5: 0x%x\n", lo5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return dib0070_write_reg(state, 0x15, lo5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) dib0070_write_reg(state, 0x1b, 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dib0070_write_reg(state, 0x1a, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dib0070_write_reg(state, 0x1b, 0x4112);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (state->cfg->vga_filter != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dib0070_write_reg(state, 0x1a, 0x0009);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct dib0070_tuning {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u8 switch_trim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) u8 vco_band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u8 hfdiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u8 vco_multi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 presc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u8 wbdmux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) u16 tuner_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct dib0070_lna_match {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 lna_band;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static const struct dib0070_tuning dib0070s_tuning_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static const struct dib0070_tuning dib0070_tuning_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { 180000, 0 }, /* VHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) { 188000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { 196400, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) { 250000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) { 550000, 0 }, /* UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { 590000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { 666000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) { 864000, 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) { 1500000, 0 }, /* LBAND or everything higher than UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) { 1600000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) { 2000000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) { 0xffffffff, 7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const struct dib0070_lna_match dib0070_lna[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { 180000, 0 }, /* VHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) { 188000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) { 196400, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) { 250000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) { 550000, 2 }, /* UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) { 650000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { 750000, 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { 850000, 6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { 864000, 7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) { 1500000, 0 }, /* LBAND or everything higher than UHF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) { 1600000, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) { 2000000, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) { 0xffffffff, 7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) #define LPF 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int dib0070_tune_digital(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) const struct dib0070_tuning *tune;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) const struct dib0070_lna_match *lna_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) enum frontend_tune_state *tune_state = &state->tune_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int ret = 10; /* 1ms is the default delay most of the time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #ifdef CONFIG_SYS_ISDBT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) freq += 850;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (state->current_rf != freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) switch (state->revision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case DIB0070S_P1A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) tune = dib0070s_tuning_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) lna_match = dib0070_lna;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) tune = dib0070_tuning_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (state->cfg->flip_chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) lna_match = dib0070_lna_flip_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) lna_match = dib0070_lna;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) while (freq > tune->max_freq) /* find the right one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) tune++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) while (freq > lna_match->max_freq) /* find the right one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) lna_match++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) state->current_tune_table_index = tune;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) state->lna_match = lna_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (*tune_state == CT_TUNER_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dprintk("Tuning for Band: %d (%d kHz)\n", band, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (state->current_rf != freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 REFDIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) u32 FBDiv, Rest, FREF, VCOF_kHz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u8 Den;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) state->current_rf = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) dib0070_write_reg(state, 0x17, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) switch (band) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case BAND_VHF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case BAND_FM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) REFDIV = (u8) (state->cfg->clock_khz / 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) FREF = state->cfg->clock_khz / REFDIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) switch (state->revision) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) case DIB0070S_P1A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case DIB0070_P1G:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case DIB0070_P1F:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) FBDiv = (freq / (FREF / 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) Rest = 2 * freq - FBDiv * FREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (Rest < LPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) Rest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) else if (Rest < 2 * LPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) Rest = 2 * LPF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) else if (Rest > (FREF - LPF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) Rest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) FBDiv += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) } else if (Rest > (FREF - 2 * LPF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) Rest = FREF - 2 * LPF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) Rest = (Rest * 6528) / (FREF / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) Den = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (Rest > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) state->lo4 |= (1 << 14) | (1 << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) Den = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) dib0070_write_reg(state, 0x11, (u16)FBDiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dib0070_write_reg(state, 0x13, (u16) Rest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (state->revision == DIB0070S_P1A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (band == BAND_SBAND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dib0070_write_reg(state, 0x1d, 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) dib0070_write_reg(state, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) dprintk("REFDIV: %u, FREF: %d\n", REFDIV, FREF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) dprintk("Num: %u, Den: %u, SD: %d\n", (u16)Rest, Den,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) (state->lo4 >> 12) & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dprintk("HFDIV code: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) state->current_tune_table_index->hfdiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dprintk("VCO = %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) state->current_tune_table_index->vco_band);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dprintk("VCOF: ((%u*%d) << 1))\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) state->current_tune_table_index->vco_multi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) *tune_state = CT_TUNER_STEP_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) } else { /* we are already tuned to this frequency - the configuration is correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret = 50; /* wakeup time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *tune_state = CT_TUNER_STEP_5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ret = dib0070_captrim(state, tune_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) } else if (*tune_state == CT_TUNER_STEP_4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (tmp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) while (freq/1000 > tmp->freq) /* find the right one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) tmp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dib0070_write_reg(state, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) (0 << 15) | (1 << 14) | (3 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) | (state->current_tune_table_index->wbdmux << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) state->wbd_gain_current = tmp->wbd_gain_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dib0070_write_reg(state, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) (0 << 15) | (1 << 14) | (3 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) | (6 << 9) | (0 << 8) | (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) | (state->current_tune_table_index->wbdmux << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) state->wbd_gain_current = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) dib0070_write_reg(state, 0x06, 0x3fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dib0070_write_reg(state, 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dib0070_write_reg(state, 0x0d, 0x0d80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dib0070_write_reg(state, 0x18, 0x07ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dib0070_write_reg(state, 0x17, 0x0033);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) *tune_state = CT_TUNER_STEP_5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) } else if (*tune_state == CT_TUNER_STEP_5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dib0070_set_bandwidth(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *tune_state = CT_TUNER_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static int dib0070_tune(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) uint32_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) state->tune_state = CT_TUNER_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = dib0070_tune_digital(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (ret != FE_CALLBACK_TIME_NEVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) msleep(ret/10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) } while (state->tune_state != CT_TUNER_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int dib0070_wakeup(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (state->cfg->sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) state->cfg->sleep(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static int dib0070_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (state->cfg->sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) state->cfg->sleep(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) u8 dib0070_get_rf_output(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) EXPORT_SYMBOL(dib0070_get_rf_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (no > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) no = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (no < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) no = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) EXPORT_SYMBOL(dib0070_set_rf_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static const u16 dib0070_p1f_defaults[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 7, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 0x0008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 0x0002,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 3, 0x0d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 0x0d80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 0x0001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 4, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 0x0103,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 3, 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 0x0004 | 0x0040,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 0x0030,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 0x07ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 6, 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 0x4112,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 0xff00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 0xc07f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 0x0180,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) u16 tuner_en = dib0070_read_reg(state, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) u16 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dib0070_write_reg(state, 0x18, 0x07ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) msleep(9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) offset = dib0070_read_reg(state, 0x19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dib0070_write_reg(state, 0x20, tuner_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) u8 gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) for (gain = 6; gain < 8; gain++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) u16 dib0070_wbd_offset(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) u32 freq = fe->dtv_property_cache.frequency/1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (tmp != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) while (freq/1000 > tmp->freq) /* find the right one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tmp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) state->wbd_gain_current = tmp->wbd_gain_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) state->wbd_gain_current = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return state->wbd_offset_3_3[state->wbd_gain_current - 6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) EXPORT_SYMBOL(dib0070_wbd_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) #define pgm_read_word(w) (*w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int dib0070_reset(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) u16 l, r, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) HARD_RESET(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) #ifndef FORCE_SBAND_TUNER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) #warning forcing SBAND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) state->revision = DIB0070S_P1A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /* P1F or not */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dprintk("Revision: %x\n", state->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (state->revision == DIB0070_P1D) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) n = (u16 *) dib0070_p1f_defaults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) l = pgm_read_word(n++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) while (l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) r = pgm_read_word(n++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) r++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) } while (--l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) l = pgm_read_word(n++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (state->cfg->force_crystal_mode != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) r = state->cfg->force_crystal_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) else if (state->cfg->clock_khz >= 24000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) r = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) r = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) r |= state->cfg->osc_buffer_state << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) dib0070_write_reg(state, 0x10, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (state->cfg->invert_iq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) r = dib0070_read_reg(state, 0x02) & 0xffdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) dib0070_write_reg(state, 0x02, r | (1 << 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (state->revision == DIB0070S_P1A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) state->cfg->enable_third_order_filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) dib0070_wbd_offset_calibration(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct dib0070_state *state = fe->tuner_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) *frequency = 1000 * state->current_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static void dib0070_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) kfree(fe->tuner_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static const struct dvb_tuner_ops dib0070_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .name = "DiBcom DiB0070",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .frequency_min_hz = 45 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .frequency_max_hz = 860 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .frequency_step_hz = 1 * kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .release = dib0070_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .init = dib0070_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .sleep = dib0070_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .set_params = dib0070_tune,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .get_frequency = dib0070_get_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) // .get_bandwidth = dib0070_get_bandwidth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) state->cfg = cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) state->fe = fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) mutex_init(&state->i2c_buffer_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) fe->tuner_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (dib0070_reset(fe) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) goto free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) pr_info("DiB0070: successfully identified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) fe->tuner_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) free_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) fe->tuner_priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) EXPORT_SYMBOL(dib0070_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) MODULE_LICENSE("GPL");