summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/video/msp3400.h10
-rw-r--r--linux/drivers/media/video/mt20xx.c14
-rw-r--r--linux/drivers/media/video/tda8290.c6
-rw-r--r--linux/drivers/media/video/tea5767.c20
-rw-r--r--linux/drivers/media/video/tuner-core.c87
-rw-r--r--linux/drivers/media/video/tuner-simple.c46
-rw-r--r--linux/drivers/media/video/tuner-types.c8
-rw-r--r--linux/drivers/media/video/v4l2-common.c1
-rw-r--r--linux/include/media/tuner-types.h18
-rw-r--r--linux/include/media/tuner.h10
-rw-r--r--linux/include/media/v4l2-common.h7
11 files changed, 137 insertions, 90 deletions
diff --git a/linux/drivers/media/video/msp3400.h b/linux/drivers/media/video/msp3400.h
index bb903981f..ef691841d 100644
--- a/linux/drivers/media/video/msp3400.h
+++ b/linux/drivers/media/video/msp3400.h
@@ -1,5 +1,5 @@
/*
- * $Id: msp3400.h,v 1.9 2006/01/11 18:54:24 mchehab Exp $
+ * $Id: msp3400.h,v 1.10 2006/01/15 17:04:52 hverkuil Exp $
*/
#ifndef MSP3400_H
@@ -7,14 +7,6 @@
/* ---------------------------------------------------------------------- */
-struct msp_matrix {
- int input;
- int output;
-};
-
-/* ioctl for MSP_SET_MATRIX will have to be registered */
-#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
-
/* This macro is allowed for *constants* only, gcc must calculate it
at compile time. Remember -- no floats in kernel mode */
#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24)))
diff --git a/linux/drivers/media/video/mt20xx.c b/linux/drivers/media/video/mt20xx.c
index fda706d86..9a0b05575 100644
--- a/linux/drivers/media/video/mt20xx.c
+++ b/linux/drivers/media/video/mt20xx.c
@@ -1,5 +1,5 @@
/*
- * $Id: mt20xx.c,v 1.14 2006/01/11 21:01:01 hverkuil Exp $
+ * $Id: mt20xx.c,v 1.15 2006/01/15 17:04:52 hverkuil Exp $
*
* i2c tv tuner chip device driver
* controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -358,8 +358,8 @@ static int mt2032_init(struct i2c_client *c)
} while (xok != 1 );
t->xogc=xogc;
- t->tv_freq = mt2032_set_tv_freq;
- t->radio_freq = mt2032_set_radio_freq;
+ t->set_tv_freq = mt2032_set_tv_freq;
+ t->set_radio_freq = mt2032_set_radio_freq;
return(1);
}
@@ -486,8 +486,8 @@ static int mt2050_init(struct i2c_client *c)
i2c_master_recv(c,buf,1);
tuner_dbg("mt2050: sro is %x\n",buf[0]);
- t->tv_freq = mt2050_set_tv_freq;
- t->radio_freq = mt2050_set_radio_freq;
+ t->set_tv_freq = mt2050_set_tv_freq;
+ t->set_radio_freq = mt2050_set_radio_freq;
return 0;
}
@@ -499,8 +499,8 @@ int microtune_init(struct i2c_client *c)
int company_code;
memset(buf,0,sizeof(buf));
- t->tv_freq = NULL;
- t->radio_freq = NULL;
+ t->set_tv_freq = NULL;
+ t->set_radio_freq = NULL;
t->standby = NULL;
if (t->std & V4L2_STD_525_60) {
tuner_dbg("pinnacle ntsc\n");
diff --git a/linux/drivers/media/video/tda8290.c b/linux/drivers/media/video/tda8290.c
index cada3fbf2..28422f177 100644
--- a/linux/drivers/media/video/tda8290.c
+++ b/linux/drivers/media/video/tda8290.c
@@ -1,5 +1,5 @@
/*
- $Id: tda8290.c,v 1.32 2005/12/25 19:06:18 mkrufky Exp $
+ $Id: tda8290.c,v 1.33 2006/01/15 17:04:52 hverkuil Exp $
i2c tv tuner chip device driver
controls the philips tda8290+75 tuner chip combo.
@@ -572,8 +572,8 @@ int tda8290_init(struct i2c_client *c)
}
tuner_info("tuner: type set to %s\n", c->name);
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = has_signal;
t->standby = standby;
t->tda827x_lpsel = 0;
diff --git a/linux/drivers/media/video/tea5767.c b/linux/drivers/media/video/tea5767.c
index d3a75aa88..e8bf32ec1 100644
--- a/linux/drivers/media/video/tea5767.c
+++ b/linux/drivers/media/video/tea5767.c
@@ -2,7 +2,7 @@
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
* I2C address is allways 0xC0.
*
- * $Id: tea5767.c,v 1.35 2006/01/11 21:01:01 hverkuil Exp $
+ * $Id: tea5767.c,v 1.36 2006/01/15 17:04:52 hverkuil Exp $
*
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
* This code is placed under the terms of the GNU General Public License
@@ -67,7 +67,7 @@ extern int tuner_debug;
#define TEA5767_PORT1_HIGH 0x01
-/* Forth register */
+/* Fourth register */
#define TEA5767_PORT2_HIGH 0x80
/* Chips stops working. Only I2C bus remains on */
#define TEA5767_STDBY 0x40
@@ -90,7 +90,7 @@ extern int tuner_debug;
/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
#define TEA5767_SRCH_IND 0x01
-/* Fiveth register */
+/* Fifth register */
/* By activating, it will use Xtal at 13 MHz as reference for divider */
#define TEA5767_PLLREF_ENABLE 0x80
@@ -114,13 +114,13 @@ extern int tuner_debug;
#define TEA5767_STEREO_MASK 0x80
#define TEA5767_IF_CNTR_MASK 0x7f
-/* Four register */
+/* Fourth register */
#define TEA5767_ADC_LEVEL_MASK 0xf0
/* should be 0 */
#define TEA5767_CHIP_ID_MASK 0x0f
-/* Fiveth register */
+/* Fifth register */
/* Reserved for future extensions */
#define TEA5767_RESERVED_MASK 0xff
@@ -225,19 +225,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_13MHz:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_32768:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
buffer[3] |= TEA5767_XTAL_32768;
/* const 700=4000*175 Khz - to adjust freq to right value */
- div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15;
+ div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
break;
case TEA5767_HIGH_LO_32768:
default:
@@ -390,8 +390,8 @@ int tea5767_tuner_init(struct i2c_client *c)
tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
strlcpy(c->name, "tea5767", sizeof(c->name));
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
t->standby = tea5767_standby;
diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c
index 5b9cb9b7e..dd77906d5 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.98 2006/01/11 21:01:01 hverkuil Exp $
+ * $Id: tuner-core.c,v 1.99 2006/01/15 17:04:52 hverkuil Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -109,7 +109,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->tv_freq) {
+ if (NULL == t->set_tv_freq) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
@@ -117,8 +117,14 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
freq / 16, freq % 16 * 100 / 16, tv_range[0],
tv_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < tv_range[0] * 16)
+ freq = tv_range[0] * 16;
+ else
+ freq = tv_range[1] * 16;
}
- t->tv_freq(c, freq);
+ t->set_tv_freq(c, freq);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -129,18 +135,23 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->radio_freq) {
+ if (NULL == t->set_radio_freq) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
- if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) {
+ 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]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < radio_range[0] * 16000)
+ freq = radio_range[0] * 16000;
+ else
+ freq = radio_range[1] * 16000;
}
- t->radio_freq(c, freq);
- return;
+ t->set_radio_freq(c, freq);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -152,15 +163,16 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
tuner_dbg("radio freq set to %lu.%02lu\n",
freq / 16000, freq % 16000 * 100 / 16000);
set_radio_freq(c, freq);
+ t->radio_freq = freq;
break;
case V4L2_TUNER_ANALOG_TV:
case V4L2_TUNER_DIGITAL_TV:
tuner_dbg("tv freq set to %lu.%02lu\n",
freq / 16, freq % 16 * 100 / 16);
set_tv_freq(c, freq);
+ t->tv_freq = freq;
break;
}
- t->freq = freq;
}
static void set_type(struct i2c_client *c, unsigned int type,
@@ -241,7 +253,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
- set_freq(c, t->freq);
+ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
c->adapter->name, c->driver->name, c->addr << 1, type,
@@ -413,11 +425,11 @@ static void tuner_status(struct i2c_client *client)
default: p = "undefined"; break;
}
if (t->mode == V4L2_TUNER_RADIO) {
- freq = t->freq / 16000;
- freq_fraction = (t->freq % 16000) * 100 / 16000;
+ freq = t->radio_freq / 16000;
+ freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
} else {
- freq = t->freq / 16;
- freq_fraction = (t->freq % 16) * 100 / 16;
+ freq = t->tv_freq / 16;
+ freq_fraction = (t->tv_freq % 16) * 100 / 16;
}
tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
@@ -497,7 +509,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr,
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
- t->freq = 87.5 * 16; /* Sets freq to FM range */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask &= ~T_RADIO;
goto register_client;
@@ -510,7 +522,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr,
if (default_mode_mask != T_UNINITIALIZED) {
tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask);
t->mode_mask = default_mode_mask;
- t->freq = 400 * 16; /* Sets freq to VHF High */
+ t->tv_freq = 400 * 16; /* Sets freq to VHF High */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask = T_UNINITIALIZED;
}
@@ -617,16 +630,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
set_addr(client, (struct tuner_setup *)arg);
break;
case AUDC_SET_RADIO:
- set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
+ if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
+ == EINVAL)
+ return 0;
+ if (t->radio_freq)
+ set_freq(client, t->radio_freq);
break;
case TUNER_SET_STANDBY:
- {
- if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
- return 0;
- if (t->standby)
- t->standby (client);
- break;
- }
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
+ break;
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
return 0;
@@ -635,7 +650,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
-
break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -661,8 +675,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tuner_fixup_std(t);
- if (t->freq)
- set_tv_freq(client, t->freq);
+ if (t->tv_freq)
+ set_tv_freq(client, t->tv_freq);
return 0;
}
case VIDIOCSFREQ:
@@ -736,15 +750,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->std = *id;
tuner_fixup_std(t);
- if (t->freq)
- set_freq(client, t->freq);
+ if (t->tv_freq)
+ set_freq(client, t->tv_freq);
break;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
- t->freq = f->frequency;
switch_v4l2();
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode) {
@@ -752,7 +765,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
== EINVAL)
return 0;
}
- set_freq(client,t->freq);
+ set_freq(client,f->frequency);
break;
}
@@ -764,7 +777,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
switch_v4l2();
f->type = t->mode;
- f->frequency = t->freq;
+ f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+ t->radio_freq : t->tv_freq;
break;
}
case VIDIOC_G_TUNER:
@@ -815,7 +829,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (V4L2_TUNER_RADIO == t->mode) {
t->audmode = tuner->audmode;
- set_radio_freq(client, t->freq);
+ set_radio_freq(client, t->radio_freq);
}
break;
}
@@ -856,8 +870,13 @@ static int tuner_resume(struct device *dev, u32 level)
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("resume\n");
- if (t->freq)
- set_freq(c, t->freq);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->radio_freq)
+ set_freq(c, t->radio_freq);
+ } else {
+ if (t->tv_freq)
+ set_freq(c, t->tv_freq);
+ }
return 0;
}
#endif
diff --git a/linux/drivers/media/video/tuner-simple.c b/linux/drivers/media/video/tuner-simple.c
index 50012433d..b2a3ac189 100644
--- a/linux/drivers/media/video/tuner-simple.c
+++ b/linux/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-simple.c,v 1.70 2006/01/12 17:06:49 mkrufky Exp $
+ * $Id: tuner-simple.c,v 1.71 2006/01/15 17:04:52 hverkuil Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -162,7 +162,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
u8 config, tuneraddr;
u16 div;
struct tunertype *tun;
- unsigned char buffer[4];
+ u8 buffer[4];
int rc, IFPCoff, i, j;
tun = &tuners[t->type];
@@ -173,6 +173,11 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
continue;
break;
}
+ if (i == tun->params[j].count) {
+ tuner_dbg("TV frequency out of range (%d > %d)",
+ freq, tun->params[j].ranges[i - 1].limit);
+ freq = tun->params[j].ranges[--i].limit;
+ }
config = tun->params[j].ranges[i].cb;
/* i == 0 -> VHF_LO */
/* i == 1 -> VHF_HI */
@@ -265,20 +270,6 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
break;
}
- /*
- * Philips FI1216MK2 remark from specification :
- * for channel selection involving band switching, and to ensure
- * smooth tuning to the desired channel without causing
- * unnecessary charge pump action, it is recommended to consider
- * the difference between wanted channel frequency and the
- * current channel frequency. Unnecessary charge pump action
- * will result in very low tuning voltage which may drive the
- * oscillator to extreme conditions.
- *
- * Progfou: specification says to send config data before
- * frequency in case (wanted frequency < current frequency).
- */
-
/* IFPCoff = Video Intermediate Frequency - Vif:
940 =16*58.75 NTSC/J (Japan)
732 =16*45.75 M/N STD
@@ -310,7 +301,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
offset / 16, offset % 16 * 100 / 16,
div);
- if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
buffer[0] = tun->params[j].config;
buffer[1] = config;
buffer[2] = (div>>8) & 0x7f;
@@ -321,6 +312,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = tun->params[j].config;
buffer[3] = config;
}
+ t->last_div = div;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -363,8 +355,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tunertype *tun;
struct tuner *t = i2c_get_clientdata(c);
- unsigned char buffer[4];
- unsigned div;
+ u8 buffer[4];
+ u16 div;
int rc, j;
tun = &tuners[t->type];
@@ -400,9 +392,19 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
}
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = buffer[2];
+ buffer[1] = buffer[3];
+ buffer[2] = (div>>8) & 0x7f;
+ buffer[3] = div & 0xff;
+ } else {
+ buffer[0] = (div>>8) & 0x7f;
+ buffer[1] = div & 0xff;
+ }
tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
+ t->last_div = div;
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
@@ -416,10 +418,10 @@ int default_tuner_init(struct i2c_client *c)
t->type, tuners[t->type].name);
strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
- t->tv_freq = default_set_tv_freq;
- t->radio_freq = default_set_radio_freq;
+ t->set_tv_freq = default_set_tv_freq;
+ t->set_radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
- t->is_stereo = tuner_stereo;
+ t->is_stereo = tuner_stereo;
t->standby = NULL;
return 0;
diff --git a/linux/drivers/media/video/tuner-types.c b/linux/drivers/media/video/tuner-types.c
index 65b115f17..ce02da29d 100644
--- a/linux/drivers/media/video/tuner-types.c
+++ b/linux/drivers/media/video/tuner-types.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-types.c,v 1.2 2006/01/12 20:08:42 hverkuil Exp $
+ * $Id: tuner-types.c,v 1.3 2006/01/15 17:04:52 hverkuil Exp $
*
* i2c tv tuner chip device type database.
*
@@ -83,6 +83,7 @@ static struct tuner_params tuner_philips_ntsc_params[] = {
.ranges = tuner_philips_ntsc_ranges,
.count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
@@ -100,6 +101,7 @@ static struct tuner_params tuner_philips_secam_params[] = {
.ranges = tuner_philips_secam_ranges,
.count = ARRAY_SIZE(tuner_philips_secam_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
@@ -117,6 +119,7 @@ static struct tuner_params tuner_philips_pal_params[] = {
.ranges = tuner_philips_pal_ranges,
.count = ARRAY_SIZE(tuner_philips_pal_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
@@ -598,6 +601,7 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = {
.ranges = tuner_fm1216me_mk3_pal_ranges,
.count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
@@ -672,6 +676,7 @@ static struct tuner_params tuner_fm1236_mk3_params[] = {
.ranges = tuner_fm1236_mk3_ntsc_ranges,
.count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
@@ -786,6 +791,7 @@ static struct tuner_params tuner_tcl_2002n_params[] = {
.ranges = tuner_tcl_2002n_ntsc_ranges,
.count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
.config = 0x8e,
+ .cb_first_if_lower_freq = 1,
},
};
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index 7c9469e6c..8e3548ce0 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -326,6 +326,7 @@ static const char *v4l2_int_ioctls[] = {
#endif
[_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
[_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
+ [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
[_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
diff --git a/linux/include/media/tuner-types.h b/linux/include/media/tuner-types.h
index 73410a62c..f7b4d1c3d 100644
--- a/linux/include/media/tuner-types.h
+++ b/linux/include/media/tuner-types.h
@@ -30,6 +30,24 @@ struct tuner_range {
struct tuner_params {
enum param_type type;
unsigned int tda988x;
+ /* Many Philips based tuners have a comment like this in their
+ * datasheet:
+ *
+ * For channel selection involving band switching, and to ensure
+ * smooth tuning to the desired channel without causing
+ * unnecessary charge pump action, it is recommended to consider
+ * the difference between wanted channel frequency and the
+ * current channel frequency. Unnecessary charge pump action
+ * will result in very low tuning voltage which may drive the
+ * oscillator to extreme conditions.
+ *
+ * Set this flag to 1 if this tuner needs this check.
+ *
+ * I tested this for PAL by first setting the TV frequency to
+ * 203 MHz and then switching to 96.6 MHz FM radio. The result was
+ * static unless the control byte was sent first.
+ */
+ unsigned int cb_first_if_lower_freq:1;
#if 0 /* to be used when we merge dvb-pll */
u32 min;
u32 max;
diff --git a/linux/include/media/tuner.h b/linux/include/media/tuner.h
index a6a5786dc..50e3bd601 100644
--- a/linux/include/media/tuner.h
+++ b/linux/include/media/tuner.h
@@ -1,5 +1,5 @@
/*
- $Id: tuner.h,v 1.75 2006/01/12 20:08:42 hverkuil Exp $
+ $Id: tuner.h,v 1.76 2006/01/15 17:04:52 hverkuil Exp $
tuner.h - definition for different tuners
Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
@@ -180,7 +180,9 @@ struct tuner {
unsigned int mode;
unsigned int mode_mask; /* Combination of allowable modes */
- unsigned int freq; /* keep track of the current settings */
+ unsigned int tv_freq; /* keep track of the current settings */
+ unsigned int radio_freq;
+ u16 last_div;
unsigned int audmode;
v4l2_std_id std;
@@ -198,8 +200,8 @@ struct tuner {
unsigned int sgIF;
/* function ptrs */
- void (*tv_freq)(struct i2c_client *c, unsigned int freq);
- void (*radio_freq)(struct i2c_client *c, unsigned int freq);
+ void (*set_tv_freq)(struct i2c_client *c, unsigned int freq);
+ void (*set_radio_freq)(struct i2c_client *c, unsigned int freq);
int (*has_signal)(struct i2c_client *c);
int (*is_stereo)(struct i2c_client *c);
void (*standby)(struct i2c_client *c);
diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h
index cff20491c..f6efa076a 100644
--- a/linux/include/media/v4l2-common.h
+++ b/linux/include/media/v4l2-common.h
@@ -126,6 +126,13 @@ enum v4l2_chip_ident {
/* select from TV,radio,extern,MUTE */
#define AUDC_SET_INPUT _IOW('d',89,int)
+/* msp3400 ioctl: will be removed in the near future */
+struct msp_matrix {
+ int input;
+ int output;
+};
+#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
+
/* tuner ioctls */
/* Sets tuner type and its I2C addr */
#define TUNER_SET_TYPE_ADDR _IOW('d',90,int)