Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] Montage M88DS3103 DVB-S/S2 demodulator driver

DVB-S/S2 satellite television demodulator driver.

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

authored by

Antti Palosaari and committed by
Mauro Carvalho Chehab
395d00d1 0400c535

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