/*
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/i2c.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/videodev2.h>
#include <media/tuner.h>
#include <media/tuner-types.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-i2c-drv.h>
#include "mt20xx.h"
#include "tda8290.h"
#include "tea5761.h"
#include "tea5767.h"
#include "tuner-xc2028.h"
#include "tuner-simple.h"
#include "tda9887.h"
#include "xc5000.h"
#define UNSET (-1U)
#define PREFIX t->i2c->driver->driver.name
/** This macro allows us to probe dynamically, avoiding static links */
#ifdef CONFIG_MEDIA_ATTACH
#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
int __r = -EINVAL; \
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
if (__a) { \
__r = (int) __a(ARGS); \
symbol_put(FUNCTION); \
} else { \
printk(KERN_ERR "TUNER: Unable to find " \
"symbol "#FUNCTION"()\n"); \
} \
__r; \
})
static void tuner_detach(struct dvb_frontend *fe)
{
if (fe->ops.tuner_ops.release) {
fe->ops.tuner_ops.release(fe);
symbol_put_addr(fe->ops.tuner_ops.release);
}
if (fe->ops.analog_ops.release) {
fe->ops.analog_ops.release(fe);
symbol_put_addr(fe->ops.analog_ops.release);
}
}
#else
#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
FUNCTION(ARGS); \
})
static void tuner_detach(struct dvb_frontend *fe)
{
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
if (fe->ops.analog_ops.release)
fe->ops.analog_ops.release(fe);
}
#endif
struct tuner {
/* device */
struct dvb_frontend fe;
struct i2c_client *i2c;
struct v4l2_subdev sd;
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;
const char *name;
};
static inline struct tuner *to_tuner(struct v4l2_subdev *sd)
{
return container_of(sd, struct tuner, sd);
}
/* insmod options used at init time => read/only */
static unsigned int addr;
static unsigned int no_autodetect;
static unsigned int show_i2c;
/* insmod options used at runtime => read/write */
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] = {