Commit 8abe4a0a authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[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: default avatarFengguang Wu <fengguang.wu@intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 7f67d96a
......@@ -401,7 +401,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
return 0;
}
int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
{
struct dib7000p_state *state = demod->demodulator_priv;
if (value > 4095)
......@@ -409,9 +409,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
state->wbd_ref = value;
return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
}
EXPORT_SYMBOL(dib7000p_set_wbd_ref);
int dib7000p_get_agc_values(struct dvb_frontend *fe,
static int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
struct dib7000p_state *state = fe->demodulator_priv;
......@@ -427,14 +426,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
return 0;
}
EXPORT_SYMBOL(dib7000p_get_agc_values);
int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
struct dib7000p_state *state = fe->demodulator_priv;
return dib7000p_write_word(state, 108, v);
}
EXPORT_SYMBOL(dib7000p_set_agc1_min);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
......@@ -478,7 +475,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
return internal;
}
int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
......@@ -513,7 +510,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config
}
return -EIO;
}
EXPORT_SYMBOL(dib7000p_update_pll);
static int dib7000p_reset_gpio(struct dib7000p_state *st)
{
......@@ -546,12 +542,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
return 0;
}
int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
{
struct dib7000p_state *state = demod->demodulator_priv;
return dib7000p_cfg_gpio(state, num, dir, val);
}
EXPORT_SYMBOL(dib7000p_set_gpio);
static u16 dib7000p_defaults[] = {
// auto search configuration
......@@ -934,7 +929,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state)
}
u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
struct dib7000p_state *state = fe->demodulator_priv;
switch (op) {
......@@ -950,7 +945,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
dib7000p_set_bandwidth(state, state->current_bandwidth);
return state->timf;
}
EXPORT_SYMBOL(dib7000p_ctrl_timf);
static void dib7000p_set_channel(struct dib7000p_state *state,
struct dtv_frontend_properties *ch, u8 seq)
......@@ -1643,7 +1637,7 @@ static void dib7000p_release(struct dvb_frontend *demod)
kfree(st);
}
int dib7000pc_detection(struct i2c_adapter *i2c_adap)
static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
u8 *tx, *rx;
struct i2c_msg msg[2] = {
......@@ -1688,16 +1682,14 @@ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
kfree(tx);
return ret;
}
EXPORT_SYMBOL(dib7000pc_detection);
struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
{
struct dib7000p_state *st = demod->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
EXPORT_SYMBOL(dib7000p_get_i2c_master);
int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val = dib7000p_read_word(state, 235) & 0xffef;
......@@ -1705,17 +1697,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("PID filter enabled %d", onoff);
return dib7000p_write_word(state, 235, val);
}
EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
}
EXPORT_SYMBOL(dib7000p_pid_filter);
int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
struct dib7000p_state *dpst;
int k = 0;
......@@ -1774,7 +1764,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
kfree(dpst);
return 0;
}
EXPORT_SYMBOL(dib7000p_i2c_enumeration);
static const s32 lut_1000ln_mant[] = {
6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
......@@ -2032,12 +2021,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = {
.functionality = dib7000p_i2c_func,
};
struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib7000p_state *st = fe->demodulator_priv;
return &st->dib7090_tuner_adap;
}
EXPORT_SYMBOL(dib7090_get_i2c_tuner);
static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
{
......@@ -2329,7 +2317,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
return ret;
}
int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 en_cur_state;
......@@ -2352,15 +2340,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
EXPORT_SYMBOL(dib7090_tuner_sleep);
int dib7090_get_adc_power(struct dvb_frontend *fe)
static int dib7090_get_adc_power(struct dvb_frontend *fe)
{
return dib7000p_get_adc_power(fe);
}
EXPORT_SYMBOL(dib7090_get_adc_power);
int dib7090_slave_reset(struct dvb_frontend *fe)
static int dib7090_slave_reset(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg;
......@@ -2371,10 +2357,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe)
dib7000p_write_word(state, 1032, 0xffff);
return 0;
}
EXPORT_SYMBOL(dib7090_slave_reset);
static struct dvb_frontend_ops dib7000p_ops;
struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
struct dvb_frontend *demod;
struct dib7000p_state *st;
......@@ -2434,7 +2419,32 @@ struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, st
kfree(st);
return NULL;
}
EXPORT_SYMBOL(dib7000p_init);
void *dib7000p_attach(struct dib7000p_ops *ops)
{
if (!ops)
return NULL;
ops->slave_reset = dib7090_slave_reset;
ops->get_adc_power = dib7090_get_adc_power;
ops->dib7000pc_detection = dib7000pc_detection;
ops->get_i2c_tuner = dib7090_get_i2c_tuner;
ops->tuner_sleep = dib7090_tuner_sleep;
ops->init = dib7000p_init;
ops->set_agc1_min = dib7000p_set_agc1_min;
ops->set_gpio = dib7000p_set_gpio;
ops->i2c_enumeration = dib7000p_i2c_enumeration;
ops->pid_filter = dib7000p_pid_filter;
ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
ops->get_i2c_master = dib7000p_get_i2c_master;
ops->update_pll = dib7000p_update_pll;
ops->ctrl_timf = dib7000p_ctrl_timf;
ops->get_agc_values = dib7000p_get_agc_values;
ops->set_wbd_ref = dib7000p_set_wbd_ref;
return ops;
}
EXPORT_SYMBOL(dib7000p_attach);
static struct dvb_frontend_ops dib7000p_ops = {
.delsys = { SYS_DVBT },
......
......@@ -46,121 +46,34 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
extern struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
extern int dib7090_get_adc_power(struct dvb_frontend *fe);
extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
extern int dib7090_slave_reset(struct dvb_frontend *fe);
extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
struct dib7000p_ops {
int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
int (*get_agc_values)(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
#else
static inline struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
int (*get_adc_power)(struct dvb_frontend *fe);
int (*slave_reset)(struct dvb_frontend *fe);
struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
};
static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
void *dib7000p_attach(struct dib7000p_ops *ops);
#else
static inline void *dib7000p_attach(struct dib7000p_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline int dib7090_slave_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
#endif
#endif
......@@ -748,6 +748,7 @@ static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
static int dvb_register(struct cx23885_tsport *port)
{
struct dib7000p_ops dib7000p_ops;
struct cx23885_dev *dev = port->dev;
struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
......@@ -925,8 +926,11 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1400:
i2c_bus = &dev->i2c_bus[0];
fe0->dvb.frontend = dvb_attach(dib7000p_init,
&i2c_bus->i2c_adap,
if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
return -ENODEV;
fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
0x12, &hauppauge_hvr1400_dib7000_config);
if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
......
......@@ -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,
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment