^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) Driver for M88RS2000 demodulator and tuner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) Beta Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Include various calculation code from DS3000 driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Copyright (C) 2009 Konstantin Dimitrov.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <media/dvb_frontend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "m88rs2000.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct m88rs2000_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct i2c_adapter *i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) const struct m88rs2000_config *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct dvb_frontend frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u8 no_lock_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u32 tuner_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u32 symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) enum fe_code_rate fec_inner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u8 tuner_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int errmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int m88rs2000_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) module_param_named(debug, m88rs2000_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define dprintk(level, args...) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (level & m88rs2000_debug) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) printk(KERN_DEBUG "m88rs2000-fe: " args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define deb_info(args...) dprintk(0x01, args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define info(format, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int m88rs2000_writereg(struct m88rs2000_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 reg, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 buf[] = { reg, data };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct i2c_msg msg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .addr = state->config->demod_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .len = 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ret = i2c_transfer(state->i2c, &msg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) __func__, reg, data, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return (ret != 1) ? -EREMOTEIO : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u8 b0[] = { reg };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u8 b1[] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .addr = state->config->demod_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .buf = b0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .len = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .addr = state->config->demod_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .buf = b1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .len = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ret = i2c_transfer(state->i2c, msg, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (ret != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __func__, reg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return b1[0];
^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 u32 m88rs2000_get_mclk(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Must not be 0x00 or 0xff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) reg = m88rs2000_readreg(state, 0x86);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!reg || reg == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) reg /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) reg += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mclk = (u32)(reg * RS2000_FE_CRYSTAL_KHZ + 28 / 2) / 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int m88rs2000_set_carrieroffset(struct dvb_frontend *fe, s16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) s32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mclk = m88rs2000_get_mclk(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!mclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) tmp = (offset * 4096 + (s32)mclk / 2) / (s32)mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (tmp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) tmp += 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* Carrier Offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ret = m88rs2000_writereg(state, 0x9c, (u8)(tmp >> 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) reg = m88rs2000_readreg(state, 0x9d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) reg &= 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) reg |= (u8)(tmp & 0xf) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ret |= m88rs2000_writereg(state, 0x9d, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u64 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u32 mclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u8 b[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if ((srate < 1000000) || (srate > 45000000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) mclk = m88rs2000_get_mclk(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!mclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) temp = srate / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) temp *= 1 << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) do_div(temp, mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) b[0] = (u8) (temp >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) b[1] = (u8) (temp >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) b[2] = (u8) temp & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = m88rs2000_writereg(state, 0x93, b[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret |= m88rs2000_writereg(state, 0x94, b[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ret |= m88rs2000_writereg(state, 0x95, b[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (srate > 10000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ret |= m88rs2000_writereg(state, 0xa0, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret |= m88rs2000_writereg(state, 0xa0, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret |= m88rs2000_writereg(state, 0xa1, 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (srate > 12000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret |= m88rs2000_writereg(state, 0xa3, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) else if (srate > 2800000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret |= m88rs2000_writereg(state, 0xa3, 0x98);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ret |= m88rs2000_writereg(state, 0xa3, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) deb_info("m88rs2000: m88rs2000_set_symbolrate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct dvb_diseqc_master_cmd *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) deb_info("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) m88rs2000_writereg(state, 0x9a, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) reg = m88rs2000_readreg(state, 0xb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) reg &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) m88rs2000_writereg(state, 0xb2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (i = 0; i < m->msg_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) m88rs2000_writereg(state, 0xb3 + i, m->msg[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) reg = m88rs2000_readreg(state, 0xb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) reg &= 0x87;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) reg |= ((m->msg_len - 1) << 3) | 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) reg &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) m88rs2000_writereg(state, 0xb1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) for (i = 0; i < 15; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if ((m88rs2000_readreg(state, 0xb1) & 0x40) == 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) reg = m88rs2000_readreg(state, 0xb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if ((reg & 0x40) > 0x0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) reg &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) reg |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) m88rs2000_writereg(state, 0xb1, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) reg = m88rs2000_readreg(state, 0xb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) reg &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) reg |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) m88rs2000_writereg(state, 0xb2, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) m88rs2000_writereg(state, 0x9a, 0xb0);
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) enum fe_sec_mini_cmd burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u8 reg0, reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) deb_info("%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) m88rs2000_writereg(state, 0x9a, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) reg0 = m88rs2000_readreg(state, 0xb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) reg1 = m88rs2000_readreg(state, 0xb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* TODO complete this section */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) m88rs2000_writereg(state, 0xb2, reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) m88rs2000_writereg(state, 0xb1, reg0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) m88rs2000_writereg(state, 0x9a, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int m88rs2000_set_tone(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) enum fe_sec_tone_mode tone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u8 reg0, reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) m88rs2000_writereg(state, 0x9a, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) reg0 = m88rs2000_readreg(state, 0xb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) reg1 = m88rs2000_readreg(state, 0xb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) reg1 &= 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) switch (tone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case SEC_TONE_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) reg0 |= 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) reg0 &= 0xbc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case SEC_TONE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) reg1 |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) m88rs2000_writereg(state, 0xb2, reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) m88rs2000_writereg(state, 0xb1, reg0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) m88rs2000_writereg(state, 0x9a, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct inittab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u8 val;
^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 struct inittab m88rs2000_setup[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {DEMOD_WRITE, 0x9a, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {DEMOD_WRITE, 0x00, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {WRITE_DELAY, 0x19, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {DEMOD_WRITE, 0x00, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {DEMOD_WRITE, 0x9a, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {DEMOD_WRITE, 0x81, 0xc1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {DEMOD_WRITE, 0x81, 0x81},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {DEMOD_WRITE, 0x86, 0xc6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {DEMOD_WRITE, 0x9a, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {DEMOD_WRITE, 0xf0, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {DEMOD_WRITE, 0xf1, 0xbf},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {DEMOD_WRITE, 0xb0, 0x45},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {DEMOD_WRITE, 0x9a, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {0xff, 0xaa, 0xff}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static struct inittab m88rs2000_shutdown[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {DEMOD_WRITE, 0x9a, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {DEMOD_WRITE, 0xb0, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {DEMOD_WRITE, 0xf1, 0x89},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {DEMOD_WRITE, 0x00, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {DEMOD_WRITE, 0x9a, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {DEMOD_WRITE, 0x81, 0x81},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {0xff, 0xaa, 0xff}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static struct inittab fe_reset[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {DEMOD_WRITE, 0x00, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {DEMOD_WRITE, 0x20, 0x81},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {DEMOD_WRITE, 0x21, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {DEMOD_WRITE, 0x10, 0x33},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {DEMOD_WRITE, 0x11, 0x44},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {DEMOD_WRITE, 0x12, 0x07},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {DEMOD_WRITE, 0x18, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {DEMOD_WRITE, 0x28, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {DEMOD_WRITE, 0x29, 0x8e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {DEMOD_WRITE, 0x3b, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {DEMOD_WRITE, 0x32, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {DEMOD_WRITE, 0x33, 0x02},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {DEMOD_WRITE, 0x34, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {DEMOD_WRITE, 0x35, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {DEMOD_WRITE, 0x38, 0x50},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {DEMOD_WRITE, 0x39, 0x68},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {DEMOD_WRITE, 0x3c, 0x7f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {DEMOD_WRITE, 0x3d, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {DEMOD_WRITE, 0x45, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {DEMOD_WRITE, 0x46, 0x24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {DEMOD_WRITE, 0x47, 0x7c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {DEMOD_WRITE, 0x48, 0x16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {DEMOD_WRITE, 0x49, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {DEMOD_WRITE, 0x4a, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {DEMOD_WRITE, 0x4b, 0x78},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {DEMOD_WRITE, 0X4d, 0xd2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {DEMOD_WRITE, 0x4e, 0x6d},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {DEMOD_WRITE, 0x50, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {DEMOD_WRITE, 0x51, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {DEMOD_WRITE, 0x54, 0x7b},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {DEMOD_WRITE, 0x56, 0x09},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {DEMOD_WRITE, 0x58, 0x59},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {DEMOD_WRITE, 0x59, 0x37},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {DEMOD_WRITE, 0x63, 0xfa},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {0xff, 0xaa, 0xff}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static struct inittab fe_trigger[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {DEMOD_WRITE, 0x97, 0x04},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {DEMOD_WRITE, 0x99, 0x77},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {DEMOD_WRITE, 0x9b, 0x64},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {DEMOD_WRITE, 0x9e, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {DEMOD_WRITE, 0x9f, 0xf8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {DEMOD_WRITE, 0x98, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {DEMOD_WRITE, 0xc0, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {DEMOD_WRITE, 0x89, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {DEMOD_WRITE, 0x00, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {WRITE_DELAY, 0x0a, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {DEMOD_WRITE, 0x00, 0x01},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {DEMOD_WRITE, 0x00, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {DEMOD_WRITE, 0x9a, 0xb0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {0xff, 0xaa, 0xff}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int m88rs2000_tab_set(struct m88rs2000_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct inittab *tab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (tab == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) for (i = 0; i < 255; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) switch (tab[i].cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ret = m88rs2000_writereg(state, tab[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) tab[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (tab[i].reg > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) mdelay(tab[i].reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case 0xff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (tab[i].reg == 0xaa && tab[i].val == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int m88rs2000_set_voltage(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) enum fe_sec_voltage volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) data = m88rs2000_readreg(state, 0xb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) data |= 0x03; /* bit0 V/H, bit1 off/on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) switch (volt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case SEC_VOLTAGE_18:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) data &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case SEC_VOLTAGE_13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) data &= ~0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) data |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case SEC_VOLTAGE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) m88rs2000_writereg(state, 0xb2, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return 0;
^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) static int m88rs2000_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) deb_info("m88rs2000: init chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* Setup frontend from shutdown/cold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (state->config->inittab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = m88rs2000_tab_set(state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) (struct inittab *)state->config->inittab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ret = m88rs2000_tab_set(state, m88rs2000_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static int m88rs2000_sleep(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Shutdown the frondend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ret = m88rs2000_tab_set(state, m88rs2000_shutdown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static int m88rs2000_read_status(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) enum fe_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) u8 reg = m88rs2000_readreg(state, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if ((reg & 0xee) == 0xee) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) | FE_HAS_SYNC | FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (state->config->set_ts_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) state->config->set_ts_params(fe, CALL_IS_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) u8 tmp0, tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) m88rs2000_writereg(state, 0x9a, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) tmp0 = m88rs2000_readreg(state, 0xd8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if ((tmp0 & 0x10) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) m88rs2000_writereg(state, 0x9a, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) *ber = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) *ber = (m88rs2000_readreg(state, 0xd7) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) m88rs2000_readreg(state, 0xd6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) tmp1 = m88rs2000_readreg(state, 0xd9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) m88rs2000_writereg(state, 0xd9, (tmp1 & ~7) | 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* needs twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) m88rs2000_writereg(state, 0xd8, (tmp0 & ~8) | 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) m88rs2000_writereg(state, 0x9a, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static int m88rs2000_read_signal_strength(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u16 *strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (fe->ops.tuner_ops.get_rf_strength)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) fe->ops.tuner_ops.get_rf_strength(fe, strength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^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) static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *snr = 512 * m88rs2000_readreg(state, 0x65);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) *ucblocks = (m88rs2000_readreg(state, 0xd5) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) m88rs2000_readreg(state, 0xd4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) tmp = m88rs2000_readreg(state, 0xd8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) m88rs2000_writereg(state, 0xd8, tmp & ~0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* needs two times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) m88rs2000_writereg(state, 0xd8, tmp | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) m88rs2000_writereg(state, 0xd8, tmp | 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static int m88rs2000_set_fec(struct m88rs2000_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) enum fe_code_rate fec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 fec_set, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) switch (fec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) case FEC_1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) fec_set = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case FEC_2_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) fec_set = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case FEC_3_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) fec_set = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case FEC_5_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) fec_set = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case FEC_7_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) fec_set = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case FEC_AUTO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) fec_set = 0x0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) reg = m88rs2000_readreg(state, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) reg &= 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ret = m88rs2000_writereg(state, 0x70, reg | fec_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ret |= m88rs2000_writereg(state, 0x76, 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static enum fe_code_rate m88rs2000_get_fec(struct m88rs2000_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) m88rs2000_writereg(state, 0x9a, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) reg = m88rs2000_readreg(state, 0x76);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) m88rs2000_writereg(state, 0x9a, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) reg &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) reg >>= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case 0x4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return FEC_1_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case 0x3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return FEC_2_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case 0x2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return FEC_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return FEC_5_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case 0x0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return FEC_7_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return FEC_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static int m88rs2000_set_frontend(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) enum fe_status status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) u32 tuner_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) s16 offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) state->no_lock_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (c->delivery_system != SYS_DVBS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) deb_info("%s: unsupported delivery system selected (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) __func__, c->delivery_system);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EOPNOTSUPP;
^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) /* Set Tuner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (fe->ops.tuner_ops.set_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ret = fe->ops.tuner_ops.set_params(fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (fe->ops.tuner_ops.get_frequency) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) offset = (s16)((s32)tuner_freq - c->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* default mclk value 96.4285 * 2 * 1000 = 192857 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (((c->frequency % 192857) >= (192857 - 3000)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) (c->frequency % 192857) <= 3000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = m88rs2000_writereg(state, 0x86, 0xc2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ret = m88rs2000_writereg(state, 0x86, 0xc6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ret |= m88rs2000_set_carrieroffset(fe, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* Reset demod by symbol rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (c->symbol_rate > 27500000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ret = m88rs2000_writereg(state, 0xf1, 0xa4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ret = m88rs2000_writereg(state, 0xf1, 0xbf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret |= m88rs2000_tab_set(state, fe_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* Set FEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ret = m88rs2000_set_fec(state, c->fec_inner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret |= m88rs2000_writereg(state, 0x85, 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ret |= m88rs2000_writereg(state, 0x8a, 0xbf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ret |= m88rs2000_writereg(state, 0x8d, 0x1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) ret |= m88rs2000_writereg(state, 0x90, 0xf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ret |= m88rs2000_writereg(state, 0x91, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* Set Symbol Rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ret = m88rs2000_set_symbolrate(fe, c->symbol_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* Set up Demod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ret = m88rs2000_tab_set(state, fe_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) for (i = 0; i < 25; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) reg = m88rs2000_readreg(state, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if ((reg & 0xee) == 0xee) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) status = FE_HAS_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) state->no_lock_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (state->no_lock_count == 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) reg = m88rs2000_readreg(state, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) reg ^= 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) m88rs2000_writereg(state, 0x70, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) state->no_lock_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (status & FE_HAS_LOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) state->fec_inner = m88rs2000_get_fec(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Unknown suspect SNR level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) reg = m88rs2000_readreg(state, 0x65);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) state->tuner_frequency = c->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) state->symbol_rate = c->symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static int m88rs2000_get_frontend(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct dtv_frontend_properties *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) c->fec_inner = state->fec_inner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) c->frequency = state->tuner_frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) c->symbol_rate = state->symbol_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int m88rs2000_get_tune_settings(struct dvb_frontend *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct dvb_frontend_tune_settings *tune)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct dtv_frontend_properties *c = &fe->dtv_property_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (c->symbol_rate > 3000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) tune->min_delay_ms = 2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) tune->min_delay_ms = 3000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) tune->step_size = c->symbol_rate / 16000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) tune->max_drift = c->symbol_rate / 2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) m88rs2000_writereg(state, 0x81, 0x84);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) m88rs2000_writereg(state, 0x81, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static void m88rs2000_release(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct m88rs2000_state *state = fe->demodulator_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static const struct dvb_frontend_ops m88rs2000_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .delsys = { SYS_DVBS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) .info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .name = "M88RS2000 DVB-S",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .frequency_min_hz = 950 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .frequency_max_hz = 2150 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .frequency_stepsize_hz = 1 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .frequency_tolerance_hz = 5 * MHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .symbol_rate_min = 1000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) .symbol_rate_max = 45000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .symbol_rate_tolerance = 500, /* ppm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) FE_CAN_QPSK | FE_CAN_INVERSION_AUTO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) FE_CAN_FEC_AUTO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .release = m88rs2000_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .init = m88rs2000_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) .sleep = m88rs2000_sleep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .read_status = m88rs2000_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .read_ber = m88rs2000_read_ber,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .read_signal_strength = m88rs2000_read_signal_strength,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .read_snr = m88rs2000_read_snr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .read_ucblocks = m88rs2000_read_ucblocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .diseqc_send_master_cmd = m88rs2000_send_diseqc_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .diseqc_send_burst = m88rs2000_send_diseqc_burst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .set_tone = m88rs2000_set_tone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .set_voltage = m88rs2000_set_voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .set_frontend = m88rs2000_set_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .get_frontend = m88rs2000_get_frontend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .get_tune_settings = m88rs2000_get_tune_settings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct i2c_adapter *i2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct m88rs2000_state *state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* allocate memory for the internal state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (state == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* setup the state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) state->config = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) state->i2c = i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) state->tuner_frequency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) state->symbol_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) state->fec_inner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* create dvb_frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) memcpy(&state->frontend.ops, &m88rs2000_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) sizeof(struct dvb_frontend_ops));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) state->frontend.demodulator_priv = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return &state->frontend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) kfree(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) EXPORT_SYMBOL(m88rs2000_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) MODULE_VERSION("1.13");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)