diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-29 09:20:15 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-06-17 12:04:49 -0300 |
commit | 8abe4a0a3f6d4217b16a1a3f68cd5c72ab5a058e (patch) | |
tree | 39c885e72ee0ad7600a160fdc8cd632769a7e5d2 /drivers/media/usb/dvb-usb/cxusb.c | |
parent | 7f67d96ab181aff4af2074ba0a56b3f81333e896 (diff) | |
download | linux-8abe4a0a3f6d4217b16a1a3f68cd5c72ab5a058e.tar.gz linux-8abe4a0a3f6d4217b16a1a3f68cd5c72ab5a058e.tar.bz2 linux-8abe4a0a3f6d4217b16a1a3f68cd5c72ab5a058e.zip |
[media] dib7000: export just one symbol
Exporting multiple symbols don't work as it causes compilation
breakages, due to the way dvb_attach() works.
This were reported several times, like:
drivers/built-in.o: In function `cxusb_dualdig4_rev2_tuner_attach':
>> cxusb.c:(.text+0x27d4b5): undefined reference to `dib7000p_get_i2c_master'
drivers/built-in.o: In function `dib7070_set_param_override':
cxusb.c:(.text+0x27d5a5): undefined reference to `dib0070_wbd_offset'
>> cxusb.c:(.text+0x27d5be): undefined reference to `dib7000p_set_wbd_ref'
drivers/built-in.o: In function `dib7070_tuner_reset':
>> cxusb.c:(.text+0x27d5f9): undefined reference to `dib7000p_set_gpio'
drivers/built-in.o: In function `cxusb_dualdig4_rev2_frontend_attach':
>> cxusb.c:(.text+0x27df5c): undefined reference to `dib7000p_i2c_enumeration'
In this specific report:
CONFIG_DVB_USB_CXUSB=y
CONFIG_DVB_DIB7000P=m
But the same type of bug can happen if:
CONFIG_DVB_DIB7000P=m
and one of the bridge drivers is compiled builtin (cxusb, cx23885-dvb
and/or dib0700).
As a bonus, dib7000p won't be loaded anymore if the device uses
a different frontend, reducing the memory footprint.
Tested with Hauppauge Nova-TD (2 frontends).
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/dvb-usb/cxusb.c')
-rw-r--r-- | drivers/media/usb/dvb-usb/cxusb.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index e81a2fd54960..6acde5ee4324 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -1070,8 +1070,15 @@ static struct dib7000p_config cxusb_dualdig4_rev2_config = { .hostbus_diversity = 1, }; +struct dib0700_adapter_state { + int (*set_param_save)(struct dvb_frontend *); + struct dib7000p_ops dib7000p_ops; +}; + static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) { + struct dib0700_adapter_state *state = adap->priv; + if (usb_set_interface(adap->dev->udev, 0, 1) < 0) err("set interface failed"); @@ -1079,14 +1086,17 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); - if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, - &cxusb_dualdig4_rev2_config) < 0) { + if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) + return -ENODEV; + + if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &cxusb_dualdig4_rev2_config) < 0) { printk(KERN_WARNING "Unable to enumerate dib7000p\n"); return -ENODEV; } - adap->fe_adap[0].fe = dvb_attach(dib7000p_init, &adap->dev->i2c_adap, 0x80, - &cxusb_dualdig4_rev2_config); + adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, + &cxusb_dualdig4_rev2_config); if (adap->fe_adap[0].fe == NULL) return -EIO; @@ -1095,7 +1105,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) { - return dib7000p_set_gpio(fe, 8, 0, !onoff); + struct dvb_usb_adapter *adap = fe->dvb->priv; + struct dib0700_adapter_state *state = adap->priv; + + return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff); } static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) @@ -1110,10 +1123,6 @@ static struct dib0070_config dib7070p_dib0070_config = { .clock_khz = 12000, }; -struct dib0700_adapter_state { - int (*set_param_save) (struct dvb_frontend *); -}; - static int dib7070_set_param_override(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -1128,7 +1137,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe) case BAND_UHF: offset = 550; break; } - dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); + state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); return state->set_param_save(fe); } @@ -1136,8 +1145,14 @@ static int dib7070_set_param_override(struct dvb_frontend *fe) static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; - struct i2c_adapter *tun_i2c = - dib7000p_get_i2c_master(adap->fe_adap[0].fe, + struct i2c_adapter *tun_i2c; + + /* + * No need to call dvb7000p_attach here, as it was called + * already, as frontend_attach method is called first, and + * tuner_attach is only called on sucess. + */ + tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, |