^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) * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * LGDT3304 support by Jarod Wilson <jarod@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/dvb/frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <media/dvb_math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "lgdt3305.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) module_param(debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define DBG_INFO 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DBG_REG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define lg_printk(kern, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) printk(kern "%s: " fmt, __func__, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3305: " fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) lg_printk(KERN_DEBUG, fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define lg_reg(fmt, arg...) if (debug & DBG_REG) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) lg_printk(KERN_DEBUG, fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define lg_fail(ret) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) __ret = (ret < 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (__ret) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) lg_err("error %d on line %d\n", ret, __LINE__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct lgdt3305_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct i2c_adapter *i2c_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const struct lgdt3305_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) enum fe_modulation current_modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u32 current_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* FIXME: verify & document the LGDT3304 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define LGDT3305_GEN_CTRL_1 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define LGDT3305_GEN_CTRL_2 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define LGDT3305_GEN_CTRL_3 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define LGDT3305_GEN_STATUS 0x0003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define LGDT3305_GEN_CONTROL 0x0007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define LGDT3305_GEN_CTRL_4 0x000a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define LGDT3305_DGTL_AGC_REF_1 0x0012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define LGDT3305_DGTL_AGC_REF_2 0x0013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define LGDT3305_CR_CTR_FREQ_1 0x0106
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define LGDT3305_CR_CTR_FREQ_2 0x0107
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LGDT3305_CR_CTR_FREQ_3 0x0108
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define LGDT3305_CR_CTR_FREQ_4 0x0109
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define LGDT3305_CR_MSE_1 0x011b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define LGDT3305_CR_MSE_2 0x011c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define LGDT3305_CR_LOCK_STATUS 0x011d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define LGDT3305_CR_CTRL_7 0x0126
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define LGDT3305_AGC_POWER_REF_1 0x0300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define LGDT3305_AGC_POWER_REF_2 0x0301
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define LGDT3305_AGC_DELAY_PT_1 0x0302
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define LGDT3305_AGC_DELAY_PT_2 0x0303
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define LGDT3305_RFAGC_LOOP_FLTR_BW_1 0x0306
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define LGDT3305_RFAGC_LOOP_FLTR_BW_2 0x0307
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define LGDT3305_IFBW_1 0x0308
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define LGDT3305_IFBW_2 0x0309
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define LGDT3305_AGC_CTRL_1 0x030c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define LGDT3305_AGC_CTRL_4 0x0314
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define LGDT3305_EQ_MSE_1 0x0413
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define LGDT3305_EQ_MSE_2 0x0414
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define LGDT3305_EQ_MSE_3 0x0415
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define LGDT3305_PT_MSE_1 0x0417
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define LGDT3305_PT_MSE_2 0x0418
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define LGDT3305_PT_MSE_3 0x0419
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define LGDT3305_FEC_BLOCK_CTRL 0x0504
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define LGDT3305_FEC_LOCK_STATUS 0x050a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define LGDT3305_FEC_PKT_ERR_1 0x050c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define LGDT3305_FEC_PKT_ERR_2 0x050d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define LGDT3305_TP_CTRL_1 0x050e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define LGDT3305_BERT_PERIOD 0x0801
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define LGDT3305_BERT_ERROR_COUNT_1 0x080a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define LGDT3305_BERT_ERROR_COUNT_2 0x080b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define LGDT3305_BERT_ERROR_COUNT_3 0x080c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define LGDT3305_BERT_ERROR_COUNT_4 0x080d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 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) u8 buf[] = { reg >> 8, reg & 0xff, val };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .addr = state->cfg->i2c_addr, .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .buf = buf, .len = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = i2c_transfer(state->i2c_adap, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (ret != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) msg.buf[0], msg.buf[1], msg.buf[2], ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u8 reg_buf[] = { reg >> 8, reg & 0xff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { .addr = state->cfg->i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .flags = 0, .buf = reg_buf, .len = 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { .addr = state->cfg->i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .flags = I2C_M_RD, .buf = val, .len = 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) lg_reg("reg: 0x%04x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = i2c_transfer(state->i2c_adap, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) lg_err("error (addr %02x reg %04x error (ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) state->cfg->i2c_addr, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define read_reg(state, reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u8 __val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int ret = lgdt3305_read_reg(state, reg, &__val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (lg_fail(ret)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) __val = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) __val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static int lgdt3305_set_reg_bit(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u16 reg, int bit, int onoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = lgdt3305_read_reg(state, reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) val &= ~(1 << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) val |= (onoff & 1) << bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = lgdt3305_write_reg(state, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct lgdt3305_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int lgdt3305_write_regs(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct lgdt3305_reg *regs, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) lg_reg("writing %d registers...\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (i = 0; i < len - 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int lgdt3305_soft_reset(struct lgdt3305_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) enum lgdt3305_mpeg_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) lg_dbg("(%d)\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
^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 lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) enum lgdt3305_tp_clock_mode mode = state->cfg->tpclk_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) lg_dbg("edge = %d, valid = %d\n", edge, valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) val &= ~0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (edge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) val |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) val |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) val |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ret = lgdt3305_soft_reset(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int lgdt3305_set_modulation(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) u8 opermode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) opermode &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) opermode |= 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) opermode |= 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) opermode |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return ret;
^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 int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) lg_dbg("val = %d\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return lgdt3305_set_reg_bit(state, 0x043f, 2, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) u16 agc_ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) agc_ref = 0x32c4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) agc_ref = 0x2a00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) agc_ref = 0x2a80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) lg_dbg("agc ref: 0x%04x\n", agc_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u16 ifbw, rfbw, agcdelay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) agcdelay = 0x04c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) rfbw = 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ifbw = 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) agcdelay = 0x046b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) rfbw = 0x8889;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* FIXME: investigate optimal ifbw & rfbw values for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * DT3304 and re-write this switch..case block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (state->cfg->demod_chip == LGDT3304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ifbw = 0x6666;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) else /* (state->cfg->demod_chip == LGDT3305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ifbw = 0x8888;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (state->cfg->rf_agc_loop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* rf agc loop filter bandwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) agcdelay >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) agcdelay & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) rfbw >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) rfbw & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) lg_dbg("ifbw: 0x%04x\n", ifbw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* if agc loop filter bandwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int lgdt3305_agc_setup(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int lockdten, acqen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) lockdten = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) acqen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) lockdten = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) acqen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* control agc function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) switch (state->cfg->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case LGDT3304:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) case LGDT3305:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return lgdt3305_rfagc_loop(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) u16 usref = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (state->cfg->usref_8vsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) usref = state->cfg->usref_8vsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (state->cfg->usref_qam64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) usref = state->cfg->usref_qam64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (state->cfg->usref_qam256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) usref = state->cfg->usref_qam256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (usref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) lg_dbg("set manual mode: 0x%04x\n", usref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 0xff & (usref >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 0xff & (usref >> 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct dtv_frontend_properties *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int inversion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) lg_dbg("(%d)\n", inversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) inversion ? 0xf9 : 0x79);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) inversion ? 0xfd : 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static int lgdt3305_set_if(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) u16 if_freq_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) u8 nco1, nco2, nco3, nco4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u64 nco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if_freq_khz = state->cfg->vsb_if_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if_freq_khz = state->cfg->qam_if_khz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return -EINVAL;
^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) nco = if_freq_khz / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) nco <<= 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) do_div(nco, 625);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) nco <<= 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) do_div(nco, 625);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) nco1 = (nco >> 24) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) nco1 |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) nco2 = (nco >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) nco3 = (nco >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) nco4 = nco & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if_freq_khz, nco1, nco2, nco3, nco4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^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) static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (state->cfg->deny_i2c_rptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) lg_dbg("(%d)\n", enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) enable ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int lgdt3305_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) u8 gen_ctrl_3, gen_ctrl_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* hold in software reset while sleeping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) gen_ctrl_3 &= ~0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* tristate the IF-AGC pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) gen_ctrl_3 |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* tristate the RF-AGC pin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) gen_ctrl_3 |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* disable vsb/qam module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) gen_ctrl_4 &= ~0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* disable adc module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) gen_ctrl_4 &= ~0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int lgdt3305_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static struct lgdt3305_reg lgdt3304_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) { .reg = 0x000d, .val = 0x02, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) { .reg = 0x000e, .val = 0x02, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) { .reg = 0x0112, .val = 0x17, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) { .reg = 0x0113, .val = 0x15, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) { .reg = 0x0114, .val = 0x18, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) { .reg = 0x0115, .val = 0xff, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) { .reg = 0x0116, .val = 0x3c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) { .reg = 0x0214, .val = 0x67, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) { .reg = 0x0424, .val = 0x8d, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) { .reg = 0x0427, .val = 0x12, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) { .reg = 0x0428, .val = 0x4f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) { .reg = LGDT3305_IFBW_1, .val = 0x80, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) { .reg = LGDT3305_IFBW_2, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) { .reg = 0x030a, .val = 0x08, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) { .reg = 0x030b, .val = 0x9b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) { .reg = 0x030d, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) { .reg = 0x030e, .val = 0x1c, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) { .reg = 0x0314, .val = 0xe1, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) { .reg = 0x000d, .val = 0x82, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static struct lgdt3305_reg lgdt3305_init_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) { .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) { .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) { .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) { .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) { .reg = LGDT3305_CR_CTRL_7, .val = 0x79, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) { .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) { .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) { .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) { .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) { .reg = LGDT3305_IFBW_1, .val = 0x80, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) { .reg = LGDT3305_IFBW_2, .val = 0x00, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) { .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) { .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) { .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) { .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) switch (state->cfg->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case LGDT3304:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ret = lgdt3305_write_regs(state, lgdt3304_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ARRAY_SIZE(lgdt3304_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case LGDT3305:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret = lgdt3305_write_regs(state, lgdt3305_init_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ARRAY_SIZE(lgdt3305_init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ret = lgdt3305_soft_reset(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int lgdt3304_set_parameters(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (fe->ops.tuner_ops.set_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ret = fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) state->current_frequency = p->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ret = lgdt3305_set_modulation(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ret = lgdt3305_passband_digital_agc(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) ret = lgdt3305_agc_setup(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) switch (p->modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) lgdt3305_write_reg(state, 0x030d, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) lgdt3305_write_reg(state, 0x030d, 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ret = lgdt3305_set_if(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) ret = lgdt3305_spectral_inversion(state, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) state->cfg->spectral_inversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) state->current_modulation = p->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ret = lgdt3305_mpeg_mode_polarity(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static int lgdt3305_set_parameters(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct dtv_frontend_properties *p = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (fe->ops.tuner_ops.set_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ret = fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) fe->ops.i2c_gate_ctrl(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) state->current_frequency = p->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ret = lgdt3305_set_modulation(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) ret = lgdt3305_passband_digital_agc(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) ret = lgdt3305_set_agc_power_ref(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ret = lgdt3305_agc_setup(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* low if */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) ret = lgdt3305_set_if(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret = lgdt3305_spectral_inversion(state, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) state->cfg->spectral_inversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) ret = lgdt3305_set_filter_extension(state, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) state->current_modulation = p->modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ret = lgdt3305_mpeg_mode_polarity(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int lgdt3305_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct dtv_frontend_properties *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) p->modulation = state->current_modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) p->frequency = state->current_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int *locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) char *cr_lock_state = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) *locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (val & (1 << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) switch (val & 0x07) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) cr_lock_state = "QAM UNLOCK";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) cr_lock_state = "QAM 1stLock";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) cr_lock_state = "QAM 2ndLock";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) cr_lock_state = "QAM FinalLock";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) cr_lock_state = "CLOCKQAM-INVALID!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (val & (1 << 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) *locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) cr_lock_state = "CLOCKVSB";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) lg_dbg("(%d) %s\n", *locked, cr_lock_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int *locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) int ret, mpeg_lock, fec_lock, viterbi_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) *locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ret = lgdt3305_read_reg(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) LGDT3305_FEC_LOCK_STATUS, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) mpeg_lock = (val & (1 << 0)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) fec_lock = (val & (1 << 2)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) viterbi_lock = (val & (1 << 3)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) *locked = mpeg_lock && fec_lock && viterbi_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) lg_dbg("(%d) %s%s%s\n", *locked,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) mpeg_lock ? "mpeg lock " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) fec_lock ? "fec lock " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) viterbi_lock ? "viterbi lock" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int lgdt3305_read_status(struct dvb_frontend *fe, enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int ret, signal, inlock, nofecerr, snrgood,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) cr_lock, fec_lock, sync_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) signal = (val & (1 << 4)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) inlock = (val & (1 << 3)) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) sync_lock = (val & (1 << 2)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) nofecerr = (val & (1 << 1)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) snrgood = (val & (1 << 0)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) lg_dbg("%s%s%s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) signal ? "SIGNALEXIST " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) inlock ? "INLOCK " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) sync_lock ? "SYNCLOCK " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) nofecerr ? "NOFECERR " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) snrgood ? "SNRGOOD " : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ret = lgdt3305_read_cr_lock_status(state, &cr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (signal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (cr_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) *status |= FE_HAS_CARRIER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (nofecerr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) *status |= FE_HAS_VITERBI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (sync_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) *status |= FE_HAS_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* signal bit is unreliable on the DT3304 in QAM mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) *status |= FE_HAS_SIGNAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (fec_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) *status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (inlock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) *status |= FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* borrowed from lgdt330x.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static u32 calculate_snr(u32 mse, u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (mse == 0) /* no signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) mse = intlog10(mse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (mse > c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) /* Negative SNR, which is possible, but realisticly the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) demod will lose lock before the signal gets this bad. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) API only allows for unsigned values, so just return 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return 10*(c - mse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) u32 noise; /* noise value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) u32 c; /* per-modulation SNR calculation constant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) switch (state->current_modulation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) case VSB_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) #ifdef USE_PTMSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* Use Phase Tracker Mean-Square Error Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* SNR for ranges from -13.11 to +44.08 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) noise = ((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) (read_reg(state, LGDT3305_PT_MSE_2) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) (read_reg(state, LGDT3305_PT_MSE_3) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) c = 73957994; /* log10(25*32^2)*2^24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* Use Equalizer Mean-Square Error Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /* SNR for ranges from -16.12 to +44.08 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) noise = ((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) (read_reg(state, LGDT3305_EQ_MSE_2) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) (read_reg(state, LGDT3305_EQ_MSE_3) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) c = 73957994; /* log10(25*32^2)*2^24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case QAM_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case QAM_256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) (read_reg(state, LGDT3305_CR_MSE_2) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) c = (state->current_modulation == QAM_64) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 97939837 : 98026066;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* log10(688128)*2^24 and log10(696320)*2^24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) state->snr = calculate_snr(noise, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* report SNR in dB * 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) *snr = (state->snr / ((1 << 24) / 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) static int lgdt3305_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) u16 *strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /* borrowed from lgdt330x.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * Calculate strength from SNR up to 35dB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * Even though the SNR can go higher than 35dB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * there is some comfort factor in having a range of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * strong signals that can show at 100%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) u16 snr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) *strength = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ret = fe->ops.read_snr(fe, &snr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /* scale the range 0 - 35*2^24 into 0 - 65535 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (state->snr >= 8960 * 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) *strength = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) *strength = state->snr / 8960;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* ------------------------------------------------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) *ber = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) *ucblocks =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) (read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) (read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) static int lgdt3305_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct dvb_frontend_tune_settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) *fe_tune_settings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) fe_tune_settings->min_delay_ms = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static void lgdt3305_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct lgdt3305_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) lg_dbg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static const struct dvb_frontend_ops lgdt3304_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static const struct dvb_frontend_ops lgdt3305_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct i2c_adapter *i2c_adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) struct lgdt3305_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) lg_dbg("(%d-%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) config ? config->i2c_addr : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) state->cfg = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) state->i2c_adap = i2c_adap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) switch (config->demod_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case LGDT3304:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) memcpy(&state->frontend.ops, &lgdt3304_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) case LGDT3305:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) memcpy(&state->frontend.ops, &lgdt3305_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) /* verify that we're talking to a lg dt3304/5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if ((lg_fail(ret)) | (val == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) ret = lgdt3305_write_reg(state, 0x0808, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ret = lgdt3305_read_reg(state, 0x0808, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if ((lg_fail(ret)) | (val != 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) ret = lgdt3305_write_reg(state, 0x0808, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (lg_fail(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) state->current_frequency = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) state->current_modulation = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) lg_warn("unable to detect %s hardware\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) config->demod_chip ? "LGDT3304" : "LGDT3305");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) EXPORT_SYMBOL(lgdt3305_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static const struct dvb_frontend_ops lgdt3304_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) .name = "LG Electronics LGDT3304 VSB/QAM Frontend",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) .frequency_min_hz = 54 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .frequency_max_hz = 858 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .frequency_stepsize_hz = 62500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .init = lgdt3305_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .sleep = lgdt3305_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .set_frontend = lgdt3304_set_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) .get_frontend = lgdt3305_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) .get_tune_settings = lgdt3305_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) .read_status = lgdt3305_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) .read_ber = lgdt3305_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) .read_signal_strength = lgdt3305_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) .read_snr = lgdt3305_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) .read_ucblocks = lgdt3305_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) .release = lgdt3305_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static const struct dvb_frontend_ops lgdt3305_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) .name = "LG Electronics LGDT3305 VSB/QAM Frontend",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .frequency_min_hz = 54 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .frequency_max_hz = 858 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .frequency_stepsize_hz = 62500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) .init = lgdt3305_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .sleep = lgdt3305_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) .set_frontend = lgdt3305_set_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .get_frontend = lgdt3305_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) .get_tune_settings = lgdt3305_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) .read_status = lgdt3305_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) .read_ber = lgdt3305_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) .read_signal_strength = lgdt3305_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) .read_snr = lgdt3305_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .read_ucblocks = lgdt3305_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .release = lgdt3305_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) MODULE_VERSION("0.2");