1176 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 DVB device driver for cx231xx4 5 Copyright (C) 2008 <srinivasa.deevi at conexant dot com>6 Based on em28xx driver7 8 */9 10#include "cx231xx.h"11#include <linux/kernel.h>12#include <linux/slab.h>13 14#include <media/dvbdev.h>15#include <media/dmxdev.h>16#include <media/dvb_demux.h>17#include <media/dvb_net.h>18#include <media/dvb_frontend.h>19#include <media/v4l2-common.h>20#include <media/tuner.h>21 22#include "xc5000.h"23#include "s5h1432.h"24#include "tda18271.h"25#include "s5h1411.h"26#include "lgdt3305.h"27#include "si2165.h"28#include "si2168.h"29#include "mb86a20s.h"30#include "si2157.h"31#include "lgdt3306a.h"32#include "r820t.h"33#include "mn88473.h"34 35MODULE_DESCRIPTION("driver for cx231xx based DVB cards");36MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");37MODULE_LICENSE("GPL");38 39static unsigned int debug;40module_param(debug, int, 0644);41MODULE_PARM_DESC(debug, "enable debug messages [dvb]");42 43DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);44 45#define CX231XX_DVB_NUM_BUFS 546#define CX231XX_DVB_MAX_PACKETSIZE 56447#define CX231XX_DVB_MAX_PACKETS 6448#define CX231XX_DVB_MAX_FRONTENDS 249 50struct cx231xx_dvb {51 struct dvb_frontend *frontend[CX231XX_DVB_MAX_FRONTENDS];52 53 /* feed count management */54 struct mutex lock;55 int nfeeds;56 57 /* general boilerplate stuff */58 struct dvb_adapter adapter;59 struct dvb_demux demux;60 struct dmxdev dmxdev;61 struct dmx_frontend fe_hw;62 struct dmx_frontend fe_mem;63 struct dvb_net net;64 struct i2c_client *i2c_client_demod[2];65 struct i2c_client *i2c_client_tuner;66};67 68static struct s5h1432_config dvico_s5h1432_config = {69 .output_mode = S5H1432_SERIAL_OUTPUT,70 .gpio = S5H1432_GPIO_ON,71 .qam_if = S5H1432_IF_4000,72 .vsb_if = S5H1432_IF_4000,73 .inversion = S5H1432_INVERSION_OFF,74 .status_mode = S5H1432_DEMODLOCKING,75 .mpeg_timing = S5H1432_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,76};77 78static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {79 .dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4,80 .if_lvl = 1, .rfagc_top = 0x37, },81 .dvbt_7 = { .if_freq = 4000, .agc_mode = 3, .std = 5,82 .if_lvl = 1, .rfagc_top = 0x37, },83 .dvbt_8 = { .if_freq = 4000, .agc_mode = 3, .std = 6,84 .if_lvl = 1, .rfagc_top = 0x37, },85};86 87static struct tda18271_std_map mb86a20s_tda18271_config = {88 .dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4,89 .if_lvl = 0, .rfagc_top = 0x37, },90};91 92static struct tda18271_config cnxt_rde253s_tunerconfig = {93 .std_map = &cnxt_rde253s_tda18271_std_map,94 .gate = TDA18271_GATE_ANALOG,95};96 97static struct s5h1411_config tda18271_s5h1411_config = {98 .output_mode = S5H1411_SERIAL_OUTPUT,99 .gpio = S5H1411_GPIO_OFF,100 .vsb_if = S5H1411_IF_3250,101 .qam_if = S5H1411_IF_4000,102 .inversion = S5H1411_INVERSION_ON,103 .status_mode = S5H1411_DEMODLOCKING,104 .mpeg_timing = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,105};106static struct s5h1411_config xc5000_s5h1411_config = {107 .output_mode = S5H1411_SERIAL_OUTPUT,108 .gpio = S5H1411_GPIO_OFF,109 .vsb_if = S5H1411_IF_3250,110 .qam_if = S5H1411_IF_3250,111 .inversion = S5H1411_INVERSION_OFF,112 .status_mode = S5H1411_DEMODLOCKING,113 .mpeg_timing = S5H1411_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK,114};115 116static struct lgdt3305_config hcw_lgdt3305_config = {117 .i2c_addr = 0x0e,118 .mpeg_mode = LGDT3305_MPEG_SERIAL,119 .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE,120 .tpvalid_polarity = LGDT3305_TP_VALID_HIGH,121 .deny_i2c_rptr = 1,122 .spectral_inversion = 1,123 .qam_if_khz = 4000,124 .vsb_if_khz = 3250,125};126 127static struct tda18271_std_map hauppauge_tda18271_std_map = {128 .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4,129 .if_lvl = 1, .rfagc_top = 0x58, },130 .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5,131 .if_lvl = 1, .rfagc_top = 0x58, },132};133 134static struct tda18271_config hcw_tda18271_config = {135 .std_map = &hauppauge_tda18271_std_map,136 .gate = TDA18271_GATE_DIGITAL,137};138 139static const struct mb86a20s_config pv_mb86a20s_config = {140 .demod_address = 0x10,141 .is_serial = true,142};143 144static struct tda18271_config pv_tda18271_config = {145 .std_map = &mb86a20s_tda18271_config,146 .gate = TDA18271_GATE_DIGITAL,147 .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,148};149 150static const struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = {151 .qam_if_khz = 4000,152 .vsb_if_khz = 3250,153 .spectral_inversion = 1,154 .mpeg_mode = LGDT3306A_MPEG_SERIAL,155 .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE,156 .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH,157 .xtalMHz = 25,158};159 160static struct r820t_config astrometa_t2hybrid_r820t_config = {161 .i2c_addr = 0x3a, /* 0x74 >> 1 */162 .xtal = 16000000,163 .rafael_chip = CHIP_R828D,164 .max_i2c_msg_len = 2,165};166 167static inline void print_err_status(struct cx231xx *dev, int packet, int status)168{169 char *errmsg = "Unknown";170 171 switch (status) {172 case -ENOENT:173 errmsg = "unlinked synchronously";174 break;175 case -ECONNRESET:176 errmsg = "unlinked asynchronously";177 break;178 case -ENOSR:179 errmsg = "Buffer error (overrun)";180 break;181 case -EPIPE:182 errmsg = "Stalled (device not responding)";183 break;184 case -EOVERFLOW:185 errmsg = "Babble (bad cable?)";186 break;187 case -EPROTO:188 errmsg = "Bit-stuff error (bad cable?)";189 break;190 case -EILSEQ:191 errmsg = "CRC/Timeout (could be anything)";192 break;193 case -ETIME:194 errmsg = "Device does not respond";195 break;196 }197 if (packet < 0) {198 dev_dbg(dev->dev,199 "URB status %d [%s].\n", status, errmsg);200 } else {201 dev_dbg(dev->dev,202 "URB packet %d, status %d [%s].\n",203 packet, status, errmsg);204 }205}206 207static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)208{209 int i;210 211 if (!dev)212 return 0;213 214 if (dev->state & DEV_DISCONNECTED)215 return 0;216 217 if (urb->status < 0) {218 print_err_status(dev, -1, urb->status);219 if (urb->status == -ENOENT)220 return 0;221 }222 223 for (i = 0; i < urb->number_of_packets; i++) {224 int status = urb->iso_frame_desc[i].status;225 226 if (status < 0) {227 print_err_status(dev, i, status);228 if (urb->iso_frame_desc[i].status != -EPROTO)229 continue;230 }231 232 dvb_dmx_swfilter(&dev->dvb->demux,233 urb->transfer_buffer +234 urb->iso_frame_desc[i].offset,235 urb->iso_frame_desc[i].actual_length);236 }237 238 return 0;239}240 241static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)242{243 if (!dev)244 return 0;245 246 if (dev->state & DEV_DISCONNECTED)247 return 0;248 249 if (urb->status < 0) {250 print_err_status(dev, -1, urb->status);251 if (urb->status == -ENOENT)252 return 0;253 }254 255 /* Feed the transport payload into the kernel demux */256 dvb_dmx_swfilter(&dev->dvb->demux,257 urb->transfer_buffer, urb->actual_length);258 259 return 0;260}261 262static int start_streaming(struct cx231xx_dvb *dvb)263{264 int rc;265 struct cx231xx *dev = dvb->adapter.priv;266 267 if (dev->USE_ISO) {268 dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");269 cx231xx_set_alt_setting(dev, INDEX_TS1, 5);270 rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);271 if (rc < 0)272 return rc;273 dev->mode_tv = 1;274 return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,275 CX231XX_DVB_NUM_BUFS,276 dev->ts1_mode.max_pkt_size,277 dvb_isoc_copy);278 } else {279 dev_dbg(dev->dev, "DVB transfer mode is BULK.\n");280 cx231xx_set_alt_setting(dev, INDEX_TS1, 0);281 rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);282 if (rc < 0)283 return rc;284 dev->mode_tv = 1;285 return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,286 CX231XX_DVB_NUM_BUFS,287 dev->ts1_mode.max_pkt_size,288 dvb_bulk_copy);289 }290 291}292 293static int stop_streaming(struct cx231xx_dvb *dvb)294{295 struct cx231xx *dev = dvb->adapter.priv;296 297 if (dev->USE_ISO)298 cx231xx_uninit_isoc(dev);299 else300 cx231xx_uninit_bulk(dev);301 302 cx231xx_set_mode(dev, CX231XX_SUSPEND);303 304 return 0;305}306 307static int start_feed(struct dvb_demux_feed *feed)308{309 struct dvb_demux *demux = feed->demux;310 struct cx231xx_dvb *dvb = demux->priv;311 int rc, ret;312 313 if (!demux->dmx.frontend)314 return -EINVAL;315 316 mutex_lock(&dvb->lock);317 dvb->nfeeds++;318 rc = dvb->nfeeds;319 320 if (dvb->nfeeds == 1) {321 ret = start_streaming(dvb);322 if (ret < 0)323 rc = ret;324 }325 326 mutex_unlock(&dvb->lock);327 return rc;328}329 330static int stop_feed(struct dvb_demux_feed *feed)331{332 struct dvb_demux *demux = feed->demux;333 struct cx231xx_dvb *dvb = demux->priv;334 int err = 0;335 336 mutex_lock(&dvb->lock);337 dvb->nfeeds--;338 339 if (0 == dvb->nfeeds)340 err = stop_streaming(dvb);341 342 mutex_unlock(&dvb->lock);343 return err;344}345 346/* ------------------------------------------------------------------ */347static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)348{349 struct cx231xx *dev = fe->dvb->priv;350 351 if (acquire)352 return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);353 else354 return cx231xx_set_mode(dev, CX231XX_SUSPEND);355}356 357/* ------------------------------------------------------------------ */358 359static struct xc5000_config cnxt_rde250_tunerconfig = {360 .i2c_address = 0x61,361 .if_khz = 4000,362};363static struct xc5000_config cnxt_rdu250_tunerconfig = {364 .i2c_address = 0x61,365 .if_khz = 3250,366};367 368/* ------------------------------------------------------------------ */369#if 0370static int attach_xc5000(u8 addr, struct cx231xx *dev)371{372 373 struct dvb_frontend *fe;374 struct xc5000_config cfg;375 376 memset(&cfg, 0, sizeof(cfg));377 cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);378 cfg.i2c_addr = addr;379 380 if (!dev->dvb->frontend[0]) {381 dev_err(dev->dev, "%s/2: dvb frontend not attached. Can't attach xc5000\n",382 dev->name);383 return -EINVAL;384 }385 386 fe = dvb_attach(xc5000_attach, dev->dvb->frontend[0], &cfg);387 if (!fe) {388 dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name);389 dvb_frontend_detach(dev->dvb->frontend[0]);390 dev->dvb->frontend[0] = NULL;391 return -EINVAL;392 }393 394 dev_info(dev->dev, "%s/2: xc5000 attached\n", dev->name);395 396 return 0;397}398#endif399 400int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)401{402 if (dev->dvb && dev->dvb->frontend[0]) {403 404 struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops;405 406 if (dops->set_analog_params != NULL) {407 struct analog_parameters params;408 409 params.frequency = freq;410 params.std = dev->norm;411 params.mode = 0; /* 0- Air; 1 - cable */412 /*params.audmode = ; */413 414 /* Set the analog parameters to set the frequency */415 dops->set_analog_params(dev->dvb->frontend[0], ¶ms);416 }417 418 }419 420 return 0;421}422 423int cx231xx_reset_analog_tuner(struct cx231xx *dev)424{425 int status = 0;426 427 if (dev->dvb && dev->dvb->frontend[0]) {428 429 struct dvb_tuner_ops *dops = &dev->dvb->frontend[0]->ops.tuner_ops;430 431 if (dops->init != NULL && !dev->xc_fw_load_done) {432 433 dev_dbg(dev->dev,434 "Reloading firmware for XC5000\n");435 status = dops->init(dev->dvb->frontend[0]);436 if (status == 0) {437 dev->xc_fw_load_done = 1;438 dev_dbg(dev->dev,439 "XC5000 firmware download completed\n");440 } else {441 dev->xc_fw_load_done = 0;442 dev_dbg(dev->dev,443 "XC5000 firmware download failed !!!\n");444 }445 }446 447 }448 449 return status;450}451 452/* ------------------------------------------------------------------ */453 454static int register_dvb(struct cx231xx_dvb *dvb,455 struct module *module,456 struct cx231xx *dev, struct device *device)457{458 int result;459 460 mutex_init(&dvb->lock);461 462 463 /* register adapter */464 result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,465 adapter_nr);466 if (result < 0) {467 dev_warn(dev->dev,468 "%s: dvb_register_adapter failed (errno = %d)\n",469 dev->name, result);470 goto fail_adapter;471 }472 dvb_register_media_controller(&dvb->adapter, dev->media_dev);473 474 /* Ensure all frontends negotiate bus access */475 dvb->frontend[0]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;476 if (dvb->frontend[1])477 dvb->frontend[1]->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;478 479 dvb->adapter.priv = dev;480 481 /* register frontend */482 result = dvb_register_frontend(&dvb->adapter, dvb->frontend[0]);483 if (result < 0) {484 dev_warn(dev->dev,485 "%s: dvb_register_frontend failed (errno = %d)\n",486 dev->name, result);487 goto fail_frontend0;488 }489 490 if (dvb->frontend[1]) {491 result = dvb_register_frontend(&dvb->adapter, dvb->frontend[1]);492 if (result < 0) {493 dev_warn(dev->dev,494 "%s: 2nd dvb_register_frontend failed (errno = %d)\n",495 dev->name, result);496 goto fail_frontend1;497 }498 499 /* MFE lock */500 dvb->adapter.mfe_shared = 1;501 }502 503 /* register demux stuff */504 dvb->demux.dmx.capabilities =505 DMX_TS_FILTERING | DMX_SECTION_FILTERING |506 DMX_MEMORY_BASED_FILTERING;507 dvb->demux.priv = dvb;508 dvb->demux.filternum = 256;509 dvb->demux.feednum = 256;510 dvb->demux.start_feed = start_feed;511 dvb->demux.stop_feed = stop_feed;512 513 result = dvb_dmx_init(&dvb->demux);514 if (result < 0) {515 dev_warn(dev->dev,516 "%s: dvb_dmx_init failed (errno = %d)\n",517 dev->name, result);518 goto fail_dmx;519 }520 521 dvb->dmxdev.filternum = 256;522 dvb->dmxdev.demux = &dvb->demux.dmx;523 dvb->dmxdev.capabilities = 0;524 result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);525 if (result < 0) {526 dev_warn(dev->dev,527 "%s: dvb_dmxdev_init failed (errno = %d)\n",528 dev->name, result);529 goto fail_dmxdev;530 }531 532 dvb->fe_hw.source = DMX_FRONTEND_0;533 result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);534 if (result < 0) {535 dev_warn(dev->dev,536 "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",537 dev->name, result);538 goto fail_fe_hw;539 }540 541 dvb->fe_mem.source = DMX_MEMORY_FE;542 result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);543 if (result < 0) {544 dev_warn(dev->dev,545 "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",546 dev->name, result);547 goto fail_fe_mem;548 }549 550 result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);551 if (result < 0) {552 dev_warn(dev->dev,553 "%s: connect_frontend failed (errno = %d)\n",554 dev->name, result);555 goto fail_fe_conn;556 }557 558 /* register network adapter */559 dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);560 result = dvb_create_media_graph(&dvb->adapter,561 dev->tuner_type == TUNER_ABSENT);562 if (result < 0)563 goto fail_create_graph;564 565 return 0;566 567fail_create_graph:568 dvb_net_release(&dvb->net);569fail_fe_conn:570 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);571fail_fe_mem:572 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);573fail_fe_hw:574 dvb_dmxdev_release(&dvb->dmxdev);575fail_dmxdev:576 dvb_dmx_release(&dvb->demux);577fail_dmx:578 if (dvb->frontend[1])579 dvb_unregister_frontend(dvb->frontend[1]);580 dvb_unregister_frontend(dvb->frontend[0]);581fail_frontend1:582 if (dvb->frontend[1])583 dvb_frontend_detach(dvb->frontend[1]);584fail_frontend0:585 dvb_frontend_detach(dvb->frontend[0]);586 dvb_unregister_adapter(&dvb->adapter);587fail_adapter:588 return result;589}590 591static void unregister_dvb(struct cx231xx_dvb *dvb)592{593 dvb_net_release(&dvb->net);594 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);595 dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);596 dvb_dmxdev_release(&dvb->dmxdev);597 dvb_dmx_release(&dvb->demux);598 if (dvb->frontend[1])599 dvb_unregister_frontend(dvb->frontend[1]);600 dvb_unregister_frontend(dvb->frontend[0]);601 if (dvb->frontend[1])602 dvb_frontend_detach(dvb->frontend[1]);603 dvb_frontend_detach(dvb->frontend[0]);604 dvb_unregister_adapter(&dvb->adapter);605 606 /* remove I2C tuner */607 dvb_module_release(dvb->i2c_client_tuner);608 dvb->i2c_client_tuner = NULL;609 /* remove I2C demod(s) */610 dvb_module_release(dvb->i2c_client_demod[1]);611 dvb->i2c_client_demod[1] = NULL;612 dvb_module_release(dvb->i2c_client_demod[0]);613 dvb->i2c_client_demod[0] = NULL;614}615 616static int dvb_init(struct cx231xx *dev)617{618 int result;619 struct cx231xx_dvb *dvb;620 struct i2c_adapter *tuner_i2c;621 struct i2c_adapter *demod_i2c;622 struct i2c_client *client;623 struct i2c_adapter *adapter;624 625 if (!dev->board.has_dvb) {626 /* This device does not support the extension */627 return 0;628 }629 630 dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);631 632 if (dvb == NULL) {633 dev_info(dev->dev,634 "cx231xx_dvb: memory allocation failed\n");635 return -ENOMEM;636 }637 dev->dvb = dvb;638 dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;639 dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;640 641 tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);642 demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);643 mutex_lock(&dev->lock);644 cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);645 cx231xx_demod_reset(dev);646 /* init frontend */647 switch (dev->model) {648 case CX231XX_BOARD_CNXT_CARRAERA:649 case CX231XX_BOARD_CNXT_RDE_250:650 651 dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,652 &dvico_s5h1432_config,653 demod_i2c);654 655 if (!dev->dvb->frontend[0]) {656 dev_err(dev->dev,657 "Failed to attach s5h1432 front end\n");658 result = -EINVAL;659 goto out_free;660 }661 662 /* define general-purpose callback pointer */663 dvb->frontend[0]->callback = cx231xx_tuner_callback;664 665 if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],666 tuner_i2c,667 &cnxt_rde250_tunerconfig)) {668 result = -EINVAL;669 goto out_free;670 }671 672 break;673 case CX231XX_BOARD_CNXT_SHELBY:674 case CX231XX_BOARD_CNXT_RDU_250:675 676 dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,677 &xc5000_s5h1411_config,678 demod_i2c);679 680 if (!dev->dvb->frontend[0]) {681 dev_err(dev->dev,682 "Failed to attach s5h1411 front end\n");683 result = -EINVAL;684 goto out_free;685 }686 687 /* define general-purpose callback pointer */688 dvb->frontend[0]->callback = cx231xx_tuner_callback;689 690 if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],691 tuner_i2c,692 &cnxt_rdu250_tunerconfig)) {693 result = -EINVAL;694 goto out_free;695 }696 break;697 case CX231XX_BOARD_CNXT_RDE_253S:698 699 dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,700 &dvico_s5h1432_config,701 demod_i2c);702 703 if (!dev->dvb->frontend[0]) {704 dev_err(dev->dev,705 "Failed to attach s5h1432 front end\n");706 result = -EINVAL;707 goto out_free;708 }709 710 /* define general-purpose callback pointer */711 dvb->frontend[0]->callback = cx231xx_tuner_callback;712 713 if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],714 dev->board.tuner_addr, tuner_i2c,715 &cnxt_rde253s_tunerconfig)) {716 result = -EINVAL;717 goto out_free;718 }719 break;720 case CX231XX_BOARD_CNXT_RDU_253S:721 case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID:722 723 dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,724 &tda18271_s5h1411_config,725 demod_i2c);726 727 if (!dev->dvb->frontend[0]) {728 dev_err(dev->dev,729 "Failed to attach s5h1411 front end\n");730 result = -EINVAL;731 goto out_free;732 }733 734 /* define general-purpose callback pointer */735 dvb->frontend[0]->callback = cx231xx_tuner_callback;736 737 if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],738 dev->board.tuner_addr, tuner_i2c,739 &cnxt_rde253s_tunerconfig)) {740 result = -EINVAL;741 goto out_free;742 }743 break;744 case CX231XX_BOARD_HAUPPAUGE_EXETER:745 746 dev_info(dev->dev,747 "%s: looking for tuner / demod on i2c bus: %d\n",748 __func__, i2c_adapter_id(tuner_i2c));749 750 dev->dvb->frontend[0] = dvb_attach(lgdt3305_attach,751 &hcw_lgdt3305_config,752 demod_i2c);753 754 if (!dev->dvb->frontend[0]) {755 dev_err(dev->dev,756 "Failed to attach LG3305 front end\n");757 result = -EINVAL;758 goto out_free;759 }760 761 /* define general-purpose callback pointer */762 dvb->frontend[0]->callback = cx231xx_tuner_callback;763 764 dvb_attach(tda18271_attach, dev->dvb->frontend[0],765 dev->board.tuner_addr, tuner_i2c,766 &hcw_tda18271_config);767 break;768 769 case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:770 {771 struct si2165_platform_data si2165_pdata = {};772 773 /* attach demod */774 si2165_pdata.fe = &dev->dvb->frontend[0];775 si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL;776 si2165_pdata.ref_freq_hz = 16000000;777 778 /* perform probe/init/attach */779 client = dvb_module_probe("si2165", NULL, demod_i2c,780 dev->board.demod_addr,781 &si2165_pdata);782 if (!client) {783 result = -ENODEV;784 goto out_free;785 }786 dvb->i2c_client_demod[0] = client;787 788 dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;789 790 /* define general-purpose callback pointer */791 dvb->frontend[0]->callback = cx231xx_tuner_callback;792 793 dvb_attach(tda18271_attach, dev->dvb->frontend[0],794 dev->board.tuner_addr, tuner_i2c,795 &hcw_tda18271_config);796 797 dev->cx231xx_reset_analog_tuner = NULL;798 break;799 }800 case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:801 {802 struct si2165_platform_data si2165_pdata = {};803 struct si2157_config si2157_config = {};804 805 /* attach demod */806 si2165_pdata.fe = &dev->dvb->frontend[0];807 si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT;808 si2165_pdata.ref_freq_hz = 24000000;809 810 /* perform probe/init/attach */811 client = dvb_module_probe("si2165", NULL, demod_i2c,812 dev->board.demod_addr,813 &si2165_pdata);814 if (!client) {815 result = -ENODEV;816 goto out_free;817 }818 dvb->i2c_client_demod[0] = client;819 820 dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;821 822 /* define general-purpose callback pointer */823 dvb->frontend[0]->callback = cx231xx_tuner_callback;824 825 /* attach tuner */826 si2157_config.fe = dev->dvb->frontend[0];827#ifdef CONFIG_MEDIA_CONTROLLER_DVB828 si2157_config.mdev = dev->media_dev;829#endif830 si2157_config.if_port = 1;831 si2157_config.inversion = true;832 833 /* perform probe/init/attach */834 client = dvb_module_probe("si2157", NULL, tuner_i2c,835 dev->board.tuner_addr,836 &si2157_config);837 if (!client) {838 result = -ENODEV;839 goto out_free;840 }841 dev->cx231xx_reset_analog_tuner = NULL;842 843 dev->dvb->i2c_client_tuner = client;844 break;845 }846 case CX231XX_BOARD_HAUPPAUGE_955Q:847 {848 struct si2157_config si2157_config = {};849 struct lgdt3306a_config lgdt3306a_config = {};850 851 lgdt3306a_config = hauppauge_955q_lgdt3306a_config;852 lgdt3306a_config.fe = &dev->dvb->frontend[0];853 lgdt3306a_config.i2c_adapter = &adapter;854 855 /* perform probe/init/attach */856 client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,857 dev->board.demod_addr,858 &lgdt3306a_config);859 if (!client) {860 result = -ENODEV;861 goto out_free;862 }863 dvb->i2c_client_demod[0] = client;864 865 dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;866 867 /* define general-purpose callback pointer */868 dvb->frontend[0]->callback = cx231xx_tuner_callback;869 870 /* attach tuner */871 si2157_config.fe = dev->dvb->frontend[0];872#ifdef CONFIG_MEDIA_CONTROLLER_DVB873 si2157_config.mdev = dev->media_dev;874#endif875 si2157_config.if_port = 1;876 si2157_config.inversion = true;877 878 /* perform probe/init/attach */879 client = dvb_module_probe("si2157", NULL, tuner_i2c,880 dev->board.tuner_addr,881 &si2157_config);882 if (!client) {883 result = -ENODEV;884 goto out_free;885 }886 dev->cx231xx_reset_analog_tuner = NULL;887 888 dev->dvb->i2c_client_tuner = client;889 break;890 }891 case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:892 case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:893 894 dev_info(dev->dev,895 "%s: looking for demod on i2c bus: %d\n",896 __func__, i2c_adapter_id(tuner_i2c));897 898 dev->dvb->frontend[0] = dvb_attach(mb86a20s_attach,899 &pv_mb86a20s_config,900 demod_i2c);901 902 if (!dev->dvb->frontend[0]) {903 dev_err(dev->dev,904 "Failed to attach mb86a20s demod\n");905 result = -EINVAL;906 goto out_free;907 }908 909 /* define general-purpose callback pointer */910 dvb->frontend[0]->callback = cx231xx_tuner_callback;911 912 dvb_attach(tda18271_attach, dev->dvb->frontend[0],913 dev->board.tuner_addr, tuner_i2c,914 &pv_tda18271_config);915 break;916 917 case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:918 {919 struct si2157_config si2157_config = {};920 struct si2168_config si2168_config = {};921 922 /* attach demodulator chip */923 si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */924 si2168_config.fe = &dev->dvb->frontend[0];925 si2168_config.i2c_adapter = &adapter;926 si2168_config.ts_clock_inv = true;927 928 /* perform probe/init/attach */929 client = dvb_module_probe("si2168", NULL, demod_i2c,930 dev->board.demod_addr,931 &si2168_config);932 if (!client) {933 result = -ENODEV;934 goto out_free;935 }936 dvb->i2c_client_demod[0] = client;937 938 /* attach tuner chip */939 si2157_config.fe = dev->dvb->frontend[0];940#ifdef CONFIG_MEDIA_CONTROLLER_DVB941 si2157_config.mdev = dev->media_dev;942#endif943 si2157_config.if_port = 1;944 si2157_config.inversion = false;945 946 /* perform probe/init/attach */947 client = dvb_module_probe("si2157", NULL, tuner_i2c,948 dev->board.tuner_addr,949 &si2157_config);950 if (!client) {951 result = -ENODEV;952 goto out_free;953 }954 dev->cx231xx_reset_analog_tuner = NULL;955 dev->dvb->i2c_client_tuner = client;956 break;957 }958 case CX231XX_BOARD_ASTROMETA_T2HYBRID:959 {960 struct mn88473_config mn88473_config = {};961 962 /* attach demodulator chip */963 mn88473_config.i2c_wr_max = 16;964 mn88473_config.xtal = 25000000;965 mn88473_config.fe = &dev->dvb->frontend[0];966 967 /* perform probe/init/attach */968 client = dvb_module_probe("mn88473", NULL, demod_i2c,969 dev->board.demod_addr,970 &mn88473_config);971 if (!client) {972 result = -ENODEV;973 goto out_free;974 }975 dvb->i2c_client_demod[0] = client;976 977 /* define general-purpose callback pointer */978 dvb->frontend[0]->callback = cx231xx_tuner_callback;979 980 /* attach tuner chip */981 dvb_attach(r820t_attach, dev->dvb->frontend[0],982 tuner_i2c,983 &astrometa_t2hybrid_r820t_config);984 break;985 }986 case CX231XX_BOARD_HAUPPAUGE_935C:987 {988 struct si2157_config si2157_config = {};989 struct si2168_config si2168_config = {};990 991 /* attach demodulator chip */992 si2168_config.ts_mode = SI2168_TS_SERIAL;993 si2168_config.fe = &dev->dvb->frontend[0];994 si2168_config.i2c_adapter = &adapter;995 si2168_config.ts_clock_inv = true;996 997 /* perform probe/init/attach */998 client = dvb_module_probe("si2168", NULL, demod_i2c,999 dev->board.demod_addr,1000 &si2168_config);1001 if (!client) {1002 result = -ENODEV;1003 goto out_free;1004 }1005 dvb->i2c_client_demod[0] = client;1006 dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;1007 1008 /* define general-purpose callback pointer */1009 dvb->frontend[0]->callback = cx231xx_tuner_callback;1010 1011 /* attach tuner */1012 si2157_config.fe = dev->dvb->frontend[0];1013#ifdef CONFIG_MEDIA_CONTROLLER_DVB1014 si2157_config.mdev = dev->media_dev;1015#endif1016 si2157_config.if_port = 1;1017 si2157_config.inversion = true;1018 1019 /* perform probe/init/attach */1020 client = dvb_module_probe("si2157", NULL, tuner_i2c,1021 dev->board.tuner_addr,1022 &si2157_config);1023 if (!client) {1024 result = -ENODEV;1025 goto out_free;1026 }1027 dev->cx231xx_reset_analog_tuner = NULL;1028 dev->dvb->i2c_client_tuner = client;1029 break;1030 }1031 case CX231XX_BOARD_HAUPPAUGE_975:1032 {1033 struct i2c_adapter *adapter2;1034 struct si2157_config si2157_config = {};1035 struct lgdt3306a_config lgdt3306a_config = {};1036 struct si2168_config si2168_config = {};1037 1038 /* attach first demodulator chip */1039 lgdt3306a_config = hauppauge_955q_lgdt3306a_config;1040 lgdt3306a_config.fe = &dev->dvb->frontend[0];1041 lgdt3306a_config.i2c_adapter = &adapter;1042 1043 /* perform probe/init/attach */1044 client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,1045 dev->board.demod_addr,1046 &lgdt3306a_config);1047 if (!client) {1048 result = -ENODEV;1049 goto out_free;1050 }1051 dvb->i2c_client_demod[0] = client;1052 1053 /* attach second demodulator chip */1054 si2168_config.ts_mode = SI2168_TS_SERIAL;1055 si2168_config.fe = &dev->dvb->frontend[1];1056 si2168_config.i2c_adapter = &adapter2;1057 si2168_config.ts_clock_inv = true;1058 1059 /* perform probe/init/attach */1060 client = dvb_module_probe("si2168", NULL, adapter,1061 dev->board.demod_addr2,1062 &si2168_config);1063 if (!client) {1064 result = -ENODEV;1065 goto out_free;1066 }1067 dvb->i2c_client_demod[1] = client;1068 dvb->frontend[1]->id = 1;1069 1070 /* define general-purpose callback pointer */1071 dvb->frontend[0]->callback = cx231xx_tuner_callback;1072 dvb->frontend[1]->callback = cx231xx_tuner_callback;1073 1074 /* attach tuner */1075 si2157_config.fe = dev->dvb->frontend[0];1076#ifdef CONFIG_MEDIA_CONTROLLER_DVB1077 si2157_config.mdev = dev->media_dev;1078#endif1079 si2157_config.if_port = 1;1080 si2157_config.inversion = true;1081 1082 /* perform probe/init/attach */1083 client = dvb_module_probe("si2157", NULL, adapter,1084 dev->board.tuner_addr,1085 &si2157_config);1086 if (!client) {1087 result = -ENODEV;1088 goto out_free;1089 }1090 dev->cx231xx_reset_analog_tuner = NULL;1091 dvb->i2c_client_tuner = client;1092 1093 dvb->frontend[1]->tuner_priv = dvb->frontend[0]->tuner_priv;1094 1095 memcpy(&dvb->frontend[1]->ops.tuner_ops,1096 &dvb->frontend[0]->ops.tuner_ops,1097 sizeof(struct dvb_tuner_ops));1098 break;1099 }1100 default:1101 dev_err(dev->dev,1102 "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",1103 dev->name);1104 break;1105 }1106 if (!dvb->frontend[0]) {1107 dev_err(dev->dev,1108 "%s/2: frontend initialization failed\n", dev->name);1109 result = -EINVAL;1110 goto out_free;1111 }1112 1113 /* register everything */1114 result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);1115 1116 if (result < 0)1117 goto out_free;1118 1119 1120 dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");1121 1122ret:1123 cx231xx_set_mode(dev, CX231XX_SUSPEND);1124 mutex_unlock(&dev->lock);1125 return result;1126 1127out_free:1128 /* remove I2C tuner */1129 dvb_module_release(dvb->i2c_client_tuner);1130 dvb->i2c_client_tuner = NULL;1131 /* remove I2C demod(s) */1132 dvb_module_release(dvb->i2c_client_demod[1]);1133 dvb->i2c_client_demod[1] = NULL;1134 dvb_module_release(dvb->i2c_client_demod[0]);1135 dvb->i2c_client_demod[0] = NULL;1136 kfree(dvb);1137 dev->dvb = NULL;1138 goto ret;1139}1140 1141static int dvb_fini(struct cx231xx *dev)1142{1143 if (!dev->board.has_dvb) {1144 /* This device does not support the extension */1145 return 0;1146 }1147 1148 if (dev->dvb) {1149 unregister_dvb(dev->dvb);1150 kfree(dev->dvb);1151 dev->dvb = NULL;1152 }1153 1154 return 0;1155}1156 1157static struct cx231xx_ops dvb_ops = {1158 .id = CX231XX_DVB,1159 .name = "Cx231xx dvb Extension",1160 .init = dvb_init,1161 .fini = dvb_fini,1162};1163 1164static int __init cx231xx_dvb_register(void)1165{1166 return cx231xx_register_extension(&dvb_ops);1167}1168 1169static void __exit cx231xx_dvb_unregister(void)1170{1171 cx231xx_unregister_extension(&dvb_ops);1172}1173 1174module_init(cx231xx_dvb_register);1175module_exit(cx231xx_dvb_unregister);1176