1*395d00d1SAntti Palosaari /* 2*395d00d1SAntti Palosaari * Montage M88DS3103 demodulator driver 3*395d00d1SAntti Palosaari * 4*395d00d1SAntti Palosaari * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> 5*395d00d1SAntti Palosaari * 6*395d00d1SAntti Palosaari * This program is free software; you can redistribute it and/or modify 7*395d00d1SAntti Palosaari * it under the terms of the GNU General Public License as published by 8*395d00d1SAntti Palosaari * the Free Software Foundation; either version 2 of the License, or 9*395d00d1SAntti Palosaari * (at your option) any later version. 10*395d00d1SAntti Palosaari * 11*395d00d1SAntti Palosaari * This program is distributed in the hope that it will be useful, 12*395d00d1SAntti Palosaari * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*395d00d1SAntti Palosaari * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*395d00d1SAntti Palosaari * GNU General Public License for more details. 15*395d00d1SAntti Palosaari * 16*395d00d1SAntti Palosaari * You should have received a copy of the GNU General Public License along 17*395d00d1SAntti Palosaari * with this program; if not, write to the Free Software Foundation, Inc., 18*395d00d1SAntti Palosaari * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19*395d00d1SAntti Palosaari */ 20*395d00d1SAntti Palosaari 21*395d00d1SAntti Palosaari #include "m88ds3103_priv.h" 22*395d00d1SAntti Palosaari 23*395d00d1SAntti Palosaari static struct dvb_frontend_ops m88ds3103_ops; 24*395d00d1SAntti Palosaari 25*395d00d1SAntti Palosaari /* write multiple registers */ 26*395d00d1SAntti Palosaari static int m88ds3103_wr_regs(struct m88ds3103_priv *priv, 27*395d00d1SAntti Palosaari u8 reg, const u8 *val, int len) 28*395d00d1SAntti Palosaari { 29*395d00d1SAntti Palosaari int ret; 30*395d00d1SAntti Palosaari u8 buf[1 + len]; 31*395d00d1SAntti Palosaari struct i2c_msg msg[1] = { 32*395d00d1SAntti Palosaari { 33*395d00d1SAntti Palosaari .addr = priv->cfg->i2c_addr, 34*395d00d1SAntti Palosaari .flags = 0, 35*395d00d1SAntti Palosaari .len = sizeof(buf), 36*395d00d1SAntti Palosaari .buf = buf, 37*395d00d1SAntti Palosaari } 38*395d00d1SAntti Palosaari }; 39*395d00d1SAntti Palosaari 40*395d00d1SAntti Palosaari buf[0] = reg; 41*395d00d1SAntti Palosaari memcpy(&buf[1], val, len); 42*395d00d1SAntti Palosaari 43*395d00d1SAntti Palosaari mutex_lock(&priv->i2c_mutex); 44*395d00d1SAntti Palosaari ret = i2c_transfer(priv->i2c, msg, 1); 45*395d00d1SAntti Palosaari mutex_unlock(&priv->i2c_mutex); 46*395d00d1SAntti Palosaari if (ret == 1) { 47*395d00d1SAntti Palosaari ret = 0; 48*395d00d1SAntti Palosaari } else { 49*395d00d1SAntti Palosaari dev_warn(&priv->i2c->dev, 50*395d00d1SAntti Palosaari "%s: i2c wr failed=%d reg=%02x len=%d\n", 51*395d00d1SAntti Palosaari KBUILD_MODNAME, ret, reg, len); 52*395d00d1SAntti Palosaari ret = -EREMOTEIO; 53*395d00d1SAntti Palosaari } 54*395d00d1SAntti Palosaari 55*395d00d1SAntti Palosaari return ret; 56*395d00d1SAntti Palosaari } 57*395d00d1SAntti Palosaari 58*395d00d1SAntti Palosaari /* read multiple registers */ 59*395d00d1SAntti Palosaari static int m88ds3103_rd_regs(struct m88ds3103_priv *priv, 60*395d00d1SAntti Palosaari u8 reg, u8 *val, int len) 61*395d00d1SAntti Palosaari { 62*395d00d1SAntti Palosaari int ret; 63*395d00d1SAntti Palosaari u8 buf[len]; 64*395d00d1SAntti Palosaari struct i2c_msg msg[2] = { 65*395d00d1SAntti Palosaari { 66*395d00d1SAntti Palosaari .addr = priv->cfg->i2c_addr, 67*395d00d1SAntti Palosaari .flags = 0, 68*395d00d1SAntti Palosaari .len = 1, 69*395d00d1SAntti Palosaari .buf = ®, 70*395d00d1SAntti Palosaari }, { 71*395d00d1SAntti Palosaari .addr = priv->cfg->i2c_addr, 72*395d00d1SAntti Palosaari .flags = I2C_M_RD, 73*395d00d1SAntti Palosaari .len = sizeof(buf), 74*395d00d1SAntti Palosaari .buf = buf, 75*395d00d1SAntti Palosaari } 76*395d00d1SAntti Palosaari }; 77*395d00d1SAntti Palosaari 78*395d00d1SAntti Palosaari mutex_lock(&priv->i2c_mutex); 79*395d00d1SAntti Palosaari ret = i2c_transfer(priv->i2c, msg, 2); 80*395d00d1SAntti Palosaari mutex_unlock(&priv->i2c_mutex); 81*395d00d1SAntti Palosaari if (ret == 2) { 82*395d00d1SAntti Palosaari memcpy(val, buf, len); 83*395d00d1SAntti Palosaari ret = 0; 84*395d00d1SAntti Palosaari } else { 85*395d00d1SAntti Palosaari dev_warn(&priv->i2c->dev, 86*395d00d1SAntti Palosaari "%s: i2c rd failed=%d reg=%02x len=%d\n", 87*395d00d1SAntti Palosaari KBUILD_MODNAME, ret, reg, len); 88*395d00d1SAntti Palosaari ret = -EREMOTEIO; 89*395d00d1SAntti Palosaari } 90*395d00d1SAntti Palosaari 91*395d00d1SAntti Palosaari return ret; 92*395d00d1SAntti Palosaari } 93*395d00d1SAntti Palosaari 94*395d00d1SAntti Palosaari /* write single register */ 95*395d00d1SAntti Palosaari static int m88ds3103_wr_reg(struct m88ds3103_priv *priv, u8 reg, u8 val) 96*395d00d1SAntti Palosaari { 97*395d00d1SAntti Palosaari return m88ds3103_wr_regs(priv, reg, &val, 1); 98*395d00d1SAntti Palosaari } 99*395d00d1SAntti Palosaari 100*395d00d1SAntti Palosaari /* read single register */ 101*395d00d1SAntti Palosaari static int m88ds3103_rd_reg(struct m88ds3103_priv *priv, u8 reg, u8 *val) 102*395d00d1SAntti Palosaari { 103*395d00d1SAntti Palosaari return m88ds3103_rd_regs(priv, reg, val, 1); 104*395d00d1SAntti Palosaari } 105*395d00d1SAntti Palosaari 106*395d00d1SAntti Palosaari /* write single register with mask */ 107*395d00d1SAntti Palosaari static int m88ds3103_wr_reg_mask(struct m88ds3103_priv *priv, 108*395d00d1SAntti Palosaari u8 reg, u8 val, u8 mask) 109*395d00d1SAntti Palosaari { 110*395d00d1SAntti Palosaari int ret; 111*395d00d1SAntti Palosaari u8 u8tmp; 112*395d00d1SAntti Palosaari 113*395d00d1SAntti Palosaari /* no need for read if whole reg is written */ 114*395d00d1SAntti Palosaari if (mask != 0xff) { 115*395d00d1SAntti Palosaari ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1); 116*395d00d1SAntti Palosaari if (ret) 117*395d00d1SAntti Palosaari return ret; 118*395d00d1SAntti Palosaari 119*395d00d1SAntti Palosaari val &= mask; 120*395d00d1SAntti Palosaari u8tmp &= ~mask; 121*395d00d1SAntti Palosaari val |= u8tmp; 122*395d00d1SAntti Palosaari } 123*395d00d1SAntti Palosaari 124*395d00d1SAntti Palosaari return m88ds3103_wr_regs(priv, reg, &val, 1); 125*395d00d1SAntti Palosaari } 126*395d00d1SAntti Palosaari 127*395d00d1SAntti Palosaari /* read single register with mask */ 128*395d00d1SAntti Palosaari static int m88ds3103_rd_reg_mask(struct m88ds3103_priv *priv, 129*395d00d1SAntti Palosaari u8 reg, u8 *val, u8 mask) 130*395d00d1SAntti Palosaari { 131*395d00d1SAntti Palosaari int ret, i; 132*395d00d1SAntti Palosaari u8 u8tmp; 133*395d00d1SAntti Palosaari 134*395d00d1SAntti Palosaari ret = m88ds3103_rd_regs(priv, reg, &u8tmp, 1); 135*395d00d1SAntti Palosaari if (ret) 136*395d00d1SAntti Palosaari return ret; 137*395d00d1SAntti Palosaari 138*395d00d1SAntti Palosaari u8tmp &= mask; 139*395d00d1SAntti Palosaari 140*395d00d1SAntti Palosaari /* find position of the first bit */ 141*395d00d1SAntti Palosaari for (i = 0; i < 8; i++) { 142*395d00d1SAntti Palosaari if ((mask >> i) & 0x01) 143*395d00d1SAntti Palosaari break; 144*395d00d1SAntti Palosaari } 145*395d00d1SAntti Palosaari *val = u8tmp >> i; 146*395d00d1SAntti Palosaari 147*395d00d1SAntti Palosaari return 0; 148*395d00d1SAntti Palosaari } 149*395d00d1SAntti Palosaari 150*395d00d1SAntti Palosaari static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t *status) 151*395d00d1SAntti Palosaari { 152*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 153*395d00d1SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 154*395d00d1SAntti Palosaari int ret; 155*395d00d1SAntti Palosaari u8 u8tmp; 156*395d00d1SAntti Palosaari 157*395d00d1SAntti Palosaari *status = 0; 158*395d00d1SAntti Palosaari 159*395d00d1SAntti Palosaari if (!priv->warm) { 160*395d00d1SAntti Palosaari ret = -EAGAIN; 161*395d00d1SAntti Palosaari goto err; 162*395d00d1SAntti Palosaari } 163*395d00d1SAntti Palosaari 164*395d00d1SAntti Palosaari switch (c->delivery_system) { 165*395d00d1SAntti Palosaari case SYS_DVBS: 166*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg_mask(priv, 0xd1, &u8tmp, 0x07); 167*395d00d1SAntti Palosaari if (ret) 168*395d00d1SAntti Palosaari goto err; 169*395d00d1SAntti Palosaari 170*395d00d1SAntti Palosaari if (u8tmp == 0x07) 171*395d00d1SAntti Palosaari *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 172*395d00d1SAntti Palosaari FE_HAS_VITERBI | FE_HAS_SYNC | 173*395d00d1SAntti Palosaari FE_HAS_LOCK; 174*395d00d1SAntti Palosaari break; 175*395d00d1SAntti Palosaari case SYS_DVBS2: 176*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg_mask(priv, 0x0d, &u8tmp, 0x8f); 177*395d00d1SAntti Palosaari if (ret) 178*395d00d1SAntti Palosaari goto err; 179*395d00d1SAntti Palosaari 180*395d00d1SAntti Palosaari if (u8tmp == 0x8f) 181*395d00d1SAntti Palosaari *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 182*395d00d1SAntti Palosaari FE_HAS_VITERBI | FE_HAS_SYNC | 183*395d00d1SAntti Palosaari FE_HAS_LOCK; 184*395d00d1SAntti Palosaari break; 185*395d00d1SAntti Palosaari default: 186*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", 187*395d00d1SAntti Palosaari __func__); 188*395d00d1SAntti Palosaari ret = -EINVAL; 189*395d00d1SAntti Palosaari goto err; 190*395d00d1SAntti Palosaari } 191*395d00d1SAntti Palosaari 192*395d00d1SAntti Palosaari priv->fe_status = *status; 193*395d00d1SAntti Palosaari 194*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: lock=%02x status=%02x\n", 195*395d00d1SAntti Palosaari __func__, u8tmp, *status); 196*395d00d1SAntti Palosaari 197*395d00d1SAntti Palosaari return 0; 198*395d00d1SAntti Palosaari err: 199*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 200*395d00d1SAntti Palosaari return ret; 201*395d00d1SAntti Palosaari } 202*395d00d1SAntti Palosaari 203*395d00d1SAntti Palosaari static int m88ds3103_set_frontend(struct dvb_frontend *fe) 204*395d00d1SAntti Palosaari { 205*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 206*395d00d1SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 207*395d00d1SAntti Palosaari int ret, i, len; 208*395d00d1SAntti Palosaari const struct m88ds3103_reg_val *init; 209*395d00d1SAntti Palosaari u8 u8tmp, u8tmp1, u8tmp2; 210*395d00d1SAntti Palosaari u8 buf[2]; 211*395d00d1SAntti Palosaari u16 u16tmp, divide_ratio; 212*395d00d1SAntti Palosaari u32 tuner_frequency, target_mclk, ts_clk; 213*395d00d1SAntti Palosaari s32 s32tmp; 214*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, 215*395d00d1SAntti Palosaari "%s: delivery_system=%d modulation=%d frequency=%d symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", 216*395d00d1SAntti Palosaari __func__, c->delivery_system, 217*395d00d1SAntti Palosaari c->modulation, c->frequency, c->symbol_rate, 218*395d00d1SAntti Palosaari c->inversion, c->pilot, c->rolloff); 219*395d00d1SAntti Palosaari 220*395d00d1SAntti Palosaari if (!priv->warm) { 221*395d00d1SAntti Palosaari ret = -EAGAIN; 222*395d00d1SAntti Palosaari goto err; 223*395d00d1SAntti Palosaari } 224*395d00d1SAntti Palosaari 225*395d00d1SAntti Palosaari /* program tuner */ 226*395d00d1SAntti Palosaari if (fe->ops.tuner_ops.set_params) { 227*395d00d1SAntti Palosaari ret = fe->ops.tuner_ops.set_params(fe); 228*395d00d1SAntti Palosaari if (ret) 229*395d00d1SAntti Palosaari goto err; 230*395d00d1SAntti Palosaari } 231*395d00d1SAntti Palosaari 232*395d00d1SAntti Palosaari if (fe->ops.tuner_ops.get_frequency) { 233*395d00d1SAntti Palosaari ret = fe->ops.tuner_ops.get_frequency(fe, &tuner_frequency); 234*395d00d1SAntti Palosaari if (ret) 235*395d00d1SAntti Palosaari goto err; 236*395d00d1SAntti Palosaari } 237*395d00d1SAntti Palosaari 238*395d00d1SAntti Palosaari /* reset */ 239*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x07, 0x80); 240*395d00d1SAntti Palosaari if (ret) 241*395d00d1SAntti Palosaari goto err; 242*395d00d1SAntti Palosaari 243*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x07, 0x00); 244*395d00d1SAntti Palosaari if (ret) 245*395d00d1SAntti Palosaari goto err; 246*395d00d1SAntti Palosaari 247*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xb2, 0x01); 248*395d00d1SAntti Palosaari if (ret) 249*395d00d1SAntti Palosaari goto err; 250*395d00d1SAntti Palosaari 251*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x00, 0x01); 252*395d00d1SAntti Palosaari if (ret) 253*395d00d1SAntti Palosaari goto err; 254*395d00d1SAntti Palosaari 255*395d00d1SAntti Palosaari switch (c->delivery_system) { 256*395d00d1SAntti Palosaari case SYS_DVBS: 257*395d00d1SAntti Palosaari len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals); 258*395d00d1SAntti Palosaari init = m88ds3103_dvbs_init_reg_vals; 259*395d00d1SAntti Palosaari target_mclk = 96000; 260*395d00d1SAntti Palosaari break; 261*395d00d1SAntti Palosaari case SYS_DVBS2: 262*395d00d1SAntti Palosaari len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals); 263*395d00d1SAntti Palosaari init = m88ds3103_dvbs2_init_reg_vals; 264*395d00d1SAntti Palosaari 265*395d00d1SAntti Palosaari switch (priv->cfg->ts_mode) { 266*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL: 267*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL_D7: 268*395d00d1SAntti Palosaari if (c->symbol_rate < 18000000) 269*395d00d1SAntti Palosaari target_mclk = 96000; 270*395d00d1SAntti Palosaari else 271*395d00d1SAntti Palosaari target_mclk = 144000; 272*395d00d1SAntti Palosaari break; 273*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL: 274*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_12: 275*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_16: 276*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_19_2: 277*395d00d1SAntti Palosaari case M88DS3103_TS_CI: 278*395d00d1SAntti Palosaari if (c->symbol_rate < 18000000) 279*395d00d1SAntti Palosaari target_mclk = 96000; 280*395d00d1SAntti Palosaari else if (c->symbol_rate < 28000000) 281*395d00d1SAntti Palosaari target_mclk = 144000; 282*395d00d1SAntti Palosaari else 283*395d00d1SAntti Palosaari target_mclk = 192000; 284*395d00d1SAntti Palosaari break; 285*395d00d1SAntti Palosaari default: 286*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", 287*395d00d1SAntti Palosaari __func__); 288*395d00d1SAntti Palosaari ret = -EINVAL; 289*395d00d1SAntti Palosaari goto err; 290*395d00d1SAntti Palosaari } 291*395d00d1SAntti Palosaari break; 292*395d00d1SAntti Palosaari default: 293*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", 294*395d00d1SAntti Palosaari __func__); 295*395d00d1SAntti Palosaari ret = -EINVAL; 296*395d00d1SAntti Palosaari goto err; 297*395d00d1SAntti Palosaari } 298*395d00d1SAntti Palosaari 299*395d00d1SAntti Palosaari /* program init table */ 300*395d00d1SAntti Palosaari if (c->delivery_system != priv->delivery_system) { 301*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: program init\n", __func__); 302*395d00d1SAntti Palosaari for (i = 0; i < len; i++) { 303*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, init[i].reg, init[i].val); 304*395d00d1SAntti Palosaari if (ret) 305*395d00d1SAntti Palosaari goto err; 306*395d00d1SAntti Palosaari } 307*395d00d1SAntti Palosaari } 308*395d00d1SAntti Palosaari 309*395d00d1SAntti Palosaari u8tmp1 = 0; /* silence compiler warning */ 310*395d00d1SAntti Palosaari switch (priv->cfg->ts_mode) { 311*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL: 312*395d00d1SAntti Palosaari u8tmp1 = 0x00; 313*395d00d1SAntti Palosaari ts_clk = 0; 314*395d00d1SAntti Palosaari u8tmp = 0x04; 315*395d00d1SAntti Palosaari break; 316*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL_D7: 317*395d00d1SAntti Palosaari u8tmp1 = 0x20; 318*395d00d1SAntti Palosaari ts_clk = 0; 319*395d00d1SAntti Palosaari u8tmp = 0x04; 320*395d00d1SAntti Palosaari break; 321*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL: 322*395d00d1SAntti Palosaari ts_clk = 24000; 323*395d00d1SAntti Palosaari u8tmp = 0x00; 324*395d00d1SAntti Palosaari break; 325*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_12: 326*395d00d1SAntti Palosaari ts_clk = 12000; 327*395d00d1SAntti Palosaari u8tmp = 0x00; 328*395d00d1SAntti Palosaari break; 329*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_16: 330*395d00d1SAntti Palosaari ts_clk = 16000; 331*395d00d1SAntti Palosaari u8tmp = 0x00; 332*395d00d1SAntti Palosaari break; 333*395d00d1SAntti Palosaari case M88DS3103_TS_PARALLEL_19_2: 334*395d00d1SAntti Palosaari ts_clk = 19200; 335*395d00d1SAntti Palosaari u8tmp = 0x00; 336*395d00d1SAntti Palosaari break; 337*395d00d1SAntti Palosaari case M88DS3103_TS_CI: 338*395d00d1SAntti Palosaari ts_clk = 6000; 339*395d00d1SAntti Palosaari u8tmp = 0x01; 340*395d00d1SAntti Palosaari break; 341*395d00d1SAntti Palosaari default: 342*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n", __func__); 343*395d00d1SAntti Palosaari ret = -EINVAL; 344*395d00d1SAntti Palosaari goto err; 345*395d00d1SAntti Palosaari } 346*395d00d1SAntti Palosaari 347*395d00d1SAntti Palosaari /* TS mode */ 348*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xfd, u8tmp, 0x05); 349*395d00d1SAntti Palosaari if (ret) 350*395d00d1SAntti Palosaari goto err; 351*395d00d1SAntti Palosaari 352*395d00d1SAntti Palosaari switch (priv->cfg->ts_mode) { 353*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL: 354*395d00d1SAntti Palosaari case M88DS3103_TS_SERIAL_D7: 355*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x29, u8tmp1, 0x20); 356*395d00d1SAntti Palosaari if (ret) 357*395d00d1SAntti Palosaari goto err; 358*395d00d1SAntti Palosaari } 359*395d00d1SAntti Palosaari 360*395d00d1SAntti Palosaari if (ts_clk) { 361*395d00d1SAntti Palosaari divide_ratio = DIV_ROUND_UP(target_mclk, ts_clk); 362*395d00d1SAntti Palosaari u8tmp1 = divide_ratio / 2; 363*395d00d1SAntti Palosaari u8tmp2 = DIV_ROUND_UP(divide_ratio, 2); 364*395d00d1SAntti Palosaari } else { 365*395d00d1SAntti Palosaari divide_ratio = 0; 366*395d00d1SAntti Palosaari u8tmp1 = 0; 367*395d00d1SAntti Palosaari u8tmp2 = 0; 368*395d00d1SAntti Palosaari } 369*395d00d1SAntti Palosaari 370*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, 371*395d00d1SAntti Palosaari "%s: target_mclk=%d ts_clk=%d divide_ratio=%d\n", 372*395d00d1SAntti Palosaari __func__, target_mclk, ts_clk, divide_ratio); 373*395d00d1SAntti Palosaari 374*395d00d1SAntti Palosaari u8tmp1--; 375*395d00d1SAntti Palosaari u8tmp2--; 376*395d00d1SAntti Palosaari /* u8tmp1[5:2] => fe[3:0], u8tmp1[1:0] => ea[7:6] */ 377*395d00d1SAntti Palosaari u8tmp1 &= 0x3f; 378*395d00d1SAntti Palosaari /* u8tmp2[5:0] => ea[5:0] */ 379*395d00d1SAntti Palosaari u8tmp2 &= 0x3f; 380*395d00d1SAntti Palosaari 381*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xfe, &u8tmp); 382*395d00d1SAntti Palosaari if (ret) 383*395d00d1SAntti Palosaari goto err; 384*395d00d1SAntti Palosaari 385*395d00d1SAntti Palosaari u8tmp = ((u8tmp & 0xf0) << 0) | u8tmp1 >> 2; 386*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xfe, u8tmp); 387*395d00d1SAntti Palosaari if (ret) 388*395d00d1SAntti Palosaari goto err; 389*395d00d1SAntti Palosaari 390*395d00d1SAntti Palosaari u8tmp = ((u8tmp1 & 0x03) << 6) | u8tmp2 >> 0; 391*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xea, u8tmp); 392*395d00d1SAntti Palosaari if (ret) 393*395d00d1SAntti Palosaari goto err; 394*395d00d1SAntti Palosaari 395*395d00d1SAntti Palosaari switch (target_mclk) { 396*395d00d1SAntti Palosaari case 72000: 397*395d00d1SAntti Palosaari u8tmp1 = 0x00; /* 0b00 */ 398*395d00d1SAntti Palosaari u8tmp2 = 0x03; /* 0b11 */ 399*395d00d1SAntti Palosaari break; 400*395d00d1SAntti Palosaari case 96000: 401*395d00d1SAntti Palosaari u8tmp1 = 0x02; /* 0b10 */ 402*395d00d1SAntti Palosaari u8tmp2 = 0x01; /* 0b01 */ 403*395d00d1SAntti Palosaari break; 404*395d00d1SAntti Palosaari case 115200: 405*395d00d1SAntti Palosaari u8tmp1 = 0x01; /* 0b01 */ 406*395d00d1SAntti Palosaari u8tmp2 = 0x01; /* 0b01 */ 407*395d00d1SAntti Palosaari break; 408*395d00d1SAntti Palosaari case 144000: 409*395d00d1SAntti Palosaari u8tmp1 = 0x00; /* 0b00 */ 410*395d00d1SAntti Palosaari u8tmp2 = 0x01; /* 0b01 */ 411*395d00d1SAntti Palosaari break; 412*395d00d1SAntti Palosaari case 192000: 413*395d00d1SAntti Palosaari u8tmp1 = 0x03; /* 0b11 */ 414*395d00d1SAntti Palosaari u8tmp2 = 0x00; /* 0b00 */ 415*395d00d1SAntti Palosaari break; 416*395d00d1SAntti Palosaari default: 417*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid target_mclk\n", __func__); 418*395d00d1SAntti Palosaari ret = -EINVAL; 419*395d00d1SAntti Palosaari goto err; 420*395d00d1SAntti Palosaari } 421*395d00d1SAntti Palosaari 422*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0); 423*395d00d1SAntti Palosaari if (ret) 424*395d00d1SAntti Palosaari goto err; 425*395d00d1SAntti Palosaari 426*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0); 427*395d00d1SAntti Palosaari if (ret) 428*395d00d1SAntti Palosaari goto err; 429*395d00d1SAntti Palosaari 430*395d00d1SAntti Palosaari if (c->symbol_rate <= 3000000) 431*395d00d1SAntti Palosaari u8tmp = 0x20; 432*395d00d1SAntti Palosaari else if (c->symbol_rate <= 10000000) 433*395d00d1SAntti Palosaari u8tmp = 0x10; 434*395d00d1SAntti Palosaari else 435*395d00d1SAntti Palosaari u8tmp = 0x06; 436*395d00d1SAntti Palosaari 437*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xc3, 0x08); 438*395d00d1SAntti Palosaari if (ret) 439*395d00d1SAntti Palosaari goto err; 440*395d00d1SAntti Palosaari 441*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xc8, u8tmp); 442*395d00d1SAntti Palosaari if (ret) 443*395d00d1SAntti Palosaari goto err; 444*395d00d1SAntti Palosaari 445*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xc4, 0x08); 446*395d00d1SAntti Palosaari if (ret) 447*395d00d1SAntti Palosaari goto err; 448*395d00d1SAntti Palosaari 449*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xc7, 0x00); 450*395d00d1SAntti Palosaari if (ret) 451*395d00d1SAntti Palosaari goto err; 452*395d00d1SAntti Palosaari 453*395d00d1SAntti Palosaari u16tmp = (((c->symbol_rate / 1000) << 15) + (M88DS3103_MCLK_KHZ / 4)) / 454*395d00d1SAntti Palosaari (M88DS3103_MCLK_KHZ / 2); 455*395d00d1SAntti Palosaari buf[0] = (u16tmp >> 0) & 0xff; 456*395d00d1SAntti Palosaari buf[1] = (u16tmp >> 8) & 0xff; 457*395d00d1SAntti Palosaari ret = m88ds3103_wr_regs(priv, 0x61, buf, 2); 458*395d00d1SAntti Palosaari if (ret) 459*395d00d1SAntti Palosaari goto err; 460*395d00d1SAntti Palosaari 461*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x4d, priv->cfg->spec_inv << 1, 0x02); 462*395d00d1SAntti Palosaari if (ret) 463*395d00d1SAntti Palosaari goto err; 464*395d00d1SAntti Palosaari 465*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x30, priv->cfg->agc_inv << 4, 0x10); 466*395d00d1SAntti Palosaari if (ret) 467*395d00d1SAntti Palosaari goto err; 468*395d00d1SAntti Palosaari 469*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x33, priv->cfg->agc); 470*395d00d1SAntti Palosaari if (ret) 471*395d00d1SAntti Palosaari goto err; 472*395d00d1SAntti Palosaari 473*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: carrier offset=%d\n", __func__, 474*395d00d1SAntti Palosaari (tuner_frequency - c->frequency)); 475*395d00d1SAntti Palosaari 476*395d00d1SAntti Palosaari s32tmp = 0x10000 * (tuner_frequency - c->frequency); 477*395d00d1SAntti Palosaari s32tmp = (2 * s32tmp + M88DS3103_MCLK_KHZ) / (2 * M88DS3103_MCLK_KHZ); 478*395d00d1SAntti Palosaari if (s32tmp < 0) 479*395d00d1SAntti Palosaari s32tmp += 0x10000; 480*395d00d1SAntti Palosaari 481*395d00d1SAntti Palosaari buf[0] = (s32tmp >> 0) & 0xff; 482*395d00d1SAntti Palosaari buf[1] = (s32tmp >> 8) & 0xff; 483*395d00d1SAntti Palosaari ret = m88ds3103_wr_regs(priv, 0x5e, buf, 2); 484*395d00d1SAntti Palosaari if (ret) 485*395d00d1SAntti Palosaari goto err; 486*395d00d1SAntti Palosaari 487*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x00, 0x00); 488*395d00d1SAntti Palosaari if (ret) 489*395d00d1SAntti Palosaari goto err; 490*395d00d1SAntti Palosaari 491*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xb2, 0x00); 492*395d00d1SAntti Palosaari if (ret) 493*395d00d1SAntti Palosaari goto err; 494*395d00d1SAntti Palosaari 495*395d00d1SAntti Palosaari priv->delivery_system = c->delivery_system; 496*395d00d1SAntti Palosaari 497*395d00d1SAntti Palosaari return 0; 498*395d00d1SAntti Palosaari err: 499*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 500*395d00d1SAntti Palosaari return ret; 501*395d00d1SAntti Palosaari } 502*395d00d1SAntti Palosaari 503*395d00d1SAntti Palosaari static int m88ds3103_init(struct dvb_frontend *fe) 504*395d00d1SAntti Palosaari { 505*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 506*395d00d1SAntti Palosaari int ret, len, remaining; 507*395d00d1SAntti Palosaari const struct firmware *fw = NULL; 508*395d00d1SAntti Palosaari u8 *fw_file = M88DS3103_FIRMWARE; 509*395d00d1SAntti Palosaari u8 u8tmp; 510*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 511*395d00d1SAntti Palosaari 512*395d00d1SAntti Palosaari /* set cold state by default */ 513*395d00d1SAntti Palosaari priv->warm = false; 514*395d00d1SAntti Palosaari 515*395d00d1SAntti Palosaari /* wake up device from sleep */ 516*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x01, 0x01); 517*395d00d1SAntti Palosaari if (ret) 518*395d00d1SAntti Palosaari goto err; 519*395d00d1SAntti Palosaari 520*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x00, 0x01); 521*395d00d1SAntti Palosaari if (ret) 522*395d00d1SAntti Palosaari goto err; 523*395d00d1SAntti Palosaari 524*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x00, 0x10); 525*395d00d1SAntti Palosaari if (ret) 526*395d00d1SAntti Palosaari goto err; 527*395d00d1SAntti Palosaari 528*395d00d1SAntti Palosaari /* reset */ 529*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x07, 0x60); 530*395d00d1SAntti Palosaari if (ret) 531*395d00d1SAntti Palosaari goto err; 532*395d00d1SAntti Palosaari 533*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x07, 0x00); 534*395d00d1SAntti Palosaari if (ret) 535*395d00d1SAntti Palosaari goto err; 536*395d00d1SAntti Palosaari 537*395d00d1SAntti Palosaari /* firmware status */ 538*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp); 539*395d00d1SAntti Palosaari if (ret) 540*395d00d1SAntti Palosaari goto err; 541*395d00d1SAntti Palosaari 542*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: firmware=%02x\n", __func__, u8tmp); 543*395d00d1SAntti Palosaari 544*395d00d1SAntti Palosaari if (u8tmp) 545*395d00d1SAntti Palosaari goto skip_fw_download; 546*395d00d1SAntti Palosaari 547*395d00d1SAntti Palosaari /* cold state - try to download firmware */ 548*395d00d1SAntti Palosaari dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state\n", 549*395d00d1SAntti Palosaari KBUILD_MODNAME, m88ds3103_ops.info.name); 550*395d00d1SAntti Palosaari 551*395d00d1SAntti Palosaari /* request the firmware, this will block and timeout */ 552*395d00d1SAntti Palosaari ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); 553*395d00d1SAntti Palosaari if (ret) { 554*395d00d1SAntti Palosaari dev_err(&priv->i2c->dev, "%s: firmare file '%s' not found\n", 555*395d00d1SAntti Palosaari KBUILD_MODNAME, fw_file); 556*395d00d1SAntti Palosaari goto err; 557*395d00d1SAntti Palosaari } 558*395d00d1SAntti Palosaari 559*395d00d1SAntti Palosaari dev_info(&priv->i2c->dev, "%s: downloading firmware from file '%s'\n", 560*395d00d1SAntti Palosaari KBUILD_MODNAME, fw_file); 561*395d00d1SAntti Palosaari 562*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xb2, 0x01); 563*395d00d1SAntti Palosaari if (ret) 564*395d00d1SAntti Palosaari goto err; 565*395d00d1SAntti Palosaari 566*395d00d1SAntti Palosaari for (remaining = fw->size; remaining > 0; 567*395d00d1SAntti Palosaari remaining -= (priv->cfg->i2c_wr_max - 1)) { 568*395d00d1SAntti Palosaari len = remaining; 569*395d00d1SAntti Palosaari if (len > (priv->cfg->i2c_wr_max - 1)) 570*395d00d1SAntti Palosaari len = (priv->cfg->i2c_wr_max - 1); 571*395d00d1SAntti Palosaari 572*395d00d1SAntti Palosaari ret = m88ds3103_wr_regs(priv, 0xb0, 573*395d00d1SAntti Palosaari &fw->data[fw->size - remaining], len); 574*395d00d1SAntti Palosaari if (ret) { 575*395d00d1SAntti Palosaari dev_err(&priv->i2c->dev, 576*395d00d1SAntti Palosaari "%s: firmware download failed=%d\n", 577*395d00d1SAntti Palosaari KBUILD_MODNAME, ret); 578*395d00d1SAntti Palosaari goto err; 579*395d00d1SAntti Palosaari } 580*395d00d1SAntti Palosaari } 581*395d00d1SAntti Palosaari 582*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xb2, 0x00); 583*395d00d1SAntti Palosaari if (ret) 584*395d00d1SAntti Palosaari goto err; 585*395d00d1SAntti Palosaari 586*395d00d1SAntti Palosaari release_firmware(fw); 587*395d00d1SAntti Palosaari fw = NULL; 588*395d00d1SAntti Palosaari 589*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp); 590*395d00d1SAntti Palosaari if (ret) 591*395d00d1SAntti Palosaari goto err; 592*395d00d1SAntti Palosaari 593*395d00d1SAntti Palosaari if (!u8tmp) { 594*395d00d1SAntti Palosaari dev_info(&priv->i2c->dev, "%s: firmware did not run\n", 595*395d00d1SAntti Palosaari KBUILD_MODNAME); 596*395d00d1SAntti Palosaari ret = -EFAULT; 597*395d00d1SAntti Palosaari goto err; 598*395d00d1SAntti Palosaari } 599*395d00d1SAntti Palosaari 600*395d00d1SAntti Palosaari dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n", 601*395d00d1SAntti Palosaari KBUILD_MODNAME, m88ds3103_ops.info.name); 602*395d00d1SAntti Palosaari dev_info(&priv->i2c->dev, "%s: firmware version %X.%X\n", 603*395d00d1SAntti Palosaari KBUILD_MODNAME, (u8tmp >> 4) & 0xf, (u8tmp >> 0 & 0xf)); 604*395d00d1SAntti Palosaari 605*395d00d1SAntti Palosaari skip_fw_download: 606*395d00d1SAntti Palosaari /* warm state */ 607*395d00d1SAntti Palosaari priv->warm = true; 608*395d00d1SAntti Palosaari 609*395d00d1SAntti Palosaari return 0; 610*395d00d1SAntti Palosaari err: 611*395d00d1SAntti Palosaari if (fw) 612*395d00d1SAntti Palosaari release_firmware(fw); 613*395d00d1SAntti Palosaari 614*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 615*395d00d1SAntti Palosaari return ret; 616*395d00d1SAntti Palosaari } 617*395d00d1SAntti Palosaari 618*395d00d1SAntti Palosaari static int m88ds3103_sleep(struct dvb_frontend *fe) 619*395d00d1SAntti Palosaari { 620*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 621*395d00d1SAntti Palosaari int ret; 622*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 623*395d00d1SAntti Palosaari 624*395d00d1SAntti Palosaari priv->delivery_system = SYS_UNDEFINED; 625*395d00d1SAntti Palosaari 626*395d00d1SAntti Palosaari /* TS Hi-Z */ 627*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x27, 0x00, 0x01); 628*395d00d1SAntti Palosaari if (ret) 629*395d00d1SAntti Palosaari goto err; 630*395d00d1SAntti Palosaari 631*395d00d1SAntti Palosaari /* sleep */ 632*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01); 633*395d00d1SAntti Palosaari if (ret) 634*395d00d1SAntti Palosaari goto err; 635*395d00d1SAntti Palosaari 636*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01); 637*395d00d1SAntti Palosaari if (ret) 638*395d00d1SAntti Palosaari goto err; 639*395d00d1SAntti Palosaari 640*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10); 641*395d00d1SAntti Palosaari if (ret) 642*395d00d1SAntti Palosaari goto err; 643*395d00d1SAntti Palosaari 644*395d00d1SAntti Palosaari return 0; 645*395d00d1SAntti Palosaari err: 646*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 647*395d00d1SAntti Palosaari return ret; 648*395d00d1SAntti Palosaari } 649*395d00d1SAntti Palosaari 650*395d00d1SAntti Palosaari static int m88ds3103_get_frontend(struct dvb_frontend *fe) 651*395d00d1SAntti Palosaari { 652*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 653*395d00d1SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 654*395d00d1SAntti Palosaari int ret; 655*395d00d1SAntti Palosaari u8 buf[3]; 656*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 657*395d00d1SAntti Palosaari 658*395d00d1SAntti Palosaari if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) { 659*395d00d1SAntti Palosaari ret = -EAGAIN; 660*395d00d1SAntti Palosaari goto err; 661*395d00d1SAntti Palosaari } 662*395d00d1SAntti Palosaari 663*395d00d1SAntti Palosaari switch (c->delivery_system) { 664*395d00d1SAntti Palosaari case SYS_DVBS: 665*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xe0, &buf[0]); 666*395d00d1SAntti Palosaari if (ret) 667*395d00d1SAntti Palosaari goto err; 668*395d00d1SAntti Palosaari 669*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xe6, &buf[1]); 670*395d00d1SAntti Palosaari if (ret) 671*395d00d1SAntti Palosaari goto err; 672*395d00d1SAntti Palosaari 673*395d00d1SAntti Palosaari switch ((buf[0] >> 2) & 0x01) { 674*395d00d1SAntti Palosaari case 0: 675*395d00d1SAntti Palosaari c->inversion = INVERSION_OFF; 676*395d00d1SAntti Palosaari break; 677*395d00d1SAntti Palosaari case 1: 678*395d00d1SAntti Palosaari c->inversion = INVERSION_ON; 679*395d00d1SAntti Palosaari break; 680*395d00d1SAntti Palosaari default: 681*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", 682*395d00d1SAntti Palosaari __func__); 683*395d00d1SAntti Palosaari } 684*395d00d1SAntti Palosaari 685*395d00d1SAntti Palosaari switch ((buf[1] >> 5) & 0x07) { 686*395d00d1SAntti Palosaari case 0: 687*395d00d1SAntti Palosaari c->fec_inner = FEC_7_8; 688*395d00d1SAntti Palosaari break; 689*395d00d1SAntti Palosaari case 1: 690*395d00d1SAntti Palosaari c->fec_inner = FEC_5_6; 691*395d00d1SAntti Palosaari break; 692*395d00d1SAntti Palosaari case 2: 693*395d00d1SAntti Palosaari c->fec_inner = FEC_3_4; 694*395d00d1SAntti Palosaari break; 695*395d00d1SAntti Palosaari case 3: 696*395d00d1SAntti Palosaari c->fec_inner = FEC_2_3; 697*395d00d1SAntti Palosaari break; 698*395d00d1SAntti Palosaari case 4: 699*395d00d1SAntti Palosaari c->fec_inner = FEC_1_2; 700*395d00d1SAntti Palosaari break; 701*395d00d1SAntti Palosaari default: 702*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n", 703*395d00d1SAntti Palosaari __func__); 704*395d00d1SAntti Palosaari } 705*395d00d1SAntti Palosaari 706*395d00d1SAntti Palosaari c->modulation = QPSK; 707*395d00d1SAntti Palosaari 708*395d00d1SAntti Palosaari break; 709*395d00d1SAntti Palosaari case SYS_DVBS2: 710*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0x7e, &buf[0]); 711*395d00d1SAntti Palosaari if (ret) 712*395d00d1SAntti Palosaari goto err; 713*395d00d1SAntti Palosaari 714*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0x89, &buf[1]); 715*395d00d1SAntti Palosaari if (ret) 716*395d00d1SAntti Palosaari goto err; 717*395d00d1SAntti Palosaari 718*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xf2, &buf[2]); 719*395d00d1SAntti Palosaari if (ret) 720*395d00d1SAntti Palosaari goto err; 721*395d00d1SAntti Palosaari 722*395d00d1SAntti Palosaari switch ((buf[0] >> 0) & 0x0f) { 723*395d00d1SAntti Palosaari case 2: 724*395d00d1SAntti Palosaari c->fec_inner = FEC_2_5; 725*395d00d1SAntti Palosaari break; 726*395d00d1SAntti Palosaari case 3: 727*395d00d1SAntti Palosaari c->fec_inner = FEC_1_2; 728*395d00d1SAntti Palosaari break; 729*395d00d1SAntti Palosaari case 4: 730*395d00d1SAntti Palosaari c->fec_inner = FEC_3_5; 731*395d00d1SAntti Palosaari break; 732*395d00d1SAntti Palosaari case 5: 733*395d00d1SAntti Palosaari c->fec_inner = FEC_2_3; 734*395d00d1SAntti Palosaari break; 735*395d00d1SAntti Palosaari case 6: 736*395d00d1SAntti Palosaari c->fec_inner = FEC_3_4; 737*395d00d1SAntti Palosaari break; 738*395d00d1SAntti Palosaari case 7: 739*395d00d1SAntti Palosaari c->fec_inner = FEC_4_5; 740*395d00d1SAntti Palosaari break; 741*395d00d1SAntti Palosaari case 8: 742*395d00d1SAntti Palosaari c->fec_inner = FEC_5_6; 743*395d00d1SAntti Palosaari break; 744*395d00d1SAntti Palosaari case 9: 745*395d00d1SAntti Palosaari c->fec_inner = FEC_8_9; 746*395d00d1SAntti Palosaari break; 747*395d00d1SAntti Palosaari case 10: 748*395d00d1SAntti Palosaari c->fec_inner = FEC_9_10; 749*395d00d1SAntti Palosaari break; 750*395d00d1SAntti Palosaari default: 751*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid fec_inner\n", 752*395d00d1SAntti Palosaari __func__); 753*395d00d1SAntti Palosaari } 754*395d00d1SAntti Palosaari 755*395d00d1SAntti Palosaari switch ((buf[0] >> 5) & 0x01) { 756*395d00d1SAntti Palosaari case 0: 757*395d00d1SAntti Palosaari c->pilot = PILOT_OFF; 758*395d00d1SAntti Palosaari break; 759*395d00d1SAntti Palosaari case 1: 760*395d00d1SAntti Palosaari c->pilot = PILOT_ON; 761*395d00d1SAntti Palosaari break; 762*395d00d1SAntti Palosaari default: 763*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n", 764*395d00d1SAntti Palosaari __func__); 765*395d00d1SAntti Palosaari } 766*395d00d1SAntti Palosaari 767*395d00d1SAntti Palosaari switch ((buf[0] >> 6) & 0x07) { 768*395d00d1SAntti Palosaari case 0: 769*395d00d1SAntti Palosaari c->modulation = QPSK; 770*395d00d1SAntti Palosaari break; 771*395d00d1SAntti Palosaari case 1: 772*395d00d1SAntti Palosaari c->modulation = PSK_8; 773*395d00d1SAntti Palosaari break; 774*395d00d1SAntti Palosaari case 2: 775*395d00d1SAntti Palosaari c->modulation = APSK_16; 776*395d00d1SAntti Palosaari break; 777*395d00d1SAntti Palosaari case 3: 778*395d00d1SAntti Palosaari c->modulation = APSK_32; 779*395d00d1SAntti Palosaari break; 780*395d00d1SAntti Palosaari default: 781*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid modulation\n", 782*395d00d1SAntti Palosaari __func__); 783*395d00d1SAntti Palosaari } 784*395d00d1SAntti Palosaari 785*395d00d1SAntti Palosaari switch ((buf[1] >> 7) & 0x01) { 786*395d00d1SAntti Palosaari case 0: 787*395d00d1SAntti Palosaari c->inversion = INVERSION_OFF; 788*395d00d1SAntti Palosaari break; 789*395d00d1SAntti Palosaari case 1: 790*395d00d1SAntti Palosaari c->inversion = INVERSION_ON; 791*395d00d1SAntti Palosaari break; 792*395d00d1SAntti Palosaari default: 793*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", 794*395d00d1SAntti Palosaari __func__); 795*395d00d1SAntti Palosaari } 796*395d00d1SAntti Palosaari 797*395d00d1SAntti Palosaari switch ((buf[2] >> 0) & 0x03) { 798*395d00d1SAntti Palosaari case 0: 799*395d00d1SAntti Palosaari c->rolloff = ROLLOFF_35; 800*395d00d1SAntti Palosaari break; 801*395d00d1SAntti Palosaari case 1: 802*395d00d1SAntti Palosaari c->rolloff = ROLLOFF_25; 803*395d00d1SAntti Palosaari break; 804*395d00d1SAntti Palosaari case 2: 805*395d00d1SAntti Palosaari c->rolloff = ROLLOFF_20; 806*395d00d1SAntti Palosaari break; 807*395d00d1SAntti Palosaari default: 808*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n", 809*395d00d1SAntti Palosaari __func__); 810*395d00d1SAntti Palosaari } 811*395d00d1SAntti Palosaari break; 812*395d00d1SAntti Palosaari default: 813*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", 814*395d00d1SAntti Palosaari __func__); 815*395d00d1SAntti Palosaari ret = -EINVAL; 816*395d00d1SAntti Palosaari goto err; 817*395d00d1SAntti Palosaari } 818*395d00d1SAntti Palosaari 819*395d00d1SAntti Palosaari ret = m88ds3103_rd_regs(priv, 0x6d, buf, 2); 820*395d00d1SAntti Palosaari if (ret) 821*395d00d1SAntti Palosaari goto err; 822*395d00d1SAntti Palosaari 823*395d00d1SAntti Palosaari c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) * 824*395d00d1SAntti Palosaari M88DS3103_MCLK_KHZ * 1000 / 0x10000; 825*395d00d1SAntti Palosaari 826*395d00d1SAntti Palosaari return 0; 827*395d00d1SAntti Palosaari err: 828*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 829*395d00d1SAntti Palosaari return ret; 830*395d00d1SAntti Palosaari } 831*395d00d1SAntti Palosaari 832*395d00d1SAntti Palosaari static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr) 833*395d00d1SAntti Palosaari { 834*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 835*395d00d1SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 836*395d00d1SAntti Palosaari int ret, i, tmp; 837*395d00d1SAntti Palosaari u8 buf[3]; 838*395d00d1SAntti Palosaari u16 noise, signal; 839*395d00d1SAntti Palosaari u32 noise_tot, signal_tot; 840*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 841*395d00d1SAntti Palosaari /* reports SNR in resolution of 0.1 dB */ 842*395d00d1SAntti Palosaari 843*395d00d1SAntti Palosaari /* more iterations for more accurate estimation */ 844*395d00d1SAntti Palosaari #define M88DS3103_SNR_ITERATIONS 3 845*395d00d1SAntti Palosaari 846*395d00d1SAntti Palosaari switch (c->delivery_system) { 847*395d00d1SAntti Palosaari case SYS_DVBS: 848*395d00d1SAntti Palosaari tmp = 0; 849*395d00d1SAntti Palosaari 850*395d00d1SAntti Palosaari for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { 851*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0xff, &buf[0]); 852*395d00d1SAntti Palosaari if (ret) 853*395d00d1SAntti Palosaari goto err; 854*395d00d1SAntti Palosaari 855*395d00d1SAntti Palosaari tmp += buf[0]; 856*395d00d1SAntti Palosaari } 857*395d00d1SAntti Palosaari 858*395d00d1SAntti Palosaari /* use of one register limits max value to 15 dB */ 859*395d00d1SAntti Palosaari /* SNR(X) dB = 10 * ln(X) / ln(10) dB */ 860*395d00d1SAntti Palosaari tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS); 861*395d00d1SAntti Palosaari if (tmp) 862*395d00d1SAntti Palosaari *snr = 100ul * intlog2(tmp) / intlog2(10); 863*395d00d1SAntti Palosaari else 864*395d00d1SAntti Palosaari *snr = 0; 865*395d00d1SAntti Palosaari break; 866*395d00d1SAntti Palosaari case SYS_DVBS2: 867*395d00d1SAntti Palosaari noise_tot = 0; 868*395d00d1SAntti Palosaari signal_tot = 0; 869*395d00d1SAntti Palosaari 870*395d00d1SAntti Palosaari for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { 871*395d00d1SAntti Palosaari ret = m88ds3103_rd_regs(priv, 0x8c, buf, 3); 872*395d00d1SAntti Palosaari if (ret) 873*395d00d1SAntti Palosaari goto err; 874*395d00d1SAntti Palosaari 875*395d00d1SAntti Palosaari noise = buf[1] << 6; /* [13:6] */ 876*395d00d1SAntti Palosaari noise |= buf[0] & 0x3f; /* [5:0] */ 877*395d00d1SAntti Palosaari noise >>= 2; 878*395d00d1SAntti Palosaari signal = buf[2] * buf[2]; 879*395d00d1SAntti Palosaari signal >>= 1; 880*395d00d1SAntti Palosaari 881*395d00d1SAntti Palosaari noise_tot += noise; 882*395d00d1SAntti Palosaari signal_tot += signal; 883*395d00d1SAntti Palosaari } 884*395d00d1SAntti Palosaari 885*395d00d1SAntti Palosaari noise = noise_tot / M88DS3103_SNR_ITERATIONS; 886*395d00d1SAntti Palosaari signal = signal_tot / M88DS3103_SNR_ITERATIONS; 887*395d00d1SAntti Palosaari 888*395d00d1SAntti Palosaari /* SNR(X) dB = 10 * log10(X) dB */ 889*395d00d1SAntti Palosaari if (signal > noise) { 890*395d00d1SAntti Palosaari tmp = signal / noise; 891*395d00d1SAntti Palosaari *snr = 100ul * intlog10(tmp) / (1 << 24); 892*395d00d1SAntti Palosaari } else 893*395d00d1SAntti Palosaari *snr = 0; 894*395d00d1SAntti Palosaari break; 895*395d00d1SAntti Palosaari default: 896*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n", 897*395d00d1SAntti Palosaari __func__); 898*395d00d1SAntti Palosaari ret = -EINVAL; 899*395d00d1SAntti Palosaari goto err; 900*395d00d1SAntti Palosaari } 901*395d00d1SAntti Palosaari 902*395d00d1SAntti Palosaari return 0; 903*395d00d1SAntti Palosaari err: 904*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 905*395d00d1SAntti Palosaari return ret; 906*395d00d1SAntti Palosaari } 907*395d00d1SAntti Palosaari 908*395d00d1SAntti Palosaari 909*395d00d1SAntti Palosaari static int m88ds3103_set_tone(struct dvb_frontend *fe, 910*395d00d1SAntti Palosaari fe_sec_tone_mode_t fe_sec_tone_mode) 911*395d00d1SAntti Palosaari { 912*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 913*395d00d1SAntti Palosaari int ret; 914*395d00d1SAntti Palosaari u8 u8tmp, tone, reg_a1_mask; 915*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: fe_sec_tone_mode=%d\n", __func__, 916*395d00d1SAntti Palosaari fe_sec_tone_mode); 917*395d00d1SAntti Palosaari 918*395d00d1SAntti Palosaari if (!priv->warm) { 919*395d00d1SAntti Palosaari ret = -EAGAIN; 920*395d00d1SAntti Palosaari goto err; 921*395d00d1SAntti Palosaari } 922*395d00d1SAntti Palosaari 923*395d00d1SAntti Palosaari switch (fe_sec_tone_mode) { 924*395d00d1SAntti Palosaari case SEC_TONE_ON: 925*395d00d1SAntti Palosaari tone = 0; 926*395d00d1SAntti Palosaari reg_a1_mask = 0x87; 927*395d00d1SAntti Palosaari break; 928*395d00d1SAntti Palosaari case SEC_TONE_OFF: 929*395d00d1SAntti Palosaari tone = 1; 930*395d00d1SAntti Palosaari reg_a1_mask = 0x00; 931*395d00d1SAntti Palosaari break; 932*395d00d1SAntti Palosaari default: 933*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n", 934*395d00d1SAntti Palosaari __func__); 935*395d00d1SAntti Palosaari ret = -EINVAL; 936*395d00d1SAntti Palosaari goto err; 937*395d00d1SAntti Palosaari } 938*395d00d1SAntti Palosaari 939*395d00d1SAntti Palosaari u8tmp = tone << 7 | priv->cfg->envelope_mode << 5; 940*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); 941*395d00d1SAntti Palosaari if (ret) 942*395d00d1SAntti Palosaari goto err; 943*395d00d1SAntti Palosaari 944*395d00d1SAntti Palosaari u8tmp = 1 << 2; 945*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa1, u8tmp, reg_a1_mask); 946*395d00d1SAntti Palosaari if (ret) 947*395d00d1SAntti Palosaari goto err; 948*395d00d1SAntti Palosaari 949*395d00d1SAntti Palosaari return 0; 950*395d00d1SAntti Palosaari err: 951*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 952*395d00d1SAntti Palosaari return ret; 953*395d00d1SAntti Palosaari } 954*395d00d1SAntti Palosaari 955*395d00d1SAntti Palosaari static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe, 956*395d00d1SAntti Palosaari struct dvb_diseqc_master_cmd *diseqc_cmd) 957*395d00d1SAntti Palosaari { 958*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 959*395d00d1SAntti Palosaari int ret, i; 960*395d00d1SAntti Palosaari u8 u8tmp; 961*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: msg=%*ph\n", __func__, 962*395d00d1SAntti Palosaari diseqc_cmd->msg_len, diseqc_cmd->msg); 963*395d00d1SAntti Palosaari 964*395d00d1SAntti Palosaari if (!priv->warm) { 965*395d00d1SAntti Palosaari ret = -EAGAIN; 966*395d00d1SAntti Palosaari goto err; 967*395d00d1SAntti Palosaari } 968*395d00d1SAntti Palosaari 969*395d00d1SAntti Palosaari if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) { 970*395d00d1SAntti Palosaari ret = -EINVAL; 971*395d00d1SAntti Palosaari goto err; 972*395d00d1SAntti Palosaari } 973*395d00d1SAntti Palosaari 974*395d00d1SAntti Palosaari u8tmp = priv->cfg->envelope_mode << 5; 975*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); 976*395d00d1SAntti Palosaari if (ret) 977*395d00d1SAntti Palosaari goto err; 978*395d00d1SAntti Palosaari 979*395d00d1SAntti Palosaari ret = m88ds3103_wr_regs(priv, 0xa3, diseqc_cmd->msg, 980*395d00d1SAntti Palosaari diseqc_cmd->msg_len); 981*395d00d1SAntti Palosaari if (ret) 982*395d00d1SAntti Palosaari goto err; 983*395d00d1SAntti Palosaari 984*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xa1, 985*395d00d1SAntti Palosaari (diseqc_cmd->msg_len - 1) << 3 | 0x07); 986*395d00d1SAntti Palosaari if (ret) 987*395d00d1SAntti Palosaari goto err; 988*395d00d1SAntti Palosaari 989*395d00d1SAntti Palosaari /* DiSEqC message typical period is 54 ms */ 990*395d00d1SAntti Palosaari usleep_range(40000, 60000); 991*395d00d1SAntti Palosaari 992*395d00d1SAntti Palosaari /* wait DiSEqC TX ready */ 993*395d00d1SAntti Palosaari for (i = 20, u8tmp = 1; i && u8tmp; i--) { 994*395d00d1SAntti Palosaari usleep_range(5000, 10000); 995*395d00d1SAntti Palosaari 996*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40); 997*395d00d1SAntti Palosaari if (ret) 998*395d00d1SAntti Palosaari goto err; 999*395d00d1SAntti Palosaari } 1000*395d00d1SAntti Palosaari 1001*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); 1002*395d00d1SAntti Palosaari 1003*395d00d1SAntti Palosaari if (i == 0) { 1004*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__); 1005*395d00d1SAntti Palosaari 1006*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa1, 0x40, 0xc0); 1007*395d00d1SAntti Palosaari if (ret) 1008*395d00d1SAntti Palosaari goto err; 1009*395d00d1SAntti Palosaari } 1010*395d00d1SAntti Palosaari 1011*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0); 1012*395d00d1SAntti Palosaari if (ret) 1013*395d00d1SAntti Palosaari goto err; 1014*395d00d1SAntti Palosaari 1015*395d00d1SAntti Palosaari if (i == 0) { 1016*395d00d1SAntti Palosaari ret = -ETIMEDOUT; 1017*395d00d1SAntti Palosaari goto err; 1018*395d00d1SAntti Palosaari } 1019*395d00d1SAntti Palosaari 1020*395d00d1SAntti Palosaari return 0; 1021*395d00d1SAntti Palosaari err: 1022*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 1023*395d00d1SAntti Palosaari return ret; 1024*395d00d1SAntti Palosaari } 1025*395d00d1SAntti Palosaari 1026*395d00d1SAntti Palosaari static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, 1027*395d00d1SAntti Palosaari fe_sec_mini_cmd_t fe_sec_mini_cmd) 1028*395d00d1SAntti Palosaari { 1029*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 1030*395d00d1SAntti Palosaari int ret, i; 1031*395d00d1SAntti Palosaari u8 u8tmp, burst; 1032*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__, 1033*395d00d1SAntti Palosaari fe_sec_mini_cmd); 1034*395d00d1SAntti Palosaari 1035*395d00d1SAntti Palosaari if (!priv->warm) { 1036*395d00d1SAntti Palosaari ret = -EAGAIN; 1037*395d00d1SAntti Palosaari goto err; 1038*395d00d1SAntti Palosaari } 1039*395d00d1SAntti Palosaari 1040*395d00d1SAntti Palosaari u8tmp = priv->cfg->envelope_mode << 5; 1041*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa2, u8tmp, 0xe0); 1042*395d00d1SAntti Palosaari if (ret) 1043*395d00d1SAntti Palosaari goto err; 1044*395d00d1SAntti Palosaari 1045*395d00d1SAntti Palosaari switch (fe_sec_mini_cmd) { 1046*395d00d1SAntti Palosaari case SEC_MINI_A: 1047*395d00d1SAntti Palosaari burst = 0x02; 1048*395d00d1SAntti Palosaari break; 1049*395d00d1SAntti Palosaari case SEC_MINI_B: 1050*395d00d1SAntti Palosaari burst = 0x01; 1051*395d00d1SAntti Palosaari break; 1052*395d00d1SAntti Palosaari default: 1053*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n", 1054*395d00d1SAntti Palosaari __func__); 1055*395d00d1SAntti Palosaari ret = -EINVAL; 1056*395d00d1SAntti Palosaari goto err; 1057*395d00d1SAntti Palosaari } 1058*395d00d1SAntti Palosaari 1059*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0xa1, burst); 1060*395d00d1SAntti Palosaari if (ret) 1061*395d00d1SAntti Palosaari goto err; 1062*395d00d1SAntti Palosaari 1063*395d00d1SAntti Palosaari /* DiSEqC ToneBurst period is 12.5 ms */ 1064*395d00d1SAntti Palosaari usleep_range(11000, 20000); 1065*395d00d1SAntti Palosaari 1066*395d00d1SAntti Palosaari /* wait DiSEqC TX ready */ 1067*395d00d1SAntti Palosaari for (i = 5, u8tmp = 1; i && u8tmp; i--) { 1068*395d00d1SAntti Palosaari usleep_range(800, 2000); 1069*395d00d1SAntti Palosaari 1070*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg_mask(priv, 0xa1, &u8tmp, 0x40); 1071*395d00d1SAntti Palosaari if (ret) 1072*395d00d1SAntti Palosaari goto err; 1073*395d00d1SAntti Palosaari } 1074*395d00d1SAntti Palosaari 1075*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i); 1076*395d00d1SAntti Palosaari 1077*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0xa2, 0x80, 0xc0); 1078*395d00d1SAntti Palosaari if (ret) 1079*395d00d1SAntti Palosaari goto err; 1080*395d00d1SAntti Palosaari 1081*395d00d1SAntti Palosaari if (i == 0) { 1082*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: diseqc tx timeout\n", __func__); 1083*395d00d1SAntti Palosaari ret = -ETIMEDOUT; 1084*395d00d1SAntti Palosaari goto err; 1085*395d00d1SAntti Palosaari } 1086*395d00d1SAntti Palosaari 1087*395d00d1SAntti Palosaari return 0; 1088*395d00d1SAntti Palosaari err: 1089*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 1090*395d00d1SAntti Palosaari return ret; 1091*395d00d1SAntti Palosaari } 1092*395d00d1SAntti Palosaari 1093*395d00d1SAntti Palosaari static int m88ds3103_get_tune_settings(struct dvb_frontend *fe, 1094*395d00d1SAntti Palosaari struct dvb_frontend_tune_settings *s) 1095*395d00d1SAntti Palosaari { 1096*395d00d1SAntti Palosaari s->min_delay_ms = 3000; 1097*395d00d1SAntti Palosaari 1098*395d00d1SAntti Palosaari return 0; 1099*395d00d1SAntti Palosaari } 1100*395d00d1SAntti Palosaari 1101*395d00d1SAntti Palosaari static u32 m88ds3103_tuner_i2c_func(struct i2c_adapter *adapter) 1102*395d00d1SAntti Palosaari { 1103*395d00d1SAntti Palosaari return I2C_FUNC_I2C; 1104*395d00d1SAntti Palosaari } 1105*395d00d1SAntti Palosaari 1106*395d00d1SAntti Palosaari static int m88ds3103_tuner_i2c_xfer(struct i2c_adapter *i2c_adap, 1107*395d00d1SAntti Palosaari struct i2c_msg msg[], int num) 1108*395d00d1SAntti Palosaari { 1109*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = i2c_get_adapdata(i2c_adap); 1110*395d00d1SAntti Palosaari int ret; 1111*395d00d1SAntti Palosaari struct i2c_msg gate_open_msg[1] = { 1112*395d00d1SAntti Palosaari { 1113*395d00d1SAntti Palosaari .addr = priv->cfg->i2c_addr, 1114*395d00d1SAntti Palosaari .flags = 0, 1115*395d00d1SAntti Palosaari .len = 2, 1116*395d00d1SAntti Palosaari .buf = "\x03\x11", 1117*395d00d1SAntti Palosaari } 1118*395d00d1SAntti Palosaari }; 1119*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: num=%d\n", __func__, num); 1120*395d00d1SAntti Palosaari 1121*395d00d1SAntti Palosaari mutex_lock(&priv->i2c_mutex); 1122*395d00d1SAntti Palosaari 1123*395d00d1SAntti Palosaari /* open i2c-gate */ 1124*395d00d1SAntti Palosaari ret = i2c_transfer(priv->i2c, gate_open_msg, 1); 1125*395d00d1SAntti Palosaari if (ret != 1) { 1126*395d00d1SAntti Palosaari mutex_unlock(&priv->i2c_mutex); 1127*395d00d1SAntti Palosaari dev_warn(&priv->i2c->dev, 1128*395d00d1SAntti Palosaari "%s: i2c wr failed=%d\n", 1129*395d00d1SAntti Palosaari KBUILD_MODNAME, ret); 1130*395d00d1SAntti Palosaari ret = -EREMOTEIO; 1131*395d00d1SAntti Palosaari goto err; 1132*395d00d1SAntti Palosaari } 1133*395d00d1SAntti Palosaari 1134*395d00d1SAntti Palosaari ret = i2c_transfer(priv->i2c, msg, num); 1135*395d00d1SAntti Palosaari mutex_unlock(&priv->i2c_mutex); 1136*395d00d1SAntti Palosaari if (ret < 0) 1137*395d00d1SAntti Palosaari dev_warn(&priv->i2c->dev, "%s: i2c failed=%d\n", 1138*395d00d1SAntti Palosaari KBUILD_MODNAME, ret); 1139*395d00d1SAntti Palosaari 1140*395d00d1SAntti Palosaari return ret; 1141*395d00d1SAntti Palosaari err: 1142*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 1143*395d00d1SAntti Palosaari return ret; 1144*395d00d1SAntti Palosaari } 1145*395d00d1SAntti Palosaari 1146*395d00d1SAntti Palosaari static struct i2c_algorithm m88ds3103_tuner_i2c_algo = { 1147*395d00d1SAntti Palosaari .master_xfer = m88ds3103_tuner_i2c_xfer, 1148*395d00d1SAntti Palosaari .functionality = m88ds3103_tuner_i2c_func, 1149*395d00d1SAntti Palosaari }; 1150*395d00d1SAntti Palosaari 1151*395d00d1SAntti Palosaari static void m88ds3103_release(struct dvb_frontend *fe) 1152*395d00d1SAntti Palosaari { 1153*395d00d1SAntti Palosaari struct m88ds3103_priv *priv = fe->demodulator_priv; 1154*395d00d1SAntti Palosaari i2c_del_adapter(&priv->i2c_adapter); 1155*395d00d1SAntti Palosaari kfree(priv); 1156*395d00d1SAntti Palosaari } 1157*395d00d1SAntti Palosaari 1158*395d00d1SAntti Palosaari struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, 1159*395d00d1SAntti Palosaari struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter) 1160*395d00d1SAntti Palosaari { 1161*395d00d1SAntti Palosaari int ret; 1162*395d00d1SAntti Palosaari struct m88ds3103_priv *priv; 1163*395d00d1SAntti Palosaari u8 chip_id, u8tmp; 1164*395d00d1SAntti Palosaari 1165*395d00d1SAntti Palosaari /* allocate memory for the internal priv */ 1166*395d00d1SAntti Palosaari priv = kzalloc(sizeof(struct m88ds3103_priv), GFP_KERNEL); 1167*395d00d1SAntti Palosaari if (!priv) { 1168*395d00d1SAntti Palosaari ret = -ENOMEM; 1169*395d00d1SAntti Palosaari dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); 1170*395d00d1SAntti Palosaari goto err; 1171*395d00d1SAntti Palosaari } 1172*395d00d1SAntti Palosaari 1173*395d00d1SAntti Palosaari priv->cfg = cfg; 1174*395d00d1SAntti Palosaari priv->i2c = i2c; 1175*395d00d1SAntti Palosaari mutex_init(&priv->i2c_mutex); 1176*395d00d1SAntti Palosaari 1177*395d00d1SAntti Palosaari ret = m88ds3103_rd_reg(priv, 0x01, &chip_id); 1178*395d00d1SAntti Palosaari if (ret) 1179*395d00d1SAntti Palosaari goto err; 1180*395d00d1SAntti Palosaari 1181*395d00d1SAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); 1182*395d00d1SAntti Palosaari 1183*395d00d1SAntti Palosaari switch (chip_id) { 1184*395d00d1SAntti Palosaari case 0xd0: 1185*395d00d1SAntti Palosaari break; 1186*395d00d1SAntti Palosaari default: 1187*395d00d1SAntti Palosaari goto err; 1188*395d00d1SAntti Palosaari } 1189*395d00d1SAntti Palosaari 1190*395d00d1SAntti Palosaari switch (priv->cfg->clock_out) { 1191*395d00d1SAntti Palosaari case M88DS3103_CLOCK_OUT_DISABLED: 1192*395d00d1SAntti Palosaari u8tmp = 0x80; 1193*395d00d1SAntti Palosaari break; 1194*395d00d1SAntti Palosaari case M88DS3103_CLOCK_OUT_ENABLED: 1195*395d00d1SAntti Palosaari u8tmp = 0x00; 1196*395d00d1SAntti Palosaari break; 1197*395d00d1SAntti Palosaari case M88DS3103_CLOCK_OUT_ENABLED_DIV2: 1198*395d00d1SAntti Palosaari u8tmp = 0x10; 1199*395d00d1SAntti Palosaari break; 1200*395d00d1SAntti Palosaari default: 1201*395d00d1SAntti Palosaari goto err; 1202*395d00d1SAntti Palosaari } 1203*395d00d1SAntti Palosaari 1204*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg(priv, 0x29, u8tmp); 1205*395d00d1SAntti Palosaari if (ret) 1206*395d00d1SAntti Palosaari goto err; 1207*395d00d1SAntti Palosaari 1208*395d00d1SAntti Palosaari /* sleep */ 1209*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x08, 0x00, 0x01); 1210*395d00d1SAntti Palosaari if (ret) 1211*395d00d1SAntti Palosaari goto err; 1212*395d00d1SAntti Palosaari 1213*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x04, 0x01, 0x01); 1214*395d00d1SAntti Palosaari if (ret) 1215*395d00d1SAntti Palosaari goto err; 1216*395d00d1SAntti Palosaari 1217*395d00d1SAntti Palosaari ret = m88ds3103_wr_reg_mask(priv, 0x23, 0x10, 0x10); 1218*395d00d1SAntti Palosaari if (ret) 1219*395d00d1SAntti Palosaari goto err; 1220*395d00d1SAntti Palosaari 1221*395d00d1SAntti Palosaari /* create dvb_frontend */ 1222*395d00d1SAntti Palosaari memcpy(&priv->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); 1223*395d00d1SAntti Palosaari priv->fe.demodulator_priv = priv; 1224*395d00d1SAntti Palosaari 1225*395d00d1SAntti Palosaari /* create i2c adapter for tuner */ 1226*395d00d1SAntti Palosaari strlcpy(priv->i2c_adapter.name, KBUILD_MODNAME, 1227*395d00d1SAntti Palosaari sizeof(priv->i2c_adapter.name)); 1228*395d00d1SAntti Palosaari priv->i2c_adapter.algo = &m88ds3103_tuner_i2c_algo; 1229*395d00d1SAntti Palosaari priv->i2c_adapter.algo_data = NULL; 1230*395d00d1SAntti Palosaari i2c_set_adapdata(&priv->i2c_adapter, priv); 1231*395d00d1SAntti Palosaari ret = i2c_add_adapter(&priv->i2c_adapter); 1232*395d00d1SAntti Palosaari if (ret) { 1233*395d00d1SAntti Palosaari dev_err(&i2c->dev, "%s: i2c bus could not be initialized\n", 1234*395d00d1SAntti Palosaari KBUILD_MODNAME); 1235*395d00d1SAntti Palosaari goto err; 1236*395d00d1SAntti Palosaari } 1237*395d00d1SAntti Palosaari *tuner_i2c_adapter = &priv->i2c_adapter; 1238*395d00d1SAntti Palosaari 1239*395d00d1SAntti Palosaari return &priv->fe; 1240*395d00d1SAntti Palosaari err: 1241*395d00d1SAntti Palosaari dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); 1242*395d00d1SAntti Palosaari kfree(priv); 1243*395d00d1SAntti Palosaari return NULL; 1244*395d00d1SAntti Palosaari } 1245*395d00d1SAntti Palosaari EXPORT_SYMBOL(m88ds3103_attach); 1246*395d00d1SAntti Palosaari 1247*395d00d1SAntti Palosaari static struct dvb_frontend_ops m88ds3103_ops = { 1248*395d00d1SAntti Palosaari .delsys = { SYS_DVBS, SYS_DVBS2 }, 1249*395d00d1SAntti Palosaari .info = { 1250*395d00d1SAntti Palosaari .name = "Montage M88DS3103", 1251*395d00d1SAntti Palosaari .frequency_min = 950000, 1252*395d00d1SAntti Palosaari .frequency_max = 2150000, 1253*395d00d1SAntti Palosaari .frequency_tolerance = 5000, 1254*395d00d1SAntti Palosaari .symbol_rate_min = 1000000, 1255*395d00d1SAntti Palosaari .symbol_rate_max = 45000000, 1256*395d00d1SAntti Palosaari .caps = FE_CAN_INVERSION_AUTO | 1257*395d00d1SAntti Palosaari FE_CAN_FEC_1_2 | 1258*395d00d1SAntti Palosaari FE_CAN_FEC_2_3 | 1259*395d00d1SAntti Palosaari FE_CAN_FEC_3_4 | 1260*395d00d1SAntti Palosaari FE_CAN_FEC_4_5 | 1261*395d00d1SAntti Palosaari FE_CAN_FEC_5_6 | 1262*395d00d1SAntti Palosaari FE_CAN_FEC_6_7 | 1263*395d00d1SAntti Palosaari FE_CAN_FEC_7_8 | 1264*395d00d1SAntti Palosaari FE_CAN_FEC_8_9 | 1265*395d00d1SAntti Palosaari FE_CAN_FEC_AUTO | 1266*395d00d1SAntti Palosaari FE_CAN_QPSK | 1267*395d00d1SAntti Palosaari FE_CAN_RECOVER | 1268*395d00d1SAntti Palosaari FE_CAN_2G_MODULATION 1269*395d00d1SAntti Palosaari }, 1270*395d00d1SAntti Palosaari 1271*395d00d1SAntti Palosaari .release = m88ds3103_release, 1272*395d00d1SAntti Palosaari 1273*395d00d1SAntti Palosaari .get_tune_settings = m88ds3103_get_tune_settings, 1274*395d00d1SAntti Palosaari 1275*395d00d1SAntti Palosaari .init = m88ds3103_init, 1276*395d00d1SAntti Palosaari .sleep = m88ds3103_sleep, 1277*395d00d1SAntti Palosaari 1278*395d00d1SAntti Palosaari .set_frontend = m88ds3103_set_frontend, 1279*395d00d1SAntti Palosaari .get_frontend = m88ds3103_get_frontend, 1280*395d00d1SAntti Palosaari 1281*395d00d1SAntti Palosaari .read_status = m88ds3103_read_status, 1282*395d00d1SAntti Palosaari .read_snr = m88ds3103_read_snr, 1283*395d00d1SAntti Palosaari 1284*395d00d1SAntti Palosaari .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd, 1285*395d00d1SAntti Palosaari .diseqc_send_burst = m88ds3103_diseqc_send_burst, 1286*395d00d1SAntti Palosaari 1287*395d00d1SAntti Palosaari .set_tone = m88ds3103_set_tone, 1288*395d00d1SAntti Palosaari }; 1289*395d00d1SAntti Palosaari 1290*395d00d1SAntti Palosaari MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 1291*395d00d1SAntti Palosaari MODULE_DESCRIPTION("Montage M88DS3103 DVB-S/S2 demodulator driver"); 1292*395d00d1SAntti Palosaari MODULE_LICENSE("GPL"); 1293*395d00d1SAntti Palosaari MODULE_FIRMWARE(M88DS3103_FIRMWARE); 1294