diff options
| author | Michael Krufky <mkrufky@linuxtv.org> | 2008-04-29 02:54:19 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-29 17:41:42 -0400 |
| commit | a07c8779fd212dcbad886a2824ef5f8b42cd5a06 (patch) | |
| tree | cabdff372f14dcb24673e3d675affd53564e9a10 | |
| parent | 4407a463dd6afc892aedfbdc4237c42136d9f848 (diff) | |
V4L/DVB (7789): tuner: remove static dependencies on analog tuner sub-modules
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
| -rw-r--r-- | drivers/media/common/tuners/tda8290.c | 8 | ||||
| -rw-r--r-- | drivers/media/video/tuner-core.c | 118 |
2 files changed, 79 insertions, 47 deletions
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 0ebb5b525e57..91204d3f282d 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c | |||
| @@ -578,16 +578,16 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) | |||
| 578 | 578 | ||
| 579 | if ((data == 0x83) || (data == 0x84)) { | 579 | if ((data == 0x83) || (data == 0x84)) { |
| 580 | priv->ver |= TDA18271; | 580 | priv->ver |= TDA18271; |
| 581 | tda18271_attach(fe, priv->tda827x_addr, | 581 | dvb_attach(tda18271_attach, fe, priv->tda827x_addr, |
| 582 | priv->i2c_props.adap, | 582 | priv->i2c_props.adap, &tda829x_tda18271_config); |
| 583 | &tda829x_tda18271_config); | ||
| 584 | } else { | 583 | } else { |
| 585 | if ((data & 0x3c) == 0) | 584 | if ((data & 0x3c) == 0) |
| 586 | priv->ver |= TDA8275; | 585 | priv->ver |= TDA8275; |
| 587 | else | 586 | else |
| 588 | priv->ver |= TDA8275A; | 587 | priv->ver |= TDA8275A; |
| 589 | 588 | ||
| 590 | tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); | 589 | dvb_attach(tda827x_attach, fe, priv->tda827x_addr, |
| 590 | priv->i2c_props.adap, &priv->cfg); | ||
| 591 | priv->cfg.switch_addr = priv->i2c_props.addr; | 591 | priv->cfg.switch_addr = priv->i2c_props.addr; |
| 592 | } | 592 | } |
| 593 | if (fe->ops.tuner_ops.init) | 593 | if (fe->ops.tuner_ops.init) |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6d4b9217ec3e..578414efdb1a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
| @@ -33,6 +33,46 @@ | |||
| 33 | 33 | ||
| 34 | #define PREFIX t->i2c->driver->driver.name | 34 | #define PREFIX t->i2c->driver->driver.name |
| 35 | 35 | ||
| 36 | /** This macro allows us to probe dynamically, avoiding static links */ | ||
| 37 | #ifdef CONFIG_DVB_CORE_ATTACH | ||
| 38 | #define tuner_symbol_probe(FUNCTION, ARGS...) ({ \ | ||
| 39 | int __r = -EINVAL; \ | ||
| 40 | typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ | ||
| 41 | if (__a) { \ | ||
| 42 | __r = (int) __a(ARGS); \ | ||
| 43 | } else { \ | ||
| 44 | printk(KERN_ERR "TUNER: Unable to find " \ | ||
| 45 | "symbol "#FUNCTION"()\n"); \ | ||
| 46 | } \ | ||
| 47 | symbol_put(FUNCTION); \ | ||
| 48 | __r; \ | ||
| 49 | }) | ||
| 50 | |||
| 51 | static void tuner_detach(struct dvb_frontend *fe) | ||
| 52 | { | ||
| 53 | if (fe->ops.tuner_ops.release) { | ||
| 54 | fe->ops.tuner_ops.release(fe); | ||
| 55 | symbol_put_addr(fe->ops.tuner_ops.release); | ||
| 56 | } | ||
| 57 | if (fe->ops.analog_ops.release) { | ||
| 58 | fe->ops.analog_ops.release(fe); | ||
| 59 | symbol_put_addr(fe->ops.analog_ops.release); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | #else | ||
| 63 | #define tuner_symbol_probe(FUNCTION, ARGS...) ({ \ | ||
| 64 | FUNCTION(ARGS); \ | ||
| 65 | }) | ||
| 66 | |||
| 67 | static void tuner_detach(struct dvb_frontend *fe) | ||
| 68 | { | ||
| 69 | if (fe->ops.tuner_ops.release) | ||
| 70 | fe->ops.tuner_ops.release(fe); | ||
| 71 | if (fe->ops.analog_ops.release) | ||
| 72 | fe->ops.analog_ops.release(fe); | ||
| 73 | } | ||
| 74 | #endif | ||
| 75 | |||
| 36 | struct tuner { | 76 | struct tuner { |
| 37 | /* device */ | 77 | /* device */ |
| 38 | struct dvb_frontend fe; | 78 | struct dvb_frontend fe; |
| @@ -139,22 +179,6 @@ static void fe_set_params(struct dvb_frontend *fe, | |||
| 139 | fe_tuner_ops->set_analog_params(fe, params); | 179 | fe_tuner_ops->set_analog_params(fe, params); |
| 140 | } | 180 | } |
| 141 | 181 | ||
| 142 | static void fe_release(struct dvb_frontend *fe) | ||
| 143 | { | ||
| 144 | if (fe->ops.tuner_ops.release) | ||
| 145 | fe->ops.tuner_ops.release(fe); | ||
| 146 | |||
| 147 | /* DO NOT kfree(fe->analog_demod_priv) | ||
| 148 | * | ||
| 149 | * If we are in this function, analog_demod_priv contains a pointer | ||
| 150 | * to struct tuner *t. This will be kfree'd in tuner_detach(). | ||
| 151 | * | ||
| 152 | * Otherwise, fe->ops.analog_demod_ops->release will | ||
| 153 | * handle the cleanup for analog demodulator modules. | ||
| 154 | */ | ||
| 155 | fe->analog_demod_priv = NULL; | ||
| 156 | } | ||
| 157 | |||
| 158 | static void fe_standby(struct dvb_frontend *fe) | 182 | static void fe_standby(struct dvb_frontend *fe) |
| 159 | { | 183 | { |
| 160 | struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; | 184 | struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; |
| @@ -191,7 +215,6 @@ static void tuner_status(struct dvb_frontend *fe); | |||
| 191 | static struct analog_demod_ops tuner_core_ops = { | 215 | static struct analog_demod_ops tuner_core_ops = { |
| 192 | .set_params = fe_set_params, | 216 | .set_params = fe_set_params, |
| 193 | .standby = fe_standby, | 217 | .standby = fe_standby, |
| 194 | .release = fe_release, | ||
| 195 | .has_signal = fe_has_signal, | 218 | .has_signal = fe_has_signal, |
| 196 | .set_config = fe_set_config, | 219 | .set_config = fe_set_config, |
| 197 | .tuner_status = tuner_status | 220 | .tuner_status = tuner_status |
| @@ -323,7 +346,8 @@ static void attach_tda829x(struct tuner *t) | |||
| 323 | .lna_cfg = t->config, | 346 | .lna_cfg = t->config, |
| 324 | .tuner_callback = t->tuner_callback, | 347 | .tuner_callback = t->tuner_callback, |
| 325 | }; | 348 | }; |
| 326 | tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); | 349 | dvb_attach(tda829x_attach, |
| 350 | &t->fe, t->i2c->adapter, t->i2c->addr, &cfg); | ||
| 327 | } | 351 | } |
| 328 | 352 | ||
| 329 | static struct xc5000_config xc5000_cfg; | 353 | static struct xc5000_config xc5000_cfg; |
| @@ -356,12 +380,13 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 356 | } | 380 | } |
| 357 | 381 | ||
| 358 | /* discard private data, in case set_type() was previously called */ | 382 | /* discard private data, in case set_type() was previously called */ |
| 359 | if (analog_ops->release) | 383 | tuner_detach(&t->fe); |
| 360 | analog_ops->release(&t->fe); | 384 | t->fe.analog_demod_priv = NULL; |
| 361 | 385 | ||
| 362 | switch (t->type) { | 386 | switch (t->type) { |
| 363 | case TUNER_MT2032: | 387 | case TUNER_MT2032: |
| 364 | microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr); | 388 | dvb_attach(microtune_attach, |
| 389 | &t->fe, t->i2c->adapter, t->i2c->addr); | ||
| 365 | break; | 390 | break; |
| 366 | case TUNER_PHILIPS_TDA8290: | 391 | case TUNER_PHILIPS_TDA8290: |
| 367 | { | 392 | { |
| @@ -369,12 +394,14 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 369 | break; | 394 | break; |
| 370 | } | 395 | } |
| 371 | case TUNER_TEA5767: | 396 | case TUNER_TEA5767: |
| 372 | if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr)) | 397 | if (!dvb_attach(tea5767_attach, &t->fe, |
| 398 | t->i2c->adapter, t->i2c->addr)) | ||
| 373 | goto attach_failed; | 399 | goto attach_failed; |
| 374 | t->mode_mask = T_RADIO; | 400 | t->mode_mask = T_RADIO; |
| 375 | break; | 401 | break; |
| 376 | case TUNER_TEA5761: | 402 | case TUNER_TEA5761: |
| 377 | if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr)) | 403 | if (!dvb_attach(tea5761_attach, &t->fe, |
| 404 | t->i2c->adapter, t->i2c->addr)) | ||
| 378 | goto attach_failed; | 405 | goto attach_failed; |
| 379 | t->mode_mask = T_RADIO; | 406 | t->mode_mask = T_RADIO; |
| 380 | break; | 407 | break; |
| @@ -388,8 +415,8 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 388 | buffer[2] = 0x86; | 415 | buffer[2] = 0x86; |
| 389 | buffer[3] = 0x54; | 416 | buffer[3] = 0x54; |
| 390 | i2c_master_send(c, buffer, 4); | 417 | i2c_master_send(c, buffer, 4); |
| 391 | if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, | 418 | if (!dvb_attach(simple_tuner_attach, &t->fe, |
| 392 | t->type)) | 419 | t->i2c->adapter, t->i2c->addr, t->type)) |
| 393 | goto attach_failed; | 420 | goto attach_failed; |
| 394 | break; | 421 | break; |
| 395 | case TUNER_PHILIPS_TD1316: | 422 | case TUNER_PHILIPS_TD1316: |
| @@ -397,9 +424,9 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 397 | buffer[1] = 0xdc; | 424 | buffer[1] = 0xdc; |
| 398 | buffer[2] = 0x86; | 425 | buffer[2] = 0x86; |
| 399 | buffer[3] = 0xa4; | 426 | buffer[3] = 0xa4; |
| 400 | i2c_master_send(c,buffer,4); | 427 | i2c_master_send(c, buffer, 4); |
| 401 | if (!simple_tuner_attach(&t->fe, t->i2c->adapter, | 428 | if (!dvb_attach(simple_tuner_attach, &t->fe, |
| 402 | t->i2c->addr, t->type)) | 429 | t->i2c->adapter, t->i2c->addr, t->type)) |
| 403 | goto attach_failed; | 430 | goto attach_failed; |
| 404 | break; | 431 | break; |
| 405 | case TUNER_XC2028: | 432 | case TUNER_XC2028: |
| @@ -409,12 +436,13 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 409 | .i2c_addr = t->i2c->addr, | 436 | .i2c_addr = t->i2c->addr, |
| 410 | .callback = t->tuner_callback, | 437 | .callback = t->tuner_callback, |
| 411 | }; | 438 | }; |
| 412 | if (!xc2028_attach(&t->fe, &cfg)) | 439 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) |
| 413 | goto attach_failed; | 440 | goto attach_failed; |
| 414 | break; | 441 | break; |
| 415 | } | 442 | } |
| 416 | case TUNER_TDA9887: | 443 | case TUNER_TDA9887: |
| 417 | tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr); | 444 | dvb_attach(tda9887_attach, |
| 445 | &t->fe, t->i2c->adapter, t->i2c->addr); | ||
| 418 | break; | 446 | break; |
| 419 | case TUNER_XC5000: | 447 | case TUNER_XC5000: |
| 420 | { | 448 | { |
| @@ -424,7 +452,8 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 424 | xc5000_cfg.if_khz = 5380; | 452 | xc5000_cfg.if_khz = 5380; |
| 425 | xc5000_cfg.priv = c->adapter->algo_data; | 453 | xc5000_cfg.priv = c->adapter->algo_data; |
| 426 | xc5000_cfg.tuner_callback = t->tuner_callback; | 454 | xc5000_cfg.tuner_callback = t->tuner_callback; |
| 427 | if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) | 455 | if (!dvb_attach(xc5000_attach, |
| 456 | &t->fe, t->i2c->adapter, &xc5000_cfg)) | ||
| 428 | goto attach_failed; | 457 | goto attach_failed; |
| 429 | 458 | ||
| 430 | xc_tuner_ops = &t->fe.ops.tuner_ops; | 459 | xc_tuner_ops = &t->fe.ops.tuner_ops; |
| @@ -433,8 +462,8 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 433 | break; | 462 | break; |
| 434 | } | 463 | } |
| 435 | default: | 464 | default: |
| 436 | if (!simple_tuner_attach(&t->fe, t->i2c->adapter, | 465 | if (!dvb_attach(simple_tuner_attach, &t->fe, |
| 437 | t->i2c->addr, t->type)) | 466 | t->i2c->adapter, t->i2c->addr, t->type)) |
| 438 | goto attach_failed; | 467 | goto attach_failed; |
| 439 | 468 | ||
| 440 | break; | 469 | break; |
| @@ -442,12 +471,14 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 442 | 471 | ||
| 443 | if ((NULL == analog_ops->set_params) && | 472 | if ((NULL == analog_ops->set_params) && |
| 444 | (fe_tuner_ops->set_analog_params)) { | 473 | (fe_tuner_ops->set_analog_params)) { |
| 474 | |||
| 445 | strlcpy(t->i2c->name, fe_tuner_ops->info.name, | 475 | strlcpy(t->i2c->name, fe_tuner_ops->info.name, |
| 446 | sizeof(t->i2c->name)); | 476 | sizeof(t->i2c->name)); |
| 447 | 477 | ||
| 448 | t->fe.analog_demod_priv = t; | 478 | t->fe.analog_demod_priv = t; |
| 449 | memcpy(analog_ops, &tuner_core_ops, | 479 | memcpy(analog_ops, &tuner_core_ops, |
| 450 | sizeof(struct analog_demod_ops)); | 480 | sizeof(struct analog_demod_ops)); |
| 481 | |||
| 451 | } else { | 482 | } else { |
| 452 | strlcpy(t->i2c->name, analog_ops->info.name, | 483 | strlcpy(t->i2c->name, analog_ops->info.name, |
| 453 | sizeof(t->i2c->name)); | 484 | sizeof(t->i2c->name)); |
| @@ -645,8 +676,8 @@ static void tuner_status(struct dvb_frontend *fe) | |||
| 645 | { | 676 | { |
| 646 | struct tuner *t = fe->analog_demod_priv; | 677 | struct tuner *t = fe->analog_demod_priv; |
| 647 | unsigned long freq, freq_fraction; | 678 | unsigned long freq, freq_fraction; |
| 648 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 679 | struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; |
| 649 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 680 | struct analog_demod_ops *analog_ops = &fe->ops.analog_ops; |
| 650 | const char *p; | 681 | const char *p; |
| 651 | 682 | ||
| 652 | switch (t->mode) { | 683 | switch (t->mode) { |
| @@ -1113,8 +1144,9 @@ static int tuner_probe(struct i2c_client *client) | |||
| 1113 | if (!no_autodetect) { | 1144 | if (!no_autodetect) { |
| 1114 | switch (client->addr) { | 1145 | switch (client->addr) { |
| 1115 | case 0x10: | 1146 | case 0x10: |
| 1116 | if (tea5761_autodetection(t->i2c->adapter, | 1147 | if (tuner_symbol_probe(tea5761_autodetection, |
| 1117 | t->i2c->addr) >= 0) { | 1148 | t->i2c->adapter, |
| 1149 | t->i2c->addr) >= 0) { | ||
| 1118 | t->type = TUNER_TEA5761; | 1150 | t->type = TUNER_TEA5761; |
| 1119 | t->mode_mask = T_RADIO; | 1151 | t->mode_mask = T_RADIO; |
| 1120 | t->mode = T_STANDBY; | 1152 | t->mode = T_STANDBY; |
| @@ -1133,8 +1165,8 @@ static int tuner_probe(struct i2c_client *client) | |||
| 1133 | case 0x4b: | 1165 | case 0x4b: |
| 1134 | /* If chip is not tda8290, don't register. | 1166 | /* If chip is not tda8290, don't register. |
| 1135 | since it can be tda9887*/ | 1167 | since it can be tda9887*/ |
| 1136 | if (tda829x_probe(t->i2c->adapter, | 1168 | if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter, |
| 1137 | t->i2c->addr) == 0) { | 1169 | t->i2c->addr) == 0) { |
| 1138 | tuner_dbg("tda829x detected\n"); | 1170 | tuner_dbg("tda829x detected\n"); |
| 1139 | } else { | 1171 | } else { |
| 1140 | /* Default is being tda9887 */ | 1172 | /* Default is being tda9887 */ |
| @@ -1146,7 +1178,8 @@ static int tuner_probe(struct i2c_client *client) | |||
| 1146 | } | 1178 | } |
| 1147 | break; | 1179 | break; |
| 1148 | case 0x60: | 1180 | case 0x60: |
| 1149 | if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr) | 1181 | if (tuner_symbol_probe(tea5767_autodetection, |
| 1182 | t->i2c->adapter, t->i2c->addr) | ||
| 1150 | != EINVAL) { | 1183 | != EINVAL) { |
| 1151 | t->type = TUNER_TEA5767; | 1184 | t->type = TUNER_TEA5767; |
| 1152 | t->mode_mask = T_RADIO; | 1185 | t->mode_mask = T_RADIO; |
| @@ -1235,10 +1268,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) | |||
| 1235 | static int tuner_remove(struct i2c_client *client) | 1268 | static int tuner_remove(struct i2c_client *client) |
| 1236 | { | 1269 | { |
| 1237 | struct tuner *t = i2c_get_clientdata(client); | 1270 | struct tuner *t = i2c_get_clientdata(client); |
| 1238 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | ||
| 1239 | 1271 | ||
| 1240 | if (analog_ops->release) | 1272 | tuner_detach(&t->fe); |
| 1241 | analog_ops->release(&t->fe); | 1273 | t->fe.analog_demod_priv = NULL; |
| 1242 | 1274 | ||
| 1243 | list_del(&t->list); | 1275 | list_del(&t->list); |
| 1244 | kfree(t); | 1276 | kfree(t); |
