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 /drivers/media/video | |
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>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/tuner-core.c | 118 |
1 files changed, 75 insertions, 43 deletions
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); |