#include <media/tuner.h>
#include <media/tuner-types.h>
#include <media/v4l2-common.h>
-#include "tuner-driver.h"
+#include <media/v4l2-i2c-drv-legacy.h>
#include "mt20xx.h"
#include "tda8290.h"
#include "tea5761.h"
#include "tuner-xc2028.h"
#include "tuner-simple.h"
#include "tda9887.h"
+#include "xc5000.h"
#define UNSET (-1U)
-#define PREFIX "tuner "
+#define PREFIX t->i2c->driver->driver.name
+
+struct tuner {
+ /* device */
+ struct dvb_frontend fe;
+ struct i2c_client *i2c;
+ struct list_head list;
+ unsigned int using_v4l2:1;
+
+ /* keep track of the current settings */
+ v4l2_std_id std;
+ unsigned int tv_freq;
+ unsigned int radio_freq;
+ unsigned int audmode;
+
+ unsigned int mode;
+ unsigned int mode_mask; /* Combination of allowable modes */
+
+ unsigned int type; /* chip type id */
+ unsigned int config;
+ int (*tuner_callback) (void *dev, int command, int arg);
+};
/* standard i2c insmod options */
static unsigned short normal_i2c[] = {
I2C_CLIENT_INSMOD;
/* insmod options used at init time => read/only */
-static unsigned int addr = 0;
-static unsigned int no_autodetect = 0;
-static unsigned int show_i2c = 0;
+static unsigned int addr;
+static unsigned int no_autodetect;
+static unsigned int show_i2c;
/* insmod options used at runtime => read/write */
-int tuner_debug = 0;
+static int tuner_debug;
+
+#define tuner_warn(fmt, arg...) do { \
+ printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
+ i2c_adapter_id(t->i2c->adapter), \
+ t->i2c->addr, ##arg); \
+ } while (0)
+
+#define tuner_info(fmt, arg...) do { \
+ printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \
+ i2c_adapter_id(t->i2c->adapter), \
+ t->i2c->addr, ##arg); \
+ } while (0)
+
+#define tuner_err(fmt, arg...) do { \
+ printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \
+ i2c_adapter_id(t->i2c->adapter), \
+ t->i2c->addr, ##arg); \
+ } while (0)
+
+#define tuner_dbg(fmt, arg...) do { \
+ if (tuner_debug) \
+ printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \
+ i2c_adapter_id(t->i2c->adapter), \
+ t->i2c->addr, ##arg); \
+ } while (0)
+
+/* ------------------------------------------------------------------------ */
static unsigned int tv_range[2] = { 44, 958 };
static unsigned int radio_range[2] = { 65, 108 };
MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
MODULE_LICENSE("GPL");
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
/* ---------------------------------------------------------------------- */
-static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq)
+static void fe_set_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
{
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
struct tuner *t = fe->analog_demod_priv;
- struct analog_parameters params = {
- .frequency = freq,
- .mode = t->mode,
- .audmode = t->audmode,
- .std = t->std
- };
-
if (NULL == fe_tuner_ops->set_analog_params) {
tuner_warn("Tuner frontend module has no way to set freq\n");
return;
}
- fe_tuner_ops->set_analog_params(fe, ¶ms);
+ fe_tuner_ops->set_analog_params(fe, params);
}
static void fe_release(struct dvb_frontend *fe)
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
- fe->ops.analog_demod_ops = NULL;
-
/* DO NOT kfree(fe->analog_demod_priv)
*
* If we are in this function, analog_demod_priv contains a pointer
return strength;
}
+static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
+{
+ struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
+ struct tuner *t = fe->analog_demod_priv;
+
+ if (fe_tuner_ops->set_config)
+ return fe_tuner_ops->set_config(fe, priv_cfg);
+
+ tuner_warn("Tuner frontend module has no way to set config\n");
+
+ return 0;
+}
+
static void tuner_status(struct dvb_frontend *fe);
-static struct analog_tuner_ops tuner_core_ops = {
- .set_tv_freq = fe_set_freq,
- .set_radio_freq = fe_set_freq,
+static struct analog_demod_ops tuner_core_ops = {
+ .set_params = fe_set_params,
.standby = fe_standby,
.release = fe_release,
.has_signal = fe_has_signal,
+ .set_config = fe_set_config,
.tuner_status = tuner_status
};
static void set_tv_freq(struct i2c_client *c, unsigned int freq)
{
struct tuner *t = i2c_get_clientdata(c);
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+ struct analog_parameters params = {
+ .mode = t->mode,
+ .audmode = t->audmode,
+ .std = t->std
+ };
if (t->type == UNSET) {
tuner_warn ("tuner type not set\n");
return;
}
- if ((NULL == ops) || (NULL == ops->set_tv_freq)) {
+ if (NULL == analog_ops->set_params) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
else
freq = tv_range[1] * 16;
}
- ops->set_tv_freq(&t->fe, freq);
+ params.frequency = freq;
+
+ analog_ops->set_params(&t->fe, ¶ms);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tuner *t = i2c_get_clientdata(c);
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+ struct analog_parameters params = {
+ .mode = t->mode,
+ .audmode = t->audmode,
+ .std = t->std
+ };
if (t->type == UNSET) {
tuner_warn ("tuner type not set\n");
return;
}
- if ((NULL == ops) || (NULL == ops->set_radio_freq)) {
+ if (NULL == analog_ops->set_params) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
else
freq = radio_range[1] * 16000;
}
+ params.frequency = freq;
- ops->set_radio_freq(&t->fe, freq);
+ analog_ops->set_params(&t->fe, ¶ms);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f)))
return;
+ /* We already know that the XC5000 can only be located at
+ * i2c address 0x61, 0x62, 0x63 or 0x64 */
+ if ((t->type == TUNER_XC5000) &&
+ ((t->i2c->addr <= 0x64)) && (t->i2c->addr >= 0x61))
+ return;
+
tuner_warn("====================== WARNING! ======================\n");
tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n");
tuner_warn("will soon be dropped. This message indicates that your\n");
tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n");
tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
- t->i2c->adapter->name, t->i2c->addr, t->type,
- tuners[t->type].name);
+ t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
tuner_warn("====================== WARNING! ======================\n");
}
-static void attach_simple_tuner(struct tuner *t)
+static void attach_tda829x(struct tuner *t)
{
- struct simple_tuner_config cfg = {
- .type = t->type,
- .tun = &tuners[t->type]
+ struct tda829x_config cfg = {
+ .lna_cfg = t->config,
+ .tuner_callback = t->tuner_callback,
};
- simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+ tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
}
+static struct xc5000_config xc5000_cfg;
+
static void set_type(struct i2c_client *c, unsigned int type,
unsigned int new_mode_mask, unsigned int new_config,
int (*tuner_callback) (void *dev, int command,int arg))
{
struct tuner *t = i2c_get_clientdata(c);
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
unsigned char buffer[4];
if (type == UNSET || type == TUNER_ABSENT) {
return;
}
- if (type >= tuner_count) {
- tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
- return;
- }
-
t->type = type;
t->config = new_config;
if (tuner_callback != NULL) {
}
/* discard private data, in case set_type() was previously called */
- if (ops && ops->release)
- ops->release(&t->fe);
+ if (analog_ops->release)
+ analog_ops->release(&t->fe);
switch (t->type) {
case TUNER_MT2032:
break;
case TUNER_PHILIPS_TDA8290:
{
- tda829x_attach(t);
+ attach_tda829x(t);
break;
}
case TUNER_TEA5767:
buffer[2] = 0x86;
buffer[3] = 0x54;
i2c_master_send(c, buffer, 4);
- attach_simple_tuner(t);
+ if (simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
+ t->type) == NULL) {
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+ return;
+ }
break;
case TUNER_PHILIPS_TD1316:
buffer[0] = 0x0b;
buffer[2] = 0x86;
buffer[3] = 0xa4;
i2c_master_send(c,buffer,4);
- attach_simple_tuner(t);
+ if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+ t->i2c->addr, t->type) == NULL) {
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+ return;
+ }
break;
case TUNER_XC2028:
{
- int rc=xc2028_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
- &c->dev, c->adapter->algo_data,
- t->tuner_callback);
- if (rc<0) {
+ struct xc2028_config cfg = {
+ .i2c_adap = t->i2c->adapter,
+ .i2c_addr = t->i2c->addr,
+ .video_dev = c->adapter->algo_data,
+ .callback = t->tuner_callback,
+ };
+ if (!xc2028_attach(&t->fe, &cfg)) {
t->type = TUNER_ABSENT;
t->mode_mask = T_UNINITIALIZED;
return;
break;
}
case TUNER_TDA9887:
- tda9887_attach(t);
+ tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+ break;
+ case TUNER_XC5000:
+ xc5000_cfg.i2c_address = t->i2c->addr;
+ xc5000_cfg.if_khz = 5380;
+ xc5000_cfg.priv = c->adapter->algo_data;
+ xc5000_cfg.tuner_callback = t->tuner_callback;
+ if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+ return;
+ }
+ {
+ struct dvb_tuner_ops *xc_tuner_ops;
+ xc_tuner_ops = &t->fe.ops.tuner_ops;
+ if(xc_tuner_ops->init != NULL)
+ xc_tuner_ops->init(&t->fe);
+ }
break;
default:
- attach_simple_tuner(t);
+ if (simple_tuner_attach(&t->fe, t->i2c->adapter,
+ t->i2c->addr, t->type) == NULL) {
+ t->type = TUNER_ABSENT;
+ t->mode_mask = T_UNINITIALIZED;
+ return;
+ }
break;
}
- ops = t->fe.ops.analog_demod_ops;
-
- if (((NULL == ops) ||
- ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) &&
+ if ((NULL == analog_ops->set_params) &&
(fe_tuner_ops->set_analog_params)) {
strlcpy(t->i2c->name, fe_tuner_ops->info.name,
sizeof(t->i2c->name));
- t->fe.ops.analog_demod_ops = &tuner_core_ops;
t->fe.analog_demod_priv = t;
+ memcpy(analog_ops, &tuner_core_ops,
+ sizeof(struct analog_demod_ops));
+ } else {
+ strlcpy(t->i2c->name, analog_ops->info.name,
+ sizeof(t->i2c->name));
}
tuner_dbg("type set to %s\n", t->i2c->name);
struct tuner *t = fe->analog_demod_priv;
unsigned long freq, freq_fraction;
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
const char *p;
switch (t->mode) {
if (tuner_status & TUNER_STATUS_STEREO)
tuner_info("Stereo: yes\n");
}
- if (ops) {
- if (ops->has_signal)
- tuner_info("Signal strength: %d\n",
- ops->has_signal(fe));
- if (ops->is_stereo)
- tuner_info("Stereo: %s\n",
- ops->is_stereo(fe) ? "yes" : "no");
- }
+ if (analog_ops->has_signal)
+ tuner_info("Signal strength: %d\n",
+ analog_ops->has_signal(fe));
+ if (analog_ops->is_stereo)
+ tuner_info("Stereo: %s\n",
+ analog_ops->is_stereo(fe) ? "yes" : "no");
}
/* ---------------------------------------------------------------------- */
static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
{
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
if (mode == t->mode)
return 0;
if (check_mode(t, cmd) == EINVAL) {
t->mode = T_STANDBY;
- if (ops && ops->standby)
- ops->standby(&t->fe);
+ if (analog_ops->standby)
+ analog_ops->standby(&t->fe);
return EINVAL;
}
return 0;
{
struct tuner *t = i2c_get_clientdata(client);
struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
if (tuner_debug>1)
v4l_i2c_print_ioctl(client,cmd);
if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
return 0;
t->mode = T_STANDBY;
- if (ops && ops->standby)
- ops->standby(&t->fe);
+ if (analog_ops->standby)
+ analog_ops->standby(&t->fe);
break;
#ifdef CONFIG_VIDEO_V4L1
case VIDIOCSAUDIO:
else
vt->flags &= ~VIDEO_TUNER_STEREO_ON;
} else {
- if (ops && ops->is_stereo) {
- if (ops->is_stereo(&t->fe))
+ if (analog_ops->is_stereo) {
+ if (analog_ops->is_stereo(&t->fe))
vt->flags |=
VIDEO_TUNER_STEREO_ON;
else
~VIDEO_TUNER_STEREO_ON;
}
}
- if (ops && ops->has_signal)
- vt->signal = ops->has_signal(&t->fe);
+ if (analog_ops->has_signal)
+ vt->signal =
+ analog_ops->has_signal(&t->fe);
vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */
fe_tuner_ops->get_status(&t->fe, &tuner_status);
va->mode = (tuner_status & TUNER_STATUS_STEREO)
? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
- } else if (ops && ops->is_stereo)
- va->mode = ops->is_stereo(&t->fe)
+ } else if (analog_ops->is_stereo)
+ va->mode = analog_ops->is_stereo(&t->fe)
? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
}
return 0;
#endif
case TUNER_SET_CONFIG:
{
- struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
struct v4l2_priv_tun_config *cfg = arg;
if (t->type != cfg->tuner)
break;
- if (t->type == TUNER_TDA9887) {
- t->tda9887_config = *(unsigned int *)cfg->priv;
- set_freq(client, t->tv_freq);
+ if (analog_ops->set_config) {
+ analog_ops->set_config(&t->fe, cfg->priv);
break;
}
- if (NULL == fe_tuner_ops->set_config) {
- tuner_warn("Tuner frontend module has no way to "
- "set config\n");
- break;
- }
- fe_tuner_ops->set_config(&t->fe, cfg->priv);
-
+ tuner_dbg("Tuner frontend module has no way to set config\n");
break;
}
/* --- v4l ioctls --- */
switch_v4l2();
tuner->type = t->mode;
- if (ops && ops->get_afc)
- tuner->afc = ops->get_afc(&t->fe);
+ if (analog_ops->get_afc)
+ tuner->afc = analog_ops->get_afc(&t->fe);
if (t->mode == V4L2_TUNER_ANALOG_TV)
tuner->capability |= V4L2_TUNER_CAP_NORM;
if (t->mode != V4L2_TUNER_RADIO) {
V4L2_TUNER_SUB_STEREO :
V4L2_TUNER_SUB_MONO;
} else {
- if (ops && ops->is_stereo) {
+ if (analog_ops->is_stereo) {
tuner->rxsubchans =
- ops->is_stereo(&t->fe) ?
+ analog_ops->is_stereo(&t->fe) ?
V4L2_TUNER_SUB_STEREO :
V4L2_TUNER_SUB_MONO;
}
}
- if (ops && ops->has_signal)
- tuner->signal = ops->has_signal(&t->fe);
+ if (analog_ops->has_signal)
+ tuner->signal = analog_ops->has_signal(&t->fe);
tuner->capability |=
V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
tuner->audmode = t->audmode;
break;
}
case VIDIOC_LOG_STATUS:
- if (ops && ops->tuner_status)
- ops->tuner_status(&t->fe);
+ if (analog_ops->tuner_status)
+ analog_ops->tuner_status(&t->fe);
break;
}
static int tuner_suspend(struct i2c_client *c, pm_message_t state)
{
- struct tuner *t = i2c_get_clientdata (c);
+ struct tuner *t = i2c_get_clientdata(c);
- tuner_dbg ("suspend\n");
+ tuner_dbg("suspend\n");
/* FIXME: power down ??? */
return 0;
}
static int tuner_resume(struct i2c_client *c)
{
- struct tuner *t = i2c_get_clientdata (c);
+ struct tuner *t = i2c_get_clientdata(c);
- tuner_dbg ("resume\n");
+ tuner_dbg("resume\n");
if (V4L2_TUNER_RADIO == t->mode) {
if (t->radio_freq)
set_freq(c, t->radio_freq);
/* ---------------------------------------------------------------------- */
-LIST_HEAD(tuner_list);
+static LIST_HEAD(tuner_list);
/* Search for existing radio and/or TV tuners on the given I2C adapter.
- Note that when this function is called from tuner_attach you can be
+ Note that when this function is called from tuner_probe you can be
certain no other devices will be added/deleted at the same time, I2C
core protects against that. */
static void tuner_lookup(struct i2c_adapter *adap,
}
/* During client attach, set_type is called by adapter's attach_inform callback.
- set_type must then be completed by tuner_attach.
+ set_type must then be completed by tuner_probe.
*/
-static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
+static int tuner_probe(struct i2c_client *client)
{
- struct i2c_client *client;
struct tuner *t;
struct tuner *radio;
struct tuner *tv;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (NULL == client)
- return -ENOMEM;
-
t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
- if (NULL == t) {
- kfree(client);
+ if (NULL == t)
return -ENOMEM;
- }
t->i2c = client;
- client_template.adapter = adap;
- client_template.addr = addr;
- memcpy(client, &client_template, sizeof(struct i2c_client));
+ strlcpy(client->name, "(tuner unset)", sizeof(client->name));
i2c_set_clientdata(client, t);
t->type = UNSET;
t->audmode = V4L2_TUNER_MODE_STEREO;
printk(KERN_CONT "%02x ", buffer[i]);
printk("\n");
}
- /* HACK: This test were added to avoid tuner to probe tda9840 and
+ /* HACK: This test was added to avoid tuner to probe tda9840 and
tea6415c on the MXB card */
- if (adap->id == I2C_HW_SAA7146 && addr < 0x4a)
+ if (client->adapter->id == I2C_HW_SAA7146 && client->addr < 0x4a) {
+ kfree(t);
return -ENODEV;
+ }
/* autodetection code based on the i2c addr */
if (!no_autodetect) {
- switch (addr) {
+ switch (client->addr) {
case 0x10:
if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
!= EINVAL) {
case 0x4b:
/* If chip is not tda8290, don't register.
since it can be tda9887*/
- if (tda829x_probe(t) == 0) {
+ if (tda829x_probe(t->i2c->adapter,
+ t->i2c->addr) == 0) {
tuner_dbg("tda829x detected\n");
} else {
/* Default is being tda9887 */
/* Should be just before return */
register_client:
- tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
+ tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1,
+ client->adapter->name);
/* Sets a default mode */
if (t->mode_mask & T_ANALOG_TV) {
- t->mode = T_ANALOG_TV;
+ t->mode = V4L2_TUNER_ANALOG_TV;
} else if (t->mode_mask & T_RADIO) {
- t->mode = T_RADIO;
+ t->mode = V4L2_TUNER_RADIO;
} else {
- t->mode = T_DIGITAL_TV;
+ t->mode = V4L2_TUNER_DIGITAL_TV;
}
-
- i2c_attach_client(client);
set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback);
+ list_add_tail(&t->list, &tuner_list);
return 0;
}
-static int tuner_probe(struct i2c_adapter *adap)
+static int tuner_legacy_probe(struct i2c_adapter *adap)
{
if (0 != addr) {
normal_i2c[0] = addr;
normal_i2c[1] = I2C_CLIENT_END;
}
+ if ((adap->class & I2C_CLASS_TV_ANALOG) == 0)
+ return 0;
+
/* HACK: Ignore 0x6b and 0x6f on cx88 boards.
* FusionHDTV5 RT Gold has an ir receiver at 0x6b
* and an RTC at 0x6f which can get corrupted if probed.
"too many options specified "
"in i2c probe ignore list!\n");
}
-
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, tuner_attach);
- return 0;
+ return 1;
}
-static int tuner_detach(struct i2c_client *client)
+static int tuner_remove(struct i2c_client *client)
{
struct tuner *t = i2c_get_clientdata(client);
- struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops;
- int err;
-
- err = i2c_detach_client(t->i2c);
- if (err) {
- tuner_warn
- ("Client deregistration failed, client not detached.\n");
- return err;
- }
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
- if (ops && ops->release)
- ops->release(&t->fe);
+ if (analog_ops->release)
+ analog_ops->release(&t->fe);
list_del(&t->list);
kfree(t);
- kfree(client);
return 0;
}
/* ----------------------------------------------------------------------- */
-static struct i2c_driver driver = {
- .id = I2C_DRIVERID_TUNER,
- .attach_adapter = tuner_probe,
- .detach_client = tuner_detach,
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+ .name = "tuner",
+ .driverid = I2C_DRIVERID_TUNER,
.command = tuner_command,
+ .probe = tuner_probe,
+ .remove = tuner_remove,
.suspend = tuner_suspend,
- .resume = tuner_resume,
- .driver = {
- .name = "tuner",
- },
+ .resume = tuner_resume,
+ .legacy_probe = tuner_legacy_probe,
};
-static struct i2c_client client_template = {
- .name = "(tuner unset)",
- .driver = &driver,
-};
-
-static int __init tuner_init_module(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit tuner_cleanup_module(void)
-{
- i2c_del_driver(&driver);
-}
-module_init(tuner_init_module);
-module_exit(tuner_cleanup_module);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.