summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/tuner-core.c
diff options
context:
space:
mode:
authorNickolay V. Shmyrev <devnull@localhost>2005-07-02 14:53:02 +0000
committerNickolay V. Shmyrev <devnull@localhost>2005-07-02 14:53:02 +0000
commitec7f541e384c249c0f5a2c415b95c900bb272c44 (patch)
tree9534e774784b37f4456caed77e4ab3aad3dfc4b3 /linux/drivers/media/video/tuner-core.c
parentbab3237b10b3876a78d5083646f25e0a46a8d898 (diff)
downloadmediapointer-dvb-s2-ec7f541e384c249c0f5a2c415b95c900bb272c44.tar.gz
mediapointer-dvb-s2-ec7f541e384c249c0f5a2c415b95c900bb272c44.tar.bz2
* Make.config:
- Fix check for newer kernel to compile dvb modules. * tea5767.c, tuner-core.c, tuner.h, tuner-simple.c, scripts/cardlist: - Cleanup code a bit * msp3400-old.c, vbi, tda9887.h: - Remove unused files
Diffstat (limited to 'linux/drivers/media/video/tuner-core.c')
-rw-r--r--linux/drivers/media/video/tuner-core.c212
1 files changed, 92 insertions, 120 deletions
diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c
index 69e7784c1..13e78f56c 100644
--- a/linux/drivers/media/video/tuner-core.c
+++ b/linux/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-core.c,v 1.41 2005/07/01 21:41:37 mchehab Exp $
+ * $Id: tuner-core.c,v 1.42 2005/07/02 14:53:02 nsh Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -78,11 +78,11 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
struct tuner *t = i2c_get_clientdata(c);
if (t->type == UNSET) {
- tuner_info("tuner type not set\n");
+ tuner_warn ("tuner type not set\n");
return;
}
if (NULL == t->tv_freq) {
- tuner_info("Huh? tv_set is NULL?\n");
+ tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
@@ -98,24 +98,20 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
struct tuner *t = i2c_get_clientdata(c);
if (t->type == UNSET) {
- tuner_info("tuner type not set\n");
+ tuner_warn ("tuner type not set\n");
return;
}
if (NULL == t->radio_freq) {
- tuner_info("no radio tuning for this one, sorry.\n");
+ tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
- if (freq >= radio_range[0] * 16000 && freq <= radio_range[1] * 16000) {
- if (tuner_debug)
- tuner_info("radio freq step 62.5Hz (%d.%06d)\n",
- freq / 16000, freq % 16000 * 1000 / 16);
- t->radio_freq(c, freq);
- } else {
- tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+ if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) {
+ tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
freq / 16000, freq % 16000 * 100 / 16000,
radio_range[0], radio_range[1]);
}
+ t->radio_freq(c, freq);
return;
}
@@ -143,41 +139,28 @@ static void set_type(struct i2c_client *c, unsigned int type,
enum tuner_admin_state new_admin_status)
{
struct tuner *t = i2c_get_clientdata(c);
- unsigned int i;
unsigned char buffer[4];
- /* sanity check */
if (type == UNSET || type == TUNER_ABSENT) {
- printk("tuner 0x%02x: Tuner type absent\n",c->addr);
+ tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr);
return;
}
if (type >= tuner_count) {
- printk("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
+ tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
return;
}
/* This code prevents against I2C early announces */
if (NULL == t->i2c.dev.driver) {
- printk("tuner 0x%02x: I2C driver not registred yet!\n",c->addr);
+ tuner_dbg ("tuner 0x%02x: I2C driver not registred yet!\n", c->addr);
- for (i=0;(i<5)&&(NULL == t->i2c.dev.driver);i++) {
- msleep(1); /* Giver 1 ms for I2C */
- }
- if (NULL == t->i2c.dev.driver) {
- printk("tuner 0x%02x: I2C driver still not registred. Giving up!\n",c->addr);
- t->type=type;
- /* not registered yet */
- return;
- }
- tuner_info("tuner 0x%02x: Workaround worked\n",c->addr);
+ t->type=type;
+ return;
}
-/* if ((t->admin_status==T_UNINITIALIZED) && (t->type == type))
- return;
-*/
- tuner_dbg("set tuner type to %d\n",type);
t->type = type;
+
switch (t->type) {
case TUNER_MT2032:
microtune_init(c);
@@ -187,7 +170,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
break;
case TUNER_TEA5767:
if (tea5767_tuner_init(c) == EINVAL) {
- tuner_dbg("tuner is not a tea5767!\n");
t->type = TUNER_ABSENT;
t->admin_status = T_UNINITIALIZED;
return;
@@ -210,6 +192,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
default_tuner_init(c);
break;
}
+
if (t->admin_status == T_UNINITIALIZED)
t->admin_status = new_admin_status;
@@ -218,43 +201,39 @@ static void set_type(struct i2c_client *c, unsigned int type,
t->admin_status);
}
+/*
+ * This function apply tuner config to tuner specified
+ * by tun_addr structure. I addr is unset, then admin status
+ * and tun addr status is more precise then current status,
+ * it's applied. Otherwise status and type are applied only to
+ * tuner with exactly the same addr.
+*/
+
static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
{
struct tuner *t = i2c_get_clientdata(c);
- enum tuner_admin_state new_admin_status;
- /* ADDR_UNSET defaults to first available tuner */
if (tun_addr->addr == ADDR_UNSET) {
- /* If no Address specifyed, accepts only if tuner is */
- if (!(t->admin_status & tun_addr->v4l2_tuner))
- return;
+ if (t->admin_status & tun_addr->v4l2_tuner)
+ set_type(c, tun_addr->type, tun_addr->v4l2_tuner);
+ } else if (tun_addr->addr == c->addr) {
set_type(c, tun_addr->type, tun_addr->v4l2_tuner);
- } else {
- new_admin_status = tun_addr->v4l2_tuner;
-
- /* Sets tuner to its configured value */
- if (tun_addr->addr == c->addr)
- set_type(c, tun_addr->type, new_admin_status);
}
}
static inline int check_mode(struct tuner *t, char *cmd)
{
if (1 << t->mode & t->admin_status) {
- if (tuner_debug) {
- switch (t->mode) {
- case V4L2_TUNER_RADIO:
- tuner_dbg("Cmd %s accepted for radio\n", cmd);
- break;
- case V4L2_TUNER_ANALOG_TV:
- tuner_dbg("Cmd %s accepted for analog TV\n",
- cmd);
- break;
- case V4L2_TUNER_DIGITAL_TV:
- tuner_dbg("Cmd %s accepted for digital TV\n",
- cmd);
- break;
- }
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO:
+ tuner_dbg("Cmd %s accepted for radio\n", cmd);
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
+ break;
+ case V4L2_TUNER_DIGITAL_TV:
+ tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
+ break;
}
return 0;
}
@@ -350,13 +329,13 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
/* TEA5767 autodetection code - only for addr = 0xc0 */
if (addr == 0x60) {
- if (tea5767_autodetection(&t->i2c)!=EINVAL) {
+ if (tea5767_autodetection(&t->i2c) != EINVAL) {
t->type = TUNER_TEA5767;
- t->admin_status = T_RADIO|T_STANDBY;
+ t->admin_status = T_RADIO | T_STANDBY;
default_admin_status &= ~T_RADIO;
/* Should be just before return */
- i2c_attach_client(&t->i2c);
+ i2c_attach_client (&t->i2c);
set_type(&t->i2c,t->type, t->admin_status);
return 0;
}
@@ -364,14 +343,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
/* Initializes only the first adapter found */
if (default_admin_status != T_UNINITIALIZED) {
- tuner_dbg("admin to card = 0x%02x\n", default_admin_status);
+ tuner_dbg ("Setting admin_status to 0x%02x\n", default_admin_status);
t->admin_status = default_admin_status;
default_admin_status = T_UNINITIALIZED;
}
/* Should be just before return */
- i2c_attach_client(&t->i2c);
- set_type(&t->i2c,t->type, t->admin_status);
+ i2c_attach_client (&t->i2c);
+ set_type (&t->i2c,t->type, t->admin_status);
return 0;
}
@@ -405,26 +384,27 @@ static int tuner_detach(struct i2c_client *client)
return 0;
}
+/*
+ * Switch tuner to other mode. If tuner support both tv and radio,
+ * set another frequency to some value (This is needed for some pal
+ * tuners to avoid locking). Otherwise, just put second tuner in
+ * standby mode.
+ */
+
static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
{
- int freq;
-
if (mode != t->mode) {
+
t->mode = mode;
- /* If TV/Radio tuners are separate, put the other tuner in standby mode*/
if (check_mode(t, cmd) == EINVAL) {
t->admin_status |= T_STANDBY;
if (V4L2_TUNER_RADIO == mode) {
- freq=400 * 16; /* Why 400 MHz? */
- set_tv_freq(client, freq);
+ set_tv_freq(client, 400 * 16);
} else {
- freq=87.5 * 16000; /* Is it the better value? */
- set_radio_freq(client, freq);
+ set_radio_freq(client, 87.5 * 16000);
}
-
return EINVAL;
} else {
- /* Disables standby mode */
t->admin_status &= ~T_STANDBY;
set_freq (client, t->freq);
}
@@ -432,15 +412,14 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
return 0;
}
-#define switch_v4l2() if (!t->using_v4l2 && tuner_debug) \
- tuner_info("switching to v4l2\n"); \
- t->using_v4l2 = 1;
+#define switch_v4l2() if (!t->using_v4l2) \
+ tuner_dbg("switching to v4l2\n"); \
+ t->using_v4l2 = 1;
static inline int check_v4l2(struct tuner *t)
{
if (t->using_v4l2) {
- if (tuner_debug)
- tuner_info("ignore v4l1 call\n");
+ tuner_dbg ("ignore v4l1 call\n");
return EINVAL;
}
return 0;
@@ -452,19 +431,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
unsigned int *iarg = (int *)arg;
switch (cmd) {
- /* --- configuration --- */
+ /* --- configuration --- */
case TUNER_SET_TYPE:
- if (tuner_debug)
- tuner_dbg("Calling set_type for type=%d\n",*iarg);
+ tuner_dbg("Calling set_type for type=%d\n",*iarg);
set_type(client, *iarg, T_RADIO | T_ANALOG_TV | T_DIGITAL_TV);
break;
case TUNER_SET_TYPE_ADDR:
- if (tuner_debug)
- tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x\n",
- ((struct tuner_addr *)arg)->type,
- ((struct tuner_addr *)arg)->addr,
- ((struct tuner_addr *)arg)->v4l2_tuner);
+ tuner_dbg ("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x\n",
+ ((struct tuner_addr *)arg)->type,
+ ((struct tuner_addr *)arg)->addr,
+ ((struct tuner_addr *)arg)->v4l2_tuner);
set_addr(client, (struct tuner_addr *)arg);
break;
@@ -485,9 +462,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
break;
}
break;
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
+ case TDA9887_SET_CONFIG:
+ break;
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
case VIDIOCSCHAN:
{
static const v4l2_std_id map[] = {
@@ -576,7 +555,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
v4l2_std_id *id = arg;
- if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")==EINVAL)
+ if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
+ == EINVAL)
return 0;
switch_v4l2();
@@ -595,7 +575,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2();
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode) {
- if (set_mode(client,t,f->type,"VIDIOC_S_FREQUENCY") == EINVAL)
+ if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
+ == EINVAL)
return 0;
}
set_freq(client,t->freq);
@@ -620,21 +601,24 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL)
return 0;
switch_v4l2();
+
if (V4L2_TUNER_RADIO == t->mode) {
+
if (t->has_signal)
tuner->signal = t->has_signal(client);
- if (t->is_stereo) {
- if (t->is_stereo(client)) {
- tuner->rxsubchans =
- V4L2_TUNER_SUB_STEREO |
- V4L2_TUNER_SUB_MONO;
- } else {
- tuner->rxsubchans =
- V4L2_TUNER_SUB_MONO;
- }
+
+ if (t->is_stereo(client)) {
+ tuner->rxsubchans =
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_MONO;
+ } else {
+ tuner->rxsubchans =
+ V4L2_TUNER_SUB_MONO;
}
+
tuner->capability |=
V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+
tuner->audmode = t->audmode;
tuner->rangelow = radio_range[0] * 16000;
@@ -645,35 +629,23 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
break;
}
- case VIDIOC_S_TUNER: /* Allow changing radio range and audio mode */
+ case VIDIOC_S_TUNER:
{
struct v4l2_tuner *tuner = arg;
if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL)
return 0;
+
switch_v4l2();
- /* To switch the audio mode, applications initialize the
- index and audmode fields and the reserved array and
- call the VIDIOC_S_TUNER ioctl. */
- /* rxsubchannels: V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
- V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
- V4L2_TUNER_MODE_SAP */
if (V4L2_TUNER_RADIO == t->mode) {
- if (tuner->audmode == V4L2_TUNER_MODE_MONO)
- t->audmode = V4L2_TUNER_MODE_MONO;
- else
- t->audmode = V4L2_TUNER_MODE_STEREO;
-
+ t->audmode = tuner->audmode;
set_radio_freq(client, t->freq);
}
break;
}
- case TDA9887_SET_CONFIG: /* Nothing to do on tuner-core */
- break;
default:
tuner_dbg("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
- /* nothing */
break;
}
@@ -682,20 +654,20 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
static int tuner_suspend(struct device *dev, u32 state, u32 level)
{
- struct i2c_client *c = container_of(dev, struct i2c_client, dev);
- struct tuner *t = i2c_get_clientdata(c);
+ struct i2c_client *c = container_of (dev, struct i2c_client, dev);
+ 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 device *dev, u32 level)
{
- struct i2c_client *c = container_of(dev, struct i2c_client, dev);
- struct tuner *t = i2c_get_clientdata(c);
+ struct i2c_client *c = container_of (dev, struct i2c_client, dev);
+ struct tuner *t = i2c_get_clientdata (c);
- tuner_dbg("resume\n");
+ tuner_dbg ("resume\n");
if (t->freq)
set_freq(c, t->freq);
return 0;