116216333SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2de8e4203SAntti Palosaari /* 3de8e4203SAntti Palosaari * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver 4de8e4203SAntti Palosaari * 5de8e4203SAntti Palosaari * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> 6de8e4203SAntti Palosaari */ 7de8e4203SAntti Palosaari 8de8e4203SAntti Palosaari #include "tda10071_priv.h" 9de8e4203SAntti Palosaari 10bd336e63SMax Kellermann static const struct dvb_frontend_ops tda10071_ops; 11de8e4203SAntti Palosaari 1254ab48edSAntti Palosaari /* 1354ab48edSAntti Palosaari * XXX: regmap_update_bits() does not fit our needs as it does not support 1454ab48edSAntti Palosaari * partially volatile registers. Also it performs register read even mask is as 1554ab48edSAntti Palosaari * wide as register value. 1654ab48edSAntti Palosaari */ 17de8e4203SAntti Palosaari /* write single register with mask */ 18fca3e007SAntti Palosaari static int tda10071_wr_reg_mask(struct tda10071_dev *dev, 19babb618dSMauro Carvalho Chehab u8 reg, u8 val, u8 mask) 20de8e4203SAntti Palosaari { 21de8e4203SAntti Palosaari int ret; 22de8e4203SAntti Palosaari u8 tmp; 23de8e4203SAntti Palosaari 24de8e4203SAntti Palosaari /* no need for read if whole reg is written */ 25de8e4203SAntti Palosaari if (mask != 0xff) { 2654ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1); 27de8e4203SAntti Palosaari if (ret) 28de8e4203SAntti Palosaari return ret; 29de8e4203SAntti Palosaari 30de8e4203SAntti Palosaari val &= mask; 31de8e4203SAntti Palosaari tmp &= ~mask; 32de8e4203SAntti Palosaari val |= tmp; 33de8e4203SAntti Palosaari } 34de8e4203SAntti Palosaari 3554ab48edSAntti Palosaari return regmap_bulk_write(dev->regmap, reg, &val, 1); 36de8e4203SAntti Palosaari } 37de8e4203SAntti Palosaari 38de8e4203SAntti Palosaari /* execute firmware command */ 39fca3e007SAntti Palosaari static int tda10071_cmd_execute(struct tda10071_dev *dev, 40de8e4203SAntti Palosaari struct tda10071_cmd *cmd) 41de8e4203SAntti Palosaari { 42fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 43de8e4203SAntti Palosaari int ret, i; 4454ab48edSAntti Palosaari unsigned int uitmp; 45de8e4203SAntti Palosaari 46fca3e007SAntti Palosaari if (!dev->warm) { 47de8e4203SAntti Palosaari ret = -EFAULT; 48de8e4203SAntti Palosaari goto error; 49de8e4203SAntti Palosaari } 50de8e4203SAntti Palosaari 51e14432a5SAntti Palosaari mutex_lock(&dev->cmd_execute_mutex); 52e14432a5SAntti Palosaari 53de8e4203SAntti Palosaari /* write cmd and args for firmware */ 5454ab48edSAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0x00, cmd->args, cmd->len); 55de8e4203SAntti Palosaari if (ret) 56e14432a5SAntti Palosaari goto error_mutex_unlock; 57de8e4203SAntti Palosaari 58de8e4203SAntti Palosaari /* start cmd execution */ 5954ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0x1f, 1); 60de8e4203SAntti Palosaari if (ret) 61e14432a5SAntti Palosaari goto error_mutex_unlock; 62de8e4203SAntti Palosaari 63de8e4203SAntti Palosaari /* wait cmd execution terminate */ 6454ab48edSAntti Palosaari for (i = 1000, uitmp = 1; i && uitmp; i--) { 6554ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x1f, &uitmp); 66de8e4203SAntti Palosaari if (ret) 67e14432a5SAntti Palosaari goto error_mutex_unlock; 68de8e4203SAntti Palosaari 69d102b739SAntti Palosaari usleep_range(200, 5000); 70de8e4203SAntti Palosaari } 71de8e4203SAntti Palosaari 72e14432a5SAntti Palosaari mutex_unlock(&dev->cmd_execute_mutex); 7359ca2ce1SAntti Palosaari dev_dbg(&client->dev, "loop=%d\n", i); 74de8e4203SAntti Palosaari 75de8e4203SAntti Palosaari if (i == 0) { 76de8e4203SAntti Palosaari ret = -ETIMEDOUT; 77de8e4203SAntti Palosaari goto error; 78de8e4203SAntti Palosaari } 79de8e4203SAntti Palosaari 80de8e4203SAntti Palosaari return ret; 81e14432a5SAntti Palosaari error_mutex_unlock: 82e14432a5SAntti Palosaari mutex_unlock(&dev->cmd_execute_mutex); 83de8e4203SAntti Palosaari error: 8459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 85de8e4203SAntti Palosaari return ret; 86de8e4203SAntti Palosaari } 87de8e4203SAntti Palosaari 88de8e4203SAntti Palosaari static int tda10071_set_tone(struct dvb_frontend *fe, 890df289a2SMauro Carvalho Chehab enum fe_sec_tone_mode fe_sec_tone_mode) 90de8e4203SAntti Palosaari { 91fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 92fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 93de8e4203SAntti Palosaari struct tda10071_cmd cmd; 94de8e4203SAntti Palosaari int ret; 95de8e4203SAntti Palosaari u8 tone; 96de8e4203SAntti Palosaari 97fca3e007SAntti Palosaari if (!dev->warm) { 98de8e4203SAntti Palosaari ret = -EFAULT; 99de8e4203SAntti Palosaari goto error; 100de8e4203SAntti Palosaari } 101de8e4203SAntti Palosaari 10259ca2ce1SAntti Palosaari dev_dbg(&client->dev, "tone_mode=%d\n", fe_sec_tone_mode); 103de8e4203SAntti Palosaari 104de8e4203SAntti Palosaari switch (fe_sec_tone_mode) { 105de8e4203SAntti Palosaari case SEC_TONE_ON: 106de8e4203SAntti Palosaari tone = 1; 107de8e4203SAntti Palosaari break; 108de8e4203SAntti Palosaari case SEC_TONE_OFF: 109de8e4203SAntti Palosaari tone = 0; 110de8e4203SAntti Palosaari break; 111de8e4203SAntti Palosaari default: 11259ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid fe_sec_tone_mode\n"); 113de8e4203SAntti Palosaari ret = -EINVAL; 114de8e4203SAntti Palosaari goto error; 115de8e4203SAntti Palosaari } 116de8e4203SAntti Palosaari 11721c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_PCB_CONFIG; 11821c8ba39SAntti Palosaari cmd.args[1] = 0; 11921c8ba39SAntti Palosaari cmd.args[2] = 0x00; 12021c8ba39SAntti Palosaari cmd.args[3] = 0x00; 12121c8ba39SAntti Palosaari cmd.args[4] = tone; 12221c8ba39SAntti Palosaari cmd.len = 5; 123fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 124de8e4203SAntti Palosaari if (ret) 125de8e4203SAntti Palosaari goto error; 126de8e4203SAntti Palosaari 127de8e4203SAntti Palosaari return ret; 128de8e4203SAntti Palosaari error: 12959ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 130de8e4203SAntti Palosaari return ret; 131de8e4203SAntti Palosaari } 132de8e4203SAntti Palosaari 133de8e4203SAntti Palosaari static int tda10071_set_voltage(struct dvb_frontend *fe, 1340df289a2SMauro Carvalho Chehab enum fe_sec_voltage fe_sec_voltage) 135de8e4203SAntti Palosaari { 136fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 137fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 138de8e4203SAntti Palosaari struct tda10071_cmd cmd; 139de8e4203SAntti Palosaari int ret; 140de8e4203SAntti Palosaari u8 voltage; 141de8e4203SAntti Palosaari 142fca3e007SAntti Palosaari if (!dev->warm) { 143de8e4203SAntti Palosaari ret = -EFAULT; 144de8e4203SAntti Palosaari goto error; 145de8e4203SAntti Palosaari } 146de8e4203SAntti Palosaari 14759ca2ce1SAntti Palosaari dev_dbg(&client->dev, "voltage=%d\n", fe_sec_voltage); 148de8e4203SAntti Palosaari 149de8e4203SAntti Palosaari switch (fe_sec_voltage) { 150de8e4203SAntti Palosaari case SEC_VOLTAGE_13: 151de8e4203SAntti Palosaari voltage = 0; 152de8e4203SAntti Palosaari break; 153de8e4203SAntti Palosaari case SEC_VOLTAGE_18: 154de8e4203SAntti Palosaari voltage = 1; 155de8e4203SAntti Palosaari break; 156de8e4203SAntti Palosaari case SEC_VOLTAGE_OFF: 157de8e4203SAntti Palosaari voltage = 0; 158de8e4203SAntti Palosaari break; 159de8e4203SAntti Palosaari default: 16059ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid fe_sec_voltage\n"); 161de8e4203SAntti Palosaari ret = -EINVAL; 162de8e4203SAntti Palosaari goto error; 1638f5c997fSPeter Senna Tschudin } 164de8e4203SAntti Palosaari 16521c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_SET_DC_LEVEL; 16621c8ba39SAntti Palosaari cmd.args[1] = 0; 16721c8ba39SAntti Palosaari cmd.args[2] = voltage; 16821c8ba39SAntti Palosaari cmd.len = 3; 169fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 170de8e4203SAntti Palosaari if (ret) 171de8e4203SAntti Palosaari goto error; 172de8e4203SAntti Palosaari 173de8e4203SAntti Palosaari return ret; 174de8e4203SAntti Palosaari error: 17559ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 176de8e4203SAntti Palosaari return ret; 177de8e4203SAntti Palosaari } 178de8e4203SAntti Palosaari 179de8e4203SAntti Palosaari static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe, 180de8e4203SAntti Palosaari struct dvb_diseqc_master_cmd *diseqc_cmd) 181de8e4203SAntti Palosaari { 182fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 183fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 184de8e4203SAntti Palosaari struct tda10071_cmd cmd; 185de8e4203SAntti Palosaari int ret, i; 18654ab48edSAntti Palosaari unsigned int uitmp; 187de8e4203SAntti Palosaari 188fca3e007SAntti Palosaari if (!dev->warm) { 189de8e4203SAntti Palosaari ret = -EFAULT; 190de8e4203SAntti Palosaari goto error; 191de8e4203SAntti Palosaari } 192de8e4203SAntti Palosaari 19359ca2ce1SAntti Palosaari dev_dbg(&client->dev, "msg_len=%d\n", diseqc_cmd->msg_len); 194de8e4203SAntti Palosaari 19584431c2aSAntti Palosaari if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) { 196de8e4203SAntti Palosaari ret = -EINVAL; 197de8e4203SAntti Palosaari goto error; 198de8e4203SAntti Palosaari } 199de8e4203SAntti Palosaari 200de8e4203SAntti Palosaari /* wait LNB TX */ 20154ab48edSAntti Palosaari for (i = 500, uitmp = 0; i && !uitmp; i--) { 20254ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x47, &uitmp); 203de8e4203SAntti Palosaari if (ret) 204de8e4203SAntti Palosaari goto error; 20554ab48edSAntti Palosaari uitmp = (uitmp >> 0) & 1; 206d102b739SAntti Palosaari usleep_range(10000, 20000); 207de8e4203SAntti Palosaari } 208de8e4203SAntti Palosaari 20959ca2ce1SAntti Palosaari dev_dbg(&client->dev, "loop=%d\n", i); 210de8e4203SAntti Palosaari 211de8e4203SAntti Palosaari if (i == 0) { 212de8e4203SAntti Palosaari ret = -ETIMEDOUT; 213de8e4203SAntti Palosaari goto error; 214de8e4203SAntti Palosaari } 215de8e4203SAntti Palosaari 21654ab48edSAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00); 217de8e4203SAntti Palosaari if (ret) 218de8e4203SAntti Palosaari goto error; 219de8e4203SAntti Palosaari 22021c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_SEND_DISEQC; 22121c8ba39SAntti Palosaari cmd.args[1] = 0; 22221c8ba39SAntti Palosaari cmd.args[2] = 0; 22321c8ba39SAntti Palosaari cmd.args[3] = 0; 22421c8ba39SAntti Palosaari cmd.args[4] = 2; 22521c8ba39SAntti Palosaari cmd.args[5] = 0; 22621c8ba39SAntti Palosaari cmd.args[6] = diseqc_cmd->msg_len; 22721c8ba39SAntti Palosaari memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len); 22821c8ba39SAntti Palosaari cmd.len = 7 + diseqc_cmd->msg_len; 229fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 230de8e4203SAntti Palosaari if (ret) 231de8e4203SAntti Palosaari goto error; 232de8e4203SAntti Palosaari 233de8e4203SAntti Palosaari return ret; 234de8e4203SAntti Palosaari error: 23559ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 236de8e4203SAntti Palosaari return ret; 237de8e4203SAntti Palosaari } 238de8e4203SAntti Palosaari 239de8e4203SAntti Palosaari static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe, 240de8e4203SAntti Palosaari struct dvb_diseqc_slave_reply *reply) 241de8e4203SAntti Palosaari { 242fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 243fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 244de8e4203SAntti Palosaari struct tda10071_cmd cmd; 245de8e4203SAntti Palosaari int ret, i; 24654ab48edSAntti Palosaari unsigned int uitmp; 247de8e4203SAntti Palosaari 248fca3e007SAntti Palosaari if (!dev->warm) { 249de8e4203SAntti Palosaari ret = -EFAULT; 250de8e4203SAntti Palosaari goto error; 251de8e4203SAntti Palosaari } 252de8e4203SAntti Palosaari 25359ca2ce1SAntti Palosaari dev_dbg(&client->dev, "\n"); 254de8e4203SAntti Palosaari 255de8e4203SAntti Palosaari /* wait LNB RX */ 25654ab48edSAntti Palosaari for (i = 500, uitmp = 0; i && !uitmp; i--) { 25754ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x47, &uitmp); 258de8e4203SAntti Palosaari if (ret) 259de8e4203SAntti Palosaari goto error; 26054ab48edSAntti Palosaari uitmp = (uitmp >> 1) & 1; 261d102b739SAntti Palosaari usleep_range(10000, 20000); 262de8e4203SAntti Palosaari } 263de8e4203SAntti Palosaari 26459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "loop=%d\n", i); 265de8e4203SAntti Palosaari 266de8e4203SAntti Palosaari if (i == 0) { 267de8e4203SAntti Palosaari ret = -ETIMEDOUT; 268de8e4203SAntti Palosaari goto error; 269de8e4203SAntti Palosaari } 270de8e4203SAntti Palosaari 271de8e4203SAntti Palosaari /* reply len */ 27254ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x46, &uitmp); 273de8e4203SAntti Palosaari if (ret) 274de8e4203SAntti Palosaari goto error; 275de8e4203SAntti Palosaari 27654ab48edSAntti Palosaari reply->msg_len = uitmp & 0x1f; /* [4:0] */ 277de8e4203SAntti Palosaari if (reply->msg_len > sizeof(reply->msg)) 278de8e4203SAntti Palosaari reply->msg_len = sizeof(reply->msg); /* truncate API max */ 279de8e4203SAntti Palosaari 280de8e4203SAntti Palosaari /* read reply */ 28121c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_UPDATE_REPLY; 28221c8ba39SAntti Palosaari cmd.args[1] = 0; 28321c8ba39SAntti Palosaari cmd.len = 2; 284fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 285de8e4203SAntti Palosaari if (ret) 286de8e4203SAntti Palosaari goto error; 287de8e4203SAntti Palosaari 28854ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, cmd.len, reply->msg, 28954ab48edSAntti Palosaari reply->msg_len); 290de8e4203SAntti Palosaari if (ret) 291de8e4203SAntti Palosaari goto error; 292de8e4203SAntti Palosaari 293de8e4203SAntti Palosaari return ret; 294de8e4203SAntti Palosaari error: 29559ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 296de8e4203SAntti Palosaari return ret; 297de8e4203SAntti Palosaari } 298de8e4203SAntti Palosaari 299de8e4203SAntti Palosaari static int tda10071_diseqc_send_burst(struct dvb_frontend *fe, 3000df289a2SMauro Carvalho Chehab enum fe_sec_mini_cmd fe_sec_mini_cmd) 301de8e4203SAntti Palosaari { 302fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 303fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 304de8e4203SAntti Palosaari struct tda10071_cmd cmd; 305de8e4203SAntti Palosaari int ret, i; 30654ab48edSAntti Palosaari unsigned int uitmp; 30754ab48edSAntti Palosaari u8 burst; 308de8e4203SAntti Palosaari 309fca3e007SAntti Palosaari if (!dev->warm) { 310de8e4203SAntti Palosaari ret = -EFAULT; 311de8e4203SAntti Palosaari goto error; 312de8e4203SAntti Palosaari } 313de8e4203SAntti Palosaari 31459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "fe_sec_mini_cmd=%d\n", fe_sec_mini_cmd); 315de8e4203SAntti Palosaari 316de8e4203SAntti Palosaari switch (fe_sec_mini_cmd) { 317de8e4203SAntti Palosaari case SEC_MINI_A: 318de8e4203SAntti Palosaari burst = 0; 319de8e4203SAntti Palosaari break; 320de8e4203SAntti Palosaari case SEC_MINI_B: 321de8e4203SAntti Palosaari burst = 1; 322de8e4203SAntti Palosaari break; 323de8e4203SAntti Palosaari default: 32459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid fe_sec_mini_cmd\n"); 325de8e4203SAntti Palosaari ret = -EINVAL; 326de8e4203SAntti Palosaari goto error; 327de8e4203SAntti Palosaari } 328de8e4203SAntti Palosaari 329de8e4203SAntti Palosaari /* wait LNB TX */ 33054ab48edSAntti Palosaari for (i = 500, uitmp = 0; i && !uitmp; i--) { 33154ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x47, &uitmp); 332de8e4203SAntti Palosaari if (ret) 333de8e4203SAntti Palosaari goto error; 33454ab48edSAntti Palosaari uitmp = (uitmp >> 0) & 1; 335d102b739SAntti Palosaari usleep_range(10000, 20000); 336de8e4203SAntti Palosaari } 337de8e4203SAntti Palosaari 33859ca2ce1SAntti Palosaari dev_dbg(&client->dev, "loop=%d\n", i); 339de8e4203SAntti Palosaari 340de8e4203SAntti Palosaari if (i == 0) { 341de8e4203SAntti Palosaari ret = -ETIMEDOUT; 342de8e4203SAntti Palosaari goto error; 343de8e4203SAntti Palosaari } 344de8e4203SAntti Palosaari 34554ab48edSAntti Palosaari ret = regmap_update_bits(dev->regmap, 0x47, 0x01, 0x00); 346de8e4203SAntti Palosaari if (ret) 347de8e4203SAntti Palosaari goto error; 348de8e4203SAntti Palosaari 34921c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_SEND_TONEBURST; 35021c8ba39SAntti Palosaari cmd.args[1] = 0; 35121c8ba39SAntti Palosaari cmd.args[2] = burst; 35221c8ba39SAntti Palosaari cmd.len = 3; 353fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 354de8e4203SAntti Palosaari if (ret) 355de8e4203SAntti Palosaari goto error; 356de8e4203SAntti Palosaari 357de8e4203SAntti Palosaari return ret; 358de8e4203SAntti Palosaari error: 35959ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 360de8e4203SAntti Palosaari return ret; 361de8e4203SAntti Palosaari } 362de8e4203SAntti Palosaari 3630df289a2SMauro Carvalho Chehab static int tda10071_read_status(struct dvb_frontend *fe, enum fe_status *status) 364de8e4203SAntti Palosaari { 365fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 366fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 367267897a4SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 368267897a4SAntti Palosaari struct tda10071_cmd cmd; 369de8e4203SAntti Palosaari int ret; 37054ab48edSAntti Palosaari unsigned int uitmp; 371267897a4SAntti Palosaari u8 buf[8]; 372de8e4203SAntti Palosaari 373de8e4203SAntti Palosaari *status = 0; 374de8e4203SAntti Palosaari 375fca3e007SAntti Palosaari if (!dev->warm) { 376de8e4203SAntti Palosaari ret = 0; 377de8e4203SAntti Palosaari goto error; 378de8e4203SAntti Palosaari } 379de8e4203SAntti Palosaari 38054ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x39, &uitmp); 381de8e4203SAntti Palosaari if (ret) 382de8e4203SAntti Palosaari goto error; 383de8e4203SAntti Palosaari 38407115606SAntti Palosaari /* 0x39[0] tuner PLL */ 38554ab48edSAntti Palosaari if (uitmp & 0x02) /* demod PLL */ 38607115606SAntti Palosaari *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; 38754ab48edSAntti Palosaari if (uitmp & 0x04) /* viterbi or LDPC*/ 388de8e4203SAntti Palosaari *status |= FE_HAS_VITERBI; 38954ab48edSAntti Palosaari if (uitmp & 0x08) /* RS or BCH */ 390de8e4203SAntti Palosaari *status |= FE_HAS_SYNC | FE_HAS_LOCK; 391de8e4203SAntti Palosaari 392fca3e007SAntti Palosaari dev->fe_status = *status; 393de8e4203SAntti Palosaari 394267897a4SAntti Palosaari /* signal strength */ 395267897a4SAntti Palosaari if (dev->fe_status & FE_HAS_SIGNAL) { 39621c8ba39SAntti Palosaari cmd.args[0] = CMD_GET_AGCACC; 39721c8ba39SAntti Palosaari cmd.args[1] = 0; 39821c8ba39SAntti Palosaari cmd.len = 2; 399fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 400de8e4203SAntti Palosaari if (ret) 401de8e4203SAntti Palosaari goto error; 402de8e4203SAntti Palosaari 403de8e4203SAntti Palosaari /* input power estimate dBm */ 40454ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x50, &uitmp); 405de8e4203SAntti Palosaari if (ret) 406de8e4203SAntti Palosaari goto error; 407de8e4203SAntti Palosaari 408267897a4SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_DECIBEL; 409267897a4SAntti Palosaari c->strength.stat[0].svalue = (int) (uitmp - 256) * 1000; 410267897a4SAntti Palosaari } else { 411267897a4SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 412de8e4203SAntti Palosaari } 413de8e4203SAntti Palosaari 414267897a4SAntti Palosaari /* CNR */ 415267897a4SAntti Palosaari if (dev->fe_status & FE_HAS_VITERBI) { 416267897a4SAntti Palosaari /* Es/No */ 417267897a4SAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x3a, buf, 2); 418267897a4SAntti Palosaari if (ret) 419de8e4203SAntti Palosaari goto error; 420267897a4SAntti Palosaari 421267897a4SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 422267897a4SAntti Palosaari c->cnr.stat[0].svalue = (buf[0] << 8 | buf[1] << 0) * 100; 423267897a4SAntti Palosaari } else { 424267897a4SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 425de8e4203SAntti Palosaari } 426de8e4203SAntti Palosaari 427267897a4SAntti Palosaari /* UCB/PER/BER */ 428267897a4SAntti Palosaari if (dev->fe_status & FE_HAS_LOCK) { 429267897a4SAntti Palosaari /* TODO: report total bits/packets */ 430267897a4SAntti Palosaari u8 delivery_system, reg, len; 431267897a4SAntti Palosaari 432fca3e007SAntti Palosaari switch (dev->delivery_system) { 433de8e4203SAntti Palosaari case SYS_DVBS: 434de8e4203SAntti Palosaari reg = 0x4c; 435de8e4203SAntti Palosaari len = 8; 436267897a4SAntti Palosaari delivery_system = 1; 437de8e4203SAntti Palosaari break; 438de8e4203SAntti Palosaari case SYS_DVBS2: 439de8e4203SAntti Palosaari reg = 0x4d; 440de8e4203SAntti Palosaari len = 4; 441267897a4SAntti Palosaari delivery_system = 0; 442de8e4203SAntti Palosaari break; 443de8e4203SAntti Palosaari default: 444267897a4SAntti Palosaari ret = -EINVAL; 445267897a4SAntti Palosaari goto error; 446de8e4203SAntti Palosaari } 447de8e4203SAntti Palosaari 44854ab48edSAntti Palosaari ret = regmap_read(dev->regmap, reg, &uitmp); 449de8e4203SAntti Palosaari if (ret) 450de8e4203SAntti Palosaari goto error; 451de8e4203SAntti Palosaari 452267897a4SAntti Palosaari if (dev->meas_count == uitmp) { 45354ab48edSAntti Palosaari dev_dbg(&client->dev, "meas not ready=%02x\n", uitmp); 454267897a4SAntti Palosaari ret = 0; 455267897a4SAntti Palosaari goto error; 456de8e4203SAntti Palosaari } else { 457267897a4SAntti Palosaari dev->meas_count = uitmp; 458de8e4203SAntti Palosaari } 459de8e4203SAntti Palosaari 46021c8ba39SAntti Palosaari cmd.args[0] = CMD_BER_UPDATE_COUNTERS; 46121c8ba39SAntti Palosaari cmd.args[1] = 0; 462267897a4SAntti Palosaari cmd.args[2] = delivery_system; 46321c8ba39SAntti Palosaari cmd.len = 3; 464fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 465de8e4203SAntti Palosaari if (ret) 466de8e4203SAntti Palosaari goto error; 467de8e4203SAntti Palosaari 46854ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, cmd.len, buf, len); 469de8e4203SAntti Palosaari if (ret) 470de8e4203SAntti Palosaari goto error; 471de8e4203SAntti Palosaari 472fca3e007SAntti Palosaari if (dev->delivery_system == SYS_DVBS) { 473*a7463e2dSColin Ian King u32 bit_error = buf[0] << 24 | buf[1] << 16 | 474267897a4SAntti Palosaari buf[2] << 8 | buf[3] << 0; 475*a7463e2dSColin Ian King 476*a7463e2dSColin Ian King dev->dvbv3_ber = bit_error; 477*a7463e2dSColin Ian King dev->post_bit_error += bit_error; 478267897a4SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 479267897a4SAntti Palosaari c->post_bit_error.stat[0].uvalue = dev->post_bit_error; 480267897a4SAntti Palosaari dev->block_error += buf[4] << 8 | buf[5] << 0; 481267897a4SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_COUNTER; 482267897a4SAntti Palosaari c->block_error.stat[0].uvalue = dev->block_error; 483de8e4203SAntti Palosaari } else { 484267897a4SAntti Palosaari dev->dvbv3_ber = buf[0] << 8 | buf[1] << 0; 485267897a4SAntti Palosaari dev->post_bit_error += buf[0] << 8 | buf[1] << 0; 486267897a4SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 487267897a4SAntti Palosaari c->post_bit_error.stat[0].uvalue = dev->post_bit_error; 488267897a4SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 489de8e4203SAntti Palosaari } 490267897a4SAntti Palosaari } else { 491267897a4SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 492267897a4SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 493267897a4SAntti Palosaari } 494de8e4203SAntti Palosaari 495de8e4203SAntti Palosaari return ret; 496de8e4203SAntti Palosaari error: 49759ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 498de8e4203SAntti Palosaari return ret; 499de8e4203SAntti Palosaari } 500de8e4203SAntti Palosaari 501267897a4SAntti Palosaari static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr) 502267897a4SAntti Palosaari { 503267897a4SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 504267897a4SAntti Palosaari 505267897a4SAntti Palosaari if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) 506267897a4SAntti Palosaari *snr = div_s64(c->cnr.stat[0].svalue, 100); 507267897a4SAntti Palosaari else 508267897a4SAntti Palosaari *snr = 0; 509267897a4SAntti Palosaari return 0; 510267897a4SAntti Palosaari } 511267897a4SAntti Palosaari 512267897a4SAntti Palosaari static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 513267897a4SAntti Palosaari { 514267897a4SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 515267897a4SAntti Palosaari unsigned int uitmp; 516267897a4SAntti Palosaari 517267897a4SAntti Palosaari if (c->strength.stat[0].scale == FE_SCALE_DECIBEL) { 5187d0ddc91SMauro Carvalho Chehab uitmp = div_s64(c->strength.stat[0].svalue, 1000) + 256; 519267897a4SAntti Palosaari uitmp = clamp(uitmp, 181U, 236U); /* -75dBm - -20dBm */ 520267897a4SAntti Palosaari /* scale value to 0x0000-0xffff */ 521267897a4SAntti Palosaari *strength = (uitmp-181) * 0xffff / (236-181); 522267897a4SAntti Palosaari } else { 523267897a4SAntti Palosaari *strength = 0; 524267897a4SAntti Palosaari } 525267897a4SAntti Palosaari return 0; 526267897a4SAntti Palosaari } 527267897a4SAntti Palosaari 528267897a4SAntti Palosaari static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber) 529267897a4SAntti Palosaari { 530267897a4SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 531267897a4SAntti Palosaari 532267897a4SAntti Palosaari *ber = dev->dvbv3_ber; 533267897a4SAntti Palosaari return 0; 534267897a4SAntti Palosaari } 535267897a4SAntti Palosaari 536de8e4203SAntti Palosaari static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 537de8e4203SAntti Palosaari { 538267897a4SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 539de8e4203SAntti Palosaari 540267897a4SAntti Palosaari if (c->block_error.stat[0].scale == FE_SCALE_COUNTER) 541267897a4SAntti Palosaari *ucblocks = c->block_error.stat[0].uvalue; 542267897a4SAntti Palosaari else 543de8e4203SAntti Palosaari *ucblocks = 0; 544267897a4SAntti Palosaari return 0; 545de8e4203SAntti Palosaari } 546de8e4203SAntti Palosaari 547b2a29b57SMauro Carvalho Chehab static int tda10071_set_frontend(struct dvb_frontend *fe) 548de8e4203SAntti Palosaari { 549fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 550fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 551de8e4203SAntti Palosaari struct tda10071_cmd cmd; 552de8e4203SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 553de8e4203SAntti Palosaari int ret, i; 554de8e4203SAntti Palosaari u8 mode, rolloff, pilot, inversion, div; 5550df289a2SMauro Carvalho Chehab enum fe_modulation modulation; 556de8e4203SAntti Palosaari 55759ca2ce1SAntti Palosaari dev_dbg(&client->dev, 55859ca2ce1SAntti Palosaari "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", 55959ca2ce1SAntti Palosaari c->delivery_system, c->modulation, c->frequency, c->symbol_rate, 56059ca2ce1SAntti Palosaari c->inversion, c->pilot, c->rolloff); 561de8e4203SAntti Palosaari 562fca3e007SAntti Palosaari dev->delivery_system = SYS_UNDEFINED; 563de8e4203SAntti Palosaari 564fca3e007SAntti Palosaari if (!dev->warm) { 565de8e4203SAntti Palosaari ret = -EFAULT; 566de8e4203SAntti Palosaari goto error; 567de8e4203SAntti Palosaari } 568de8e4203SAntti Palosaari 569de8e4203SAntti Palosaari switch (c->inversion) { 570de8e4203SAntti Palosaari case INVERSION_OFF: 571de8e4203SAntti Palosaari inversion = 1; 572de8e4203SAntti Palosaari break; 573de8e4203SAntti Palosaari case INVERSION_ON: 574de8e4203SAntti Palosaari inversion = 0; 575de8e4203SAntti Palosaari break; 576de8e4203SAntti Palosaari case INVERSION_AUTO: 577de8e4203SAntti Palosaari /* 2 = auto; try first on then off 578de8e4203SAntti Palosaari * 3 = auto; try first off then on */ 579de8e4203SAntti Palosaari inversion = 3; 580de8e4203SAntti Palosaari break; 581de8e4203SAntti Palosaari default: 58259ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid inversion\n"); 583de8e4203SAntti Palosaari ret = -EINVAL; 584de8e4203SAntti Palosaari goto error; 585de8e4203SAntti Palosaari } 586de8e4203SAntti Palosaari 587de8e4203SAntti Palosaari switch (c->delivery_system) { 588de8e4203SAntti Palosaari case SYS_DVBS: 589db4175aeSAntti Palosaari modulation = QPSK; 590de8e4203SAntti Palosaari rolloff = 0; 591de8e4203SAntti Palosaari pilot = 2; 592de8e4203SAntti Palosaari break; 593de8e4203SAntti Palosaari case SYS_DVBS2: 594db4175aeSAntti Palosaari modulation = c->modulation; 595db4175aeSAntti Palosaari 596de8e4203SAntti Palosaari switch (c->rolloff) { 597de8e4203SAntti Palosaari case ROLLOFF_20: 598de8e4203SAntti Palosaari rolloff = 2; 599de8e4203SAntti Palosaari break; 600de8e4203SAntti Palosaari case ROLLOFF_25: 601de8e4203SAntti Palosaari rolloff = 1; 602de8e4203SAntti Palosaari break; 603de8e4203SAntti Palosaari case ROLLOFF_35: 604de8e4203SAntti Palosaari rolloff = 0; 605de8e4203SAntti Palosaari break; 606de8e4203SAntti Palosaari case ROLLOFF_AUTO: 607de8e4203SAntti Palosaari default: 60859ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid rolloff\n"); 609de8e4203SAntti Palosaari ret = -EINVAL; 610de8e4203SAntti Palosaari goto error; 611de8e4203SAntti Palosaari } 612de8e4203SAntti Palosaari 613de8e4203SAntti Palosaari switch (c->pilot) { 614de8e4203SAntti Palosaari case PILOT_OFF: 615de8e4203SAntti Palosaari pilot = 0; 616de8e4203SAntti Palosaari break; 617de8e4203SAntti Palosaari case PILOT_ON: 618de8e4203SAntti Palosaari pilot = 1; 619de8e4203SAntti Palosaari break; 620de8e4203SAntti Palosaari case PILOT_AUTO: 621de8e4203SAntti Palosaari pilot = 2; 622de8e4203SAntti Palosaari break; 623de8e4203SAntti Palosaari default: 62459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid pilot\n"); 625de8e4203SAntti Palosaari ret = -EINVAL; 626de8e4203SAntti Palosaari goto error; 627de8e4203SAntti Palosaari } 628de8e4203SAntti Palosaari break; 629de8e4203SAntti Palosaari default: 63059ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid delivery_system\n"); 631de8e4203SAntti Palosaari ret = -EINVAL; 632de8e4203SAntti Palosaari goto error; 633de8e4203SAntti Palosaari } 634de8e4203SAntti Palosaari 635de8e4203SAntti Palosaari for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) { 636de8e4203SAntti Palosaari if (c->delivery_system == TDA10071_MODCOD[i].delivery_system && 637db4175aeSAntti Palosaari modulation == TDA10071_MODCOD[i].modulation && 638de8e4203SAntti Palosaari c->fec_inner == TDA10071_MODCOD[i].fec) { 639de8e4203SAntti Palosaari mode = TDA10071_MODCOD[i].val; 64059ca2ce1SAntti Palosaari dev_dbg(&client->dev, "mode found=%02x\n", mode); 641de8e4203SAntti Palosaari break; 642de8e4203SAntti Palosaari } 643de8e4203SAntti Palosaari } 644de8e4203SAntti Palosaari 645de8e4203SAntti Palosaari if (mode == 0xff) { 64659ca2ce1SAntti Palosaari dev_dbg(&client->dev, "invalid parameter combination\n"); 647de8e4203SAntti Palosaari ret = -EINVAL; 648de8e4203SAntti Palosaari goto error; 649de8e4203SAntti Palosaari } 650de8e4203SAntti Palosaari 651de8e4203SAntti Palosaari if (c->symbol_rate <= 5000000) 652de8e4203SAntti Palosaari div = 14; 653de8e4203SAntti Palosaari else 654de8e4203SAntti Palosaari div = 4; 655de8e4203SAntti Palosaari 65654ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0x81, div); 657de8e4203SAntti Palosaari if (ret) 658de8e4203SAntti Palosaari goto error; 659de8e4203SAntti Palosaari 66054ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xe3, div); 661de8e4203SAntti Palosaari if (ret) 662de8e4203SAntti Palosaari goto error; 663de8e4203SAntti Palosaari 66421c8ba39SAntti Palosaari cmd.args[0] = CMD_CHANGE_CHANNEL; 66521c8ba39SAntti Palosaari cmd.args[1] = 0; 66621c8ba39SAntti Palosaari cmd.args[2] = mode; 66721c8ba39SAntti Palosaari cmd.args[3] = (c->frequency >> 16) & 0xff; 66821c8ba39SAntti Palosaari cmd.args[4] = (c->frequency >> 8) & 0xff; 66921c8ba39SAntti Palosaari cmd.args[5] = (c->frequency >> 0) & 0xff; 67021c8ba39SAntti Palosaari cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff; 67121c8ba39SAntti Palosaari cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff; 672f1b1eabfSMauro Carvalho Chehab cmd.args[8] = ((tda10071_ops.info.frequency_tolerance_hz / 1000) >> 8) & 0xff; 673f1b1eabfSMauro Carvalho Chehab cmd.args[9] = ((tda10071_ops.info.frequency_tolerance_hz / 1000) >> 0) & 0xff; 67421c8ba39SAntti Palosaari cmd.args[10] = rolloff; 67521c8ba39SAntti Palosaari cmd.args[11] = inversion; 67621c8ba39SAntti Palosaari cmd.args[12] = pilot; 67721c8ba39SAntti Palosaari cmd.args[13] = 0x00; 67821c8ba39SAntti Palosaari cmd.args[14] = 0x00; 67921c8ba39SAntti Palosaari cmd.len = 15; 680fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 681de8e4203SAntti Palosaari if (ret) 682de8e4203SAntti Palosaari goto error; 683de8e4203SAntti Palosaari 684fca3e007SAntti Palosaari dev->delivery_system = c->delivery_system; 685de8e4203SAntti Palosaari 686de8e4203SAntti Palosaari return ret; 687de8e4203SAntti Palosaari error: 68859ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 689de8e4203SAntti Palosaari return ret; 690de8e4203SAntti Palosaari } 691de8e4203SAntti Palosaari 6927e3e68bcSMauro Carvalho Chehab static int tda10071_get_frontend(struct dvb_frontend *fe, 6937e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *c) 694de8e4203SAntti Palosaari { 695fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 696fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 697de8e4203SAntti Palosaari int ret, i; 698de8e4203SAntti Palosaari u8 buf[5], tmp; 699de8e4203SAntti Palosaari 700fca3e007SAntti Palosaari if (!dev->warm || !(dev->fe_status & FE_HAS_LOCK)) { 7014c4acb7aSAntti Palosaari ret = 0; 702de8e4203SAntti Palosaari goto error; 703de8e4203SAntti Palosaari } 704de8e4203SAntti Palosaari 70554ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x30, buf, 5); 706de8e4203SAntti Palosaari if (ret) 707de8e4203SAntti Palosaari goto error; 708de8e4203SAntti Palosaari 709de8e4203SAntti Palosaari tmp = buf[0] & 0x3f; 710de8e4203SAntti Palosaari for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) { 711de8e4203SAntti Palosaari if (tmp == TDA10071_MODCOD[i].val) { 712de8e4203SAntti Palosaari c->modulation = TDA10071_MODCOD[i].modulation; 713de8e4203SAntti Palosaari c->fec_inner = TDA10071_MODCOD[i].fec; 714de8e4203SAntti Palosaari c->delivery_system = TDA10071_MODCOD[i].delivery_system; 715de8e4203SAntti Palosaari } 716de8e4203SAntti Palosaari } 717de8e4203SAntti Palosaari 718de8e4203SAntti Palosaari switch ((buf[1] >> 0) & 0x01) { 719de8e4203SAntti Palosaari case 0: 720b32725e8SAntti Palosaari c->inversion = INVERSION_ON; 721de8e4203SAntti Palosaari break; 722de8e4203SAntti Palosaari case 1: 723b32725e8SAntti Palosaari c->inversion = INVERSION_OFF; 724de8e4203SAntti Palosaari break; 725de8e4203SAntti Palosaari } 726de8e4203SAntti Palosaari 727de8e4203SAntti Palosaari switch ((buf[1] >> 7) & 0x01) { 728de8e4203SAntti Palosaari case 0: 729de8e4203SAntti Palosaari c->pilot = PILOT_OFF; 730de8e4203SAntti Palosaari break; 731de8e4203SAntti Palosaari case 1: 732de8e4203SAntti Palosaari c->pilot = PILOT_ON; 733de8e4203SAntti Palosaari break; 734de8e4203SAntti Palosaari } 735de8e4203SAntti Palosaari 736de8e4203SAntti Palosaari c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0); 737de8e4203SAntti Palosaari 73854ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x52, buf, 3); 739de8e4203SAntti Palosaari if (ret) 740de8e4203SAntti Palosaari goto error; 741de8e4203SAntti Palosaari 742c2c1a6e5SAntti Palosaari c->symbol_rate = ((buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0)) * 1000; 743de8e4203SAntti Palosaari 744de8e4203SAntti Palosaari return ret; 745de8e4203SAntti Palosaari error: 74659ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 747de8e4203SAntti Palosaari return ret; 748de8e4203SAntti Palosaari } 749de8e4203SAntti Palosaari 750de8e4203SAntti Palosaari static int tda10071_init(struct dvb_frontend *fe) 751de8e4203SAntti Palosaari { 752fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 753fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 754267897a4SAntti Palosaari struct dtv_frontend_properties *c = &fe->dtv_property_cache; 755de8e4203SAntti Palosaari struct tda10071_cmd cmd; 75675d404ecSAntti Palosaari int ret, i, len, remaining, fw_size; 75754ab48edSAntti Palosaari unsigned int uitmp; 758de8e4203SAntti Palosaari const struct firmware *fw; 75903f4efc3SAntti Palosaari u8 *fw_file = TDA10071_FIRMWARE; 760de8e4203SAntti Palosaari u8 tmp, buf[4]; 761de8e4203SAntti Palosaari struct tda10071_reg_val_mask tab[] = { 762de8e4203SAntti Palosaari { 0xcd, 0x00, 0x07 }, 763de8e4203SAntti Palosaari { 0x80, 0x00, 0x02 }, 764de8e4203SAntti Palosaari { 0xcd, 0x00, 0xc0 }, 765de8e4203SAntti Palosaari { 0xce, 0x00, 0x1b }, 766de8e4203SAntti Palosaari { 0x9d, 0x00, 0x01 }, 767de8e4203SAntti Palosaari { 0x9d, 0x00, 0x02 }, 768de8e4203SAntti Palosaari { 0x9e, 0x00, 0x01 }, 769de8e4203SAntti Palosaari { 0x87, 0x00, 0x80 }, 770de8e4203SAntti Palosaari { 0xce, 0x00, 0x08 }, 771de8e4203SAntti Palosaari { 0xce, 0x00, 0x10 }, 772de8e4203SAntti Palosaari }; 773de8e4203SAntti Palosaari struct tda10071_reg_val_mask tab2[] = { 774de8e4203SAntti Palosaari { 0xf1, 0x70, 0xff }, 775fca3e007SAntti Palosaari { 0x88, dev->pll_multiplier, 0x3f }, 776de8e4203SAntti Palosaari { 0x89, 0x00, 0x10 }, 777de8e4203SAntti Palosaari { 0x89, 0x10, 0x10 }, 778de8e4203SAntti Palosaari { 0xc0, 0x01, 0x01 }, 779de8e4203SAntti Palosaari { 0xc0, 0x00, 0x01 }, 780de8e4203SAntti Palosaari { 0xe0, 0xff, 0xff }, 781de8e4203SAntti Palosaari { 0xe0, 0x00, 0xff }, 782de8e4203SAntti Palosaari { 0x96, 0x1e, 0x7e }, 783de8e4203SAntti Palosaari { 0x8b, 0x08, 0x08 }, 784de8e4203SAntti Palosaari { 0x8b, 0x00, 0x08 }, 785de8e4203SAntti Palosaari { 0x8f, 0x1a, 0x7e }, 786de8e4203SAntti Palosaari { 0x8c, 0x68, 0xff }, 787de8e4203SAntti Palosaari { 0x8d, 0x08, 0xff }, 788de8e4203SAntti Palosaari { 0x8e, 0x4c, 0xff }, 789de8e4203SAntti Palosaari { 0x8f, 0x01, 0x01 }, 790de8e4203SAntti Palosaari { 0x8b, 0x04, 0x04 }, 791de8e4203SAntti Palosaari { 0x8b, 0x00, 0x04 }, 792de8e4203SAntti Palosaari { 0x87, 0x05, 0x07 }, 793de8e4203SAntti Palosaari { 0x80, 0x00, 0x20 }, 794de8e4203SAntti Palosaari { 0xc8, 0x01, 0xff }, 795de8e4203SAntti Palosaari { 0xb4, 0x47, 0xff }, 796de8e4203SAntti Palosaari { 0xb5, 0x9c, 0xff }, 797de8e4203SAntti Palosaari { 0xb6, 0x7d, 0xff }, 798de8e4203SAntti Palosaari { 0xba, 0x00, 0x03 }, 799de8e4203SAntti Palosaari { 0xb7, 0x47, 0xff }, 800de8e4203SAntti Palosaari { 0xb8, 0x9c, 0xff }, 801de8e4203SAntti Palosaari { 0xb9, 0x7d, 0xff }, 802de8e4203SAntti Palosaari { 0xba, 0x00, 0x0c }, 803de8e4203SAntti Palosaari { 0xc8, 0x00, 0xff }, 804de8e4203SAntti Palosaari { 0xcd, 0x00, 0x04 }, 805de8e4203SAntti Palosaari { 0xcd, 0x00, 0x20 }, 806de8e4203SAntti Palosaari { 0xe8, 0x02, 0xff }, 807de8e4203SAntti Palosaari { 0xcf, 0x20, 0xff }, 808de8e4203SAntti Palosaari { 0x9b, 0xd7, 0xff }, 809de8e4203SAntti Palosaari { 0x9a, 0x01, 0x03 }, 810de8e4203SAntti Palosaari { 0xa8, 0x05, 0x0f }, 811de8e4203SAntti Palosaari { 0xa8, 0x65, 0xf0 }, 812de8e4203SAntti Palosaari { 0xa6, 0xa0, 0xf0 }, 813de8e4203SAntti Palosaari { 0x9d, 0x50, 0xfc }, 814de8e4203SAntti Palosaari { 0x9e, 0x20, 0xe0 }, 815de8e4203SAntti Palosaari { 0xa3, 0x1c, 0x7c }, 816de8e4203SAntti Palosaari { 0xd5, 0x03, 0x03 }, 817de8e4203SAntti Palosaari }; 818de8e4203SAntti Palosaari 819fca3e007SAntti Palosaari if (dev->warm) { 820de8e4203SAntti Palosaari /* warm state - wake up device from sleep */ 821de8e4203SAntti Palosaari 822de8e4203SAntti Palosaari for (i = 0; i < ARRAY_SIZE(tab); i++) { 823fca3e007SAntti Palosaari ret = tda10071_wr_reg_mask(dev, tab[i].reg, 824de8e4203SAntti Palosaari tab[i].val, tab[i].mask); 825de8e4203SAntti Palosaari if (ret) 826de8e4203SAntti Palosaari goto error; 827de8e4203SAntti Palosaari } 828de8e4203SAntti Palosaari 82921c8ba39SAntti Palosaari cmd.args[0] = CMD_SET_SLEEP_MODE; 83021c8ba39SAntti Palosaari cmd.args[1] = 0; 83121c8ba39SAntti Palosaari cmd.args[2] = 0; 83221c8ba39SAntti Palosaari cmd.len = 3; 833fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 834de8e4203SAntti Palosaari if (ret) 835de8e4203SAntti Palosaari goto error; 836de8e4203SAntti Palosaari } else { 837de8e4203SAntti Palosaari /* cold state - try to download firmware */ 838de8e4203SAntti Palosaari 839de8e4203SAntti Palosaari /* request the firmware, this will block and timeout */ 84059ca2ce1SAntti Palosaari ret = request_firmware(&fw, fw_file, &client->dev); 841de8e4203SAntti Palosaari if (ret) { 84259ca2ce1SAntti Palosaari dev_err(&client->dev, 843fe63a1a6SMauro Carvalho Chehab "did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware\n", 84459ca2ce1SAntti Palosaari fw_file, ret); 845de8e4203SAntti Palosaari goto error; 846de8e4203SAntti Palosaari } 847de8e4203SAntti Palosaari 848de8e4203SAntti Palosaari /* init */ 849de8e4203SAntti Palosaari for (i = 0; i < ARRAY_SIZE(tab2); i++) { 850fca3e007SAntti Palosaari ret = tda10071_wr_reg_mask(dev, tab2[i].reg, 851de8e4203SAntti Palosaari tab2[i].val, tab2[i].mask); 852de8e4203SAntti Palosaari if (ret) 853de8e4203SAntti Palosaari goto error_release_firmware; 854de8e4203SAntti Palosaari } 855de8e4203SAntti Palosaari 856de8e4203SAntti Palosaari /* download firmware */ 85754ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xe0, 0x7f); 858de8e4203SAntti Palosaari if (ret) 859de8e4203SAntti Palosaari goto error_release_firmware; 860de8e4203SAntti Palosaari 86154ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xf7, 0x81); 862de8e4203SAntti Palosaari if (ret) 863de8e4203SAntti Palosaari goto error_release_firmware; 864de8e4203SAntti Palosaari 86554ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xf8, 0x00); 866de8e4203SAntti Palosaari if (ret) 867de8e4203SAntti Palosaari goto error_release_firmware; 868de8e4203SAntti Palosaari 86954ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xf9, 0x00); 870de8e4203SAntti Palosaari if (ret) 871de8e4203SAntti Palosaari goto error_release_firmware; 872de8e4203SAntti Palosaari 87359ca2ce1SAntti Palosaari dev_info(&client->dev, 87459ca2ce1SAntti Palosaari "found a '%s' in cold state, will try to load a firmware\n", 87559ca2ce1SAntti Palosaari tda10071_ops.info.name); 87659ca2ce1SAntti Palosaari dev_info(&client->dev, "downloading firmware from file '%s'\n", 87759ca2ce1SAntti Palosaari fw_file); 878de8e4203SAntti Palosaari 87975d404ecSAntti Palosaari /* do not download last byte */ 88075d404ecSAntti Palosaari fw_size = fw->size - 1; 88175d404ecSAntti Palosaari 88275d404ecSAntti Palosaari for (remaining = fw_size; remaining > 0; 883fca3e007SAntti Palosaari remaining -= (dev->i2c_wr_max - 1)) { 884de8e4203SAntti Palosaari len = remaining; 885fca3e007SAntti Palosaari if (len > (dev->i2c_wr_max - 1)) 886fca3e007SAntti Palosaari len = (dev->i2c_wr_max - 1); 887de8e4203SAntti Palosaari 88854ab48edSAntti Palosaari ret = regmap_bulk_write(dev->regmap, 0xfa, 88975d404ecSAntti Palosaari (u8 *) &fw->data[fw_size - remaining], len); 890de8e4203SAntti Palosaari if (ret) { 89159ca2ce1SAntti Palosaari dev_err(&client->dev, 89259ca2ce1SAntti Palosaari "firmware download failed=%d\n", ret); 893de8e4203SAntti Palosaari goto error_release_firmware; 894de8e4203SAntti Palosaari } 895de8e4203SAntti Palosaari } 896de8e4203SAntti Palosaari release_firmware(fw); 897de8e4203SAntti Palosaari 89854ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xf7, 0x0c); 899de8e4203SAntti Palosaari if (ret) 900de8e4203SAntti Palosaari goto error; 901de8e4203SAntti Palosaari 90254ab48edSAntti Palosaari ret = regmap_write(dev->regmap, 0xe0, 0x00); 903de8e4203SAntti Palosaari if (ret) 904de8e4203SAntti Palosaari goto error; 905de8e4203SAntti Palosaari 906de8e4203SAntti Palosaari /* wait firmware start */ 907de8e4203SAntti Palosaari msleep(250); 908de8e4203SAntti Palosaari 909de8e4203SAntti Palosaari /* firmware status */ 91054ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0x51, &uitmp); 911de8e4203SAntti Palosaari if (ret) 912de8e4203SAntti Palosaari goto error; 913de8e4203SAntti Palosaari 91454ab48edSAntti Palosaari if (uitmp) { 91559ca2ce1SAntti Palosaari dev_info(&client->dev, "firmware did not run\n"); 916de8e4203SAntti Palosaari ret = -EFAULT; 917de8e4203SAntti Palosaari goto error; 918de8e4203SAntti Palosaari } else { 919fca3e007SAntti Palosaari dev->warm = true; 920de8e4203SAntti Palosaari } 921de8e4203SAntti Palosaari 92221c8ba39SAntti Palosaari cmd.args[0] = CMD_GET_FW_VERSION; 92321c8ba39SAntti Palosaari cmd.len = 1; 924fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 925de8e4203SAntti Palosaari if (ret) 926de8e4203SAntti Palosaari goto error; 927de8e4203SAntti Palosaari 92854ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, cmd.len, buf, 4); 929de8e4203SAntti Palosaari if (ret) 930de8e4203SAntti Palosaari goto error; 931de8e4203SAntti Palosaari 93259ca2ce1SAntti Palosaari dev_info(&client->dev, "firmware version %d.%d.%d.%d\n", 93359ca2ce1SAntti Palosaari buf[0], buf[1], buf[2], buf[3]); 93459ca2ce1SAntti Palosaari dev_info(&client->dev, "found a '%s' in warm state\n", 93559ca2ce1SAntti Palosaari tda10071_ops.info.name); 936de8e4203SAntti Palosaari 93754ab48edSAntti Palosaari ret = regmap_bulk_read(dev->regmap, 0x81, buf, 2); 938de8e4203SAntti Palosaari if (ret) 939de8e4203SAntti Palosaari goto error; 940de8e4203SAntti Palosaari 94121c8ba39SAntti Palosaari cmd.args[0] = CMD_DEMOD_INIT; 942fca3e007SAntti Palosaari cmd.args[1] = ((dev->clk / 1000) >> 8) & 0xff; 943fca3e007SAntti Palosaari cmd.args[2] = ((dev->clk / 1000) >> 0) & 0xff; 94421c8ba39SAntti Palosaari cmd.args[3] = buf[0]; 94521c8ba39SAntti Palosaari cmd.args[4] = buf[1]; 946fca3e007SAntti Palosaari cmd.args[5] = dev->pll_multiplier; 947fca3e007SAntti Palosaari cmd.args[6] = dev->spec_inv; 94821c8ba39SAntti Palosaari cmd.args[7] = 0x00; 94921c8ba39SAntti Palosaari cmd.len = 8; 950fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 951de8e4203SAntti Palosaari if (ret) 952de8e4203SAntti Palosaari goto error; 953de8e4203SAntti Palosaari 954fca3e007SAntti Palosaari if (dev->tuner_i2c_addr) 955fca3e007SAntti Palosaari tmp = dev->tuner_i2c_addr; 956116802f1SAntti Palosaari else 957116802f1SAntti Palosaari tmp = 0x14; 958116802f1SAntti Palosaari 95921c8ba39SAntti Palosaari cmd.args[0] = CMD_TUNER_INIT; 96021c8ba39SAntti Palosaari cmd.args[1] = 0x00; 96121c8ba39SAntti Palosaari cmd.args[2] = 0x00; 96221c8ba39SAntti Palosaari cmd.args[3] = 0x00; 96321c8ba39SAntti Palosaari cmd.args[4] = 0x00; 964116802f1SAntti Palosaari cmd.args[5] = tmp; 96521c8ba39SAntti Palosaari cmd.args[6] = 0x00; 96621c8ba39SAntti Palosaari cmd.args[7] = 0x03; 96721c8ba39SAntti Palosaari cmd.args[8] = 0x02; 96821c8ba39SAntti Palosaari cmd.args[9] = 0x02; 96921c8ba39SAntti Palosaari cmd.args[10] = 0x00; 97021c8ba39SAntti Palosaari cmd.args[11] = 0x00; 97121c8ba39SAntti Palosaari cmd.args[12] = 0x00; 97221c8ba39SAntti Palosaari cmd.args[13] = 0x00; 97321c8ba39SAntti Palosaari cmd.args[14] = 0x00; 97421c8ba39SAntti Palosaari cmd.len = 15; 975fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 976de8e4203SAntti Palosaari if (ret) 977de8e4203SAntti Palosaari goto error; 978de8e4203SAntti Palosaari 97921c8ba39SAntti Palosaari cmd.args[0] = CMD_MPEG_CONFIG; 98021c8ba39SAntti Palosaari cmd.args[1] = 0; 981fca3e007SAntti Palosaari cmd.args[2] = dev->ts_mode; 98221c8ba39SAntti Palosaari cmd.args[3] = 0x00; 98321c8ba39SAntti Palosaari cmd.args[4] = 0x04; 98421c8ba39SAntti Palosaari cmd.args[5] = 0x00; 98521c8ba39SAntti Palosaari cmd.len = 6; 986fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 987de8e4203SAntti Palosaari if (ret) 988de8e4203SAntti Palosaari goto error; 989de8e4203SAntti Palosaari 99054ab48edSAntti Palosaari ret = regmap_update_bits(dev->regmap, 0xf0, 0x01, 0x01); 991de8e4203SAntti Palosaari if (ret) 992de8e4203SAntti Palosaari goto error; 993de8e4203SAntti Palosaari 99421c8ba39SAntti Palosaari cmd.args[0] = CMD_LNB_CONFIG; 99521c8ba39SAntti Palosaari cmd.args[1] = 0; 99621c8ba39SAntti Palosaari cmd.args[2] = 150; 99721c8ba39SAntti Palosaari cmd.args[3] = 3; 99821c8ba39SAntti Palosaari cmd.args[4] = 22; 99921c8ba39SAntti Palosaari cmd.args[5] = 1; 100021c8ba39SAntti Palosaari cmd.args[6] = 1; 100121c8ba39SAntti Palosaari cmd.args[7] = 30; 100221c8ba39SAntti Palosaari cmd.args[8] = 30; 100321c8ba39SAntti Palosaari cmd.args[9] = 30; 100421c8ba39SAntti Palosaari cmd.args[10] = 30; 100521c8ba39SAntti Palosaari cmd.len = 11; 1006fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 1007de8e4203SAntti Palosaari if (ret) 1008de8e4203SAntti Palosaari goto error; 1009de8e4203SAntti Palosaari 101021c8ba39SAntti Palosaari cmd.args[0] = CMD_BER_CONTROL; 101121c8ba39SAntti Palosaari cmd.args[1] = 0; 101221c8ba39SAntti Palosaari cmd.args[2] = 14; 101321c8ba39SAntti Palosaari cmd.args[3] = 14; 101421c8ba39SAntti Palosaari cmd.len = 4; 1015fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 1016de8e4203SAntti Palosaari if (ret) 1017de8e4203SAntti Palosaari goto error; 1018de8e4203SAntti Palosaari } 1019de8e4203SAntti Palosaari 1020267897a4SAntti Palosaari /* init stats here in order signal app which stats are supported */ 1021267897a4SAntti Palosaari c->strength.len = 1; 1022267897a4SAntti Palosaari c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1023267897a4SAntti Palosaari c->cnr.len = 1; 1024267897a4SAntti Palosaari c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1025267897a4SAntti Palosaari c->post_bit_error.len = 1; 1026267897a4SAntti Palosaari c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1027267897a4SAntti Palosaari c->block_error.len = 1; 1028267897a4SAntti Palosaari c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1029267897a4SAntti Palosaari 1030de8e4203SAntti Palosaari return ret; 1031de8e4203SAntti Palosaari error_release_firmware: 1032de8e4203SAntti Palosaari release_firmware(fw); 1033de8e4203SAntti Palosaari error: 103459ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1035de8e4203SAntti Palosaari return ret; 1036de8e4203SAntti Palosaari } 1037de8e4203SAntti Palosaari 1038de8e4203SAntti Palosaari static int tda10071_sleep(struct dvb_frontend *fe) 1039de8e4203SAntti Palosaari { 1040fca3e007SAntti Palosaari struct tda10071_dev *dev = fe->demodulator_priv; 1041fca3e007SAntti Palosaari struct i2c_client *client = dev->client; 1042de8e4203SAntti Palosaari struct tda10071_cmd cmd; 1043de8e4203SAntti Palosaari int ret, i; 1044de8e4203SAntti Palosaari struct tda10071_reg_val_mask tab[] = { 1045de8e4203SAntti Palosaari { 0xcd, 0x07, 0x07 }, 1046de8e4203SAntti Palosaari { 0x80, 0x02, 0x02 }, 1047de8e4203SAntti Palosaari { 0xcd, 0xc0, 0xc0 }, 1048de8e4203SAntti Palosaari { 0xce, 0x1b, 0x1b }, 1049de8e4203SAntti Palosaari { 0x9d, 0x01, 0x01 }, 1050de8e4203SAntti Palosaari { 0x9d, 0x02, 0x02 }, 1051de8e4203SAntti Palosaari { 0x9e, 0x01, 0x01 }, 1052de8e4203SAntti Palosaari { 0x87, 0x80, 0x80 }, 1053de8e4203SAntti Palosaari { 0xce, 0x08, 0x08 }, 1054de8e4203SAntti Palosaari { 0xce, 0x10, 0x10 }, 1055de8e4203SAntti Palosaari }; 1056de8e4203SAntti Palosaari 1057fca3e007SAntti Palosaari if (!dev->warm) { 1058de8e4203SAntti Palosaari ret = -EFAULT; 1059de8e4203SAntti Palosaari goto error; 1060de8e4203SAntti Palosaari } 1061de8e4203SAntti Palosaari 106221c8ba39SAntti Palosaari cmd.args[0] = CMD_SET_SLEEP_MODE; 106321c8ba39SAntti Palosaari cmd.args[1] = 0; 106421c8ba39SAntti Palosaari cmd.args[2] = 1; 106521c8ba39SAntti Palosaari cmd.len = 3; 1066fca3e007SAntti Palosaari ret = tda10071_cmd_execute(dev, &cmd); 1067de8e4203SAntti Palosaari if (ret) 1068de8e4203SAntti Palosaari goto error; 1069de8e4203SAntti Palosaari 1070de8e4203SAntti Palosaari for (i = 0; i < ARRAY_SIZE(tab); i++) { 1071fca3e007SAntti Palosaari ret = tda10071_wr_reg_mask(dev, tab[i].reg, tab[i].val, 1072de8e4203SAntti Palosaari tab[i].mask); 1073de8e4203SAntti Palosaari if (ret) 1074de8e4203SAntti Palosaari goto error; 1075de8e4203SAntti Palosaari } 1076de8e4203SAntti Palosaari 1077de8e4203SAntti Palosaari return ret; 1078de8e4203SAntti Palosaari error: 107959ca2ce1SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1080de8e4203SAntti Palosaari return ret; 1081de8e4203SAntti Palosaari } 1082de8e4203SAntti Palosaari 1083de8e4203SAntti Palosaari static int tda10071_get_tune_settings(struct dvb_frontend *fe, 1084de8e4203SAntti Palosaari struct dvb_frontend_tune_settings *s) 1085de8e4203SAntti Palosaari { 1086de8e4203SAntti Palosaari s->min_delay_ms = 8000; 1087de8e4203SAntti Palosaari s->step_size = 0; 1088de8e4203SAntti Palosaari s->max_drift = 0; 1089de8e4203SAntti Palosaari 1090de8e4203SAntti Palosaari return 0; 1091de8e4203SAntti Palosaari } 1092de8e4203SAntti Palosaari 1093bd336e63SMax Kellermann static const struct dvb_frontend_ops tda10071_ops = { 10942b49fad5SAntti Palosaari .delsys = { SYS_DVBS, SYS_DVBS2 }, 1095de8e4203SAntti Palosaari .info = { 1096de8e4203SAntti Palosaari .name = "NXP TDA10071", 1097f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 950 * MHz, 1098f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 2150 * MHz, 1099f1b1eabfSMauro Carvalho Chehab .frequency_tolerance_hz = 5 * MHz, 1100de8e4203SAntti Palosaari .symbol_rate_min = 1000000, 1101de8e4203SAntti Palosaari .symbol_rate_max = 45000000, 1102de8e4203SAntti Palosaari .caps = FE_CAN_INVERSION_AUTO | 1103de8e4203SAntti Palosaari FE_CAN_FEC_1_2 | 1104de8e4203SAntti Palosaari FE_CAN_FEC_2_3 | 1105de8e4203SAntti Palosaari FE_CAN_FEC_3_4 | 1106de8e4203SAntti Palosaari FE_CAN_FEC_4_5 | 1107de8e4203SAntti Palosaari FE_CAN_FEC_5_6 | 1108de8e4203SAntti Palosaari FE_CAN_FEC_6_7 | 1109de8e4203SAntti Palosaari FE_CAN_FEC_7_8 | 1110de8e4203SAntti Palosaari FE_CAN_FEC_8_9 | 1111de8e4203SAntti Palosaari FE_CAN_FEC_AUTO | 1112de8e4203SAntti Palosaari FE_CAN_QPSK | 1113de8e4203SAntti Palosaari FE_CAN_RECOVER | 1114de8e4203SAntti Palosaari FE_CAN_2G_MODULATION 1115de8e4203SAntti Palosaari }, 1116de8e4203SAntti Palosaari 1117de8e4203SAntti Palosaari .get_tune_settings = tda10071_get_tune_settings, 1118de8e4203SAntti Palosaari 1119de8e4203SAntti Palosaari .init = tda10071_init, 1120de8e4203SAntti Palosaari .sleep = tda10071_sleep, 1121de8e4203SAntti Palosaari 1122b2a29b57SMauro Carvalho Chehab .set_frontend = tda10071_set_frontend, 1123b2a29b57SMauro Carvalho Chehab .get_frontend = tda10071_get_frontend, 1124de8e4203SAntti Palosaari 1125de8e4203SAntti Palosaari .read_status = tda10071_read_status, 1126de8e4203SAntti Palosaari .read_snr = tda10071_read_snr, 1127de8e4203SAntti Palosaari .read_signal_strength = tda10071_read_signal_strength, 1128de8e4203SAntti Palosaari .read_ber = tda10071_read_ber, 1129de8e4203SAntti Palosaari .read_ucblocks = tda10071_read_ucblocks, 1130de8e4203SAntti Palosaari 1131de8e4203SAntti Palosaari .diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd, 1132de8e4203SAntti Palosaari .diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply, 1133de8e4203SAntti Palosaari .diseqc_send_burst = tda10071_diseqc_send_burst, 1134de8e4203SAntti Palosaari 1135de8e4203SAntti Palosaari .set_tone = tda10071_set_tone, 1136de8e4203SAntti Palosaari .set_voltage = tda10071_set_voltage, 1137de8e4203SAntti Palosaari }; 1138de8e4203SAntti Palosaari 1139d69abb79SAntti Palosaari static struct dvb_frontend *tda10071_get_dvb_frontend(struct i2c_client *client) 1140d69abb79SAntti Palosaari { 1141fca3e007SAntti Palosaari struct tda10071_dev *dev = i2c_get_clientdata(client); 1142d69abb79SAntti Palosaari 1143d69abb79SAntti Palosaari dev_dbg(&client->dev, "\n"); 1144d69abb79SAntti Palosaari 1145d69abb79SAntti Palosaari return &dev->fe; 1146d69abb79SAntti Palosaari } 1147d69abb79SAntti Palosaari 1148d69abb79SAntti Palosaari static int tda10071_probe(struct i2c_client *client, 1149d69abb79SAntti Palosaari const struct i2c_device_id *id) 1150d69abb79SAntti Palosaari { 1151fca3e007SAntti Palosaari struct tda10071_dev *dev; 1152d69abb79SAntti Palosaari struct tda10071_platform_data *pdata = client->dev.platform_data; 1153d69abb79SAntti Palosaari int ret; 115454ab48edSAntti Palosaari unsigned int uitmp; 115554ab48edSAntti Palosaari static const struct regmap_config regmap_config = { 115654ab48edSAntti Palosaari .reg_bits = 8, 115754ab48edSAntti Palosaari .val_bits = 8, 115854ab48edSAntti Palosaari }; 1159d69abb79SAntti Palosaari 1160d69abb79SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1161d69abb79SAntti Palosaari if (!dev) { 1162d69abb79SAntti Palosaari ret = -ENOMEM; 1163d69abb79SAntti Palosaari goto err; 1164d69abb79SAntti Palosaari } 1165d69abb79SAntti Palosaari 1166d69abb79SAntti Palosaari dev->client = client; 1167e14432a5SAntti Palosaari mutex_init(&dev->cmd_execute_mutex); 116859ca2ce1SAntti Palosaari dev->clk = pdata->clk; 116959ca2ce1SAntti Palosaari dev->i2c_wr_max = pdata->i2c_wr_max; 117059ca2ce1SAntti Palosaari dev->ts_mode = pdata->ts_mode; 117159ca2ce1SAntti Palosaari dev->spec_inv = pdata->spec_inv; 117259ca2ce1SAntti Palosaari dev->pll_multiplier = pdata->pll_multiplier; 117359ca2ce1SAntti Palosaari dev->tuner_i2c_addr = pdata->tuner_i2c_addr; 117454ab48edSAntti Palosaari dev->regmap = devm_regmap_init_i2c(client, ®map_config); 117554ab48edSAntti Palosaari if (IS_ERR(dev->regmap)) { 117654ab48edSAntti Palosaari ret = PTR_ERR(dev->regmap); 117754ab48edSAntti Palosaari goto err_kfree; 117854ab48edSAntti Palosaari } 1179d69abb79SAntti Palosaari 1180d69abb79SAntti Palosaari /* chip ID */ 118154ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0xff, &uitmp); 1182ab80b19bSAntti Palosaari if (ret) 1183d69abb79SAntti Palosaari goto err_kfree; 118454ab48edSAntti Palosaari if (uitmp != 0x0f) { 1185ab80b19bSAntti Palosaari ret = -ENODEV; 1186ab80b19bSAntti Palosaari goto err_kfree; 1187ab80b19bSAntti Palosaari } 1188d69abb79SAntti Palosaari 1189d69abb79SAntti Palosaari /* chip type */ 119054ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0xdd, &uitmp); 1191ab80b19bSAntti Palosaari if (ret) 1192d69abb79SAntti Palosaari goto err_kfree; 119354ab48edSAntti Palosaari if (uitmp != 0x00) { 1194ab80b19bSAntti Palosaari ret = -ENODEV; 1195ab80b19bSAntti Palosaari goto err_kfree; 1196ab80b19bSAntti Palosaari } 1197d69abb79SAntti Palosaari 1198d69abb79SAntti Palosaari /* chip version */ 119954ab48edSAntti Palosaari ret = regmap_read(dev->regmap, 0xfe, &uitmp); 1200ab80b19bSAntti Palosaari if (ret) 1201d69abb79SAntti Palosaari goto err_kfree; 120254ab48edSAntti Palosaari if (uitmp != 0x01) { 1203ab80b19bSAntti Palosaari ret = -ENODEV; 1204ab80b19bSAntti Palosaari goto err_kfree; 1205ab80b19bSAntti Palosaari } 1206d69abb79SAntti Palosaari 1207d69abb79SAntti Palosaari /* create dvb_frontend */ 1208d69abb79SAntti Palosaari memcpy(&dev->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops)); 1209d69abb79SAntti Palosaari dev->fe.demodulator_priv = dev; 1210d69abb79SAntti Palosaari i2c_set_clientdata(client, dev); 1211d69abb79SAntti Palosaari 1212d69abb79SAntti Palosaari /* setup callbacks */ 1213d69abb79SAntti Palosaari pdata->get_dvb_frontend = tda10071_get_dvb_frontend; 1214d69abb79SAntti Palosaari 1215d69abb79SAntti Palosaari dev_info(&client->dev, "NXP TDA10071 successfully identified\n"); 1216d69abb79SAntti Palosaari return 0; 1217d69abb79SAntti Palosaari err_kfree: 1218d69abb79SAntti Palosaari kfree(dev); 1219d69abb79SAntti Palosaari err: 1220d69abb79SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 1221d69abb79SAntti Palosaari return ret; 1222d69abb79SAntti Palosaari } 1223d69abb79SAntti Palosaari 1224d69abb79SAntti Palosaari static int tda10071_remove(struct i2c_client *client) 1225d69abb79SAntti Palosaari { 1226d69abb79SAntti Palosaari struct tda10071_dev *dev = i2c_get_clientdata(client); 1227d69abb79SAntti Palosaari 1228d69abb79SAntti Palosaari dev_dbg(&client->dev, "\n"); 1229d69abb79SAntti Palosaari 1230d69abb79SAntti Palosaari kfree(dev); 1231d69abb79SAntti Palosaari return 0; 1232d69abb79SAntti Palosaari } 1233d69abb79SAntti Palosaari 1234d69abb79SAntti Palosaari static const struct i2c_device_id tda10071_id_table[] = { 1235d69abb79SAntti Palosaari {"tda10071_cx24118", 0}, 1236d69abb79SAntti Palosaari {} 1237d69abb79SAntti Palosaari }; 1238d69abb79SAntti Palosaari MODULE_DEVICE_TABLE(i2c, tda10071_id_table); 1239d69abb79SAntti Palosaari 1240d69abb79SAntti Palosaari static struct i2c_driver tda10071_driver = { 1241d69abb79SAntti Palosaari .driver = { 1242d69abb79SAntti Palosaari .name = "tda10071", 1243d69abb79SAntti Palosaari .suppress_bind_attrs = true, 1244d69abb79SAntti Palosaari }, 1245d69abb79SAntti Palosaari .probe = tda10071_probe, 1246d69abb79SAntti Palosaari .remove = tda10071_remove, 1247d69abb79SAntti Palosaari .id_table = tda10071_id_table, 1248d69abb79SAntti Palosaari }; 1249d69abb79SAntti Palosaari 1250d69abb79SAntti Palosaari module_i2c_driver(tda10071_driver); 1251d69abb79SAntti Palosaari 1252de8e4203SAntti Palosaari MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 1253de8e4203SAntti Palosaari MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver"); 1254de8e4203SAntti Palosaari MODULE_LICENSE("GPL"); 125503f4efc3SAntti Palosaari MODULE_FIRMWARE(TDA10071_FIRMWARE); 1256