static unsigned int debug = 0;
static unsigned int type = UNSET;
static unsigned int addr = 0;
-static char *pal = "b";
static unsigned int tv_range[2] = { 44, 958 };
static unsigned int radio_range[2] = { 65, 108 };
+static unsigned int tv_antenna = 1;
+static unsigned int radio_antenna = 0;
MODULE_PARM(debug,"i");
MODULE_PARM(type,"i");
MODULE_PARM(addr,"i");
MODULE_PARM(tv_range,"2i");
MODULE_PARM(radio_range,"2i");
-MODULE_PARM(pal,"s");
+MODULE_PARM(tv_antenna,"i");
+MODULE_PARM(radio_antenna,"i");
#define optimize_vco 1
struct tuner {
unsigned int type; /* chip type */
unsigned int freq; /* keep track of the current settings */
- unsigned int std;
+ v4l2_std_id std;
+ int using_v4l2;
unsigned int radio;
- unsigned int mode; /* current norm for multi-norm tuners */
unsigned int input;
// only for MT2032
int if2,from,to;
// signal bandwidth and picture carrier
- if (t->mode == VIDEO_MODE_NTSC) {
- from=40750*1000;
- to=46750*1000;
- if2=45750*1000;
+ if (t->std & V4L2_STD_525_60) {
+ // NTSC
+ from = 40750*1000;
+ to = 46750*1000;
+ if2 = 45750*1000;
} else {
- // Pal
- from=32900*1000;
- to=39900*1000;
- if2=38900*1000;
+ // PAL
+ from = 32900*1000;
+ to = 39900*1000;
+ if2 = 38900*1000;
}
mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
return(1);
}
+static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
+{
+ unsigned char buf[2];
+ int ret;
+
+ buf[0] = 6;
+ buf[1] = antenna ? 0x11 : 0x10;
+ ret=i2c_master_send(c,buf,2);
+ dprintk("mt2050: enabled antenna connector %d\n", antenna);
+}
+
static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
{
unsigned int if1=1218*1000*1000;
struct tuner *t = i2c_get_clientdata(c);
unsigned int if2;
- if (t->mode == VIDEO_MODE_NTSC) {
- if2=45750*1000;
+ if (t->std & V4L2_STD_525_60) {
+ // NTSC
+ if2 = 45750*1000;
} else {
- // Pal
- if2=38900*1000;
+ // PAL
+ if2 = 38900*1000;
}
- mt2050_set_if_freq(c,freq*62500,if2);
+ mt2050_set_if_freq(c, freq*62500, if2);
+ mt2050_set_antenna(c, tv_antenna);
}
static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
int if2 = t->radio_if2;
mt2050_set_if_freq(c, freq*62500, if2);
+ mt2050_set_antenna(c, radio_antenna);
}
static int mt2050_init(struct i2c_client *c)
unsigned char buf[21];
int company_code;
- buf[0] = 0;
- t->tv_freq = NULL;
+ memset(buf,0,sizeof(buf));
+ t->tv_freq = NULL;
t->radio_freq = NULL;
name = "unknown";
company_code = buf[0x11] << 8 | buf[0x12];
printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n",
company_code,buf[0x13],buf[0x14]);
+
+#if 0
+ /* seems to cause more problems than it solves ... */
switch (company_code) {
case 0x30bf:
case 0x3cbf:
printk("tuner: microtune: unknown companycode\n");
return 0;
}
+#endif
if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
NULL != microtune_part[buf[0x13]])
/* 0x02 -> PAL BDGHI / SECAM L */
/* 0x04 -> ??? PAL others / SECAM others ??? */
config &= ~0x02;
- if (t->mode == VIDEO_MODE_SECAM)
+ if (t->std & V4L2_STD_SECAM)
config |= 0x02;
break;
case TUNER_TEMIC_4046FM5:
config &= ~0x0f;
- switch (pal[0]) {
- case 'i':
- case 'I':
+
+ if (t->std & V4L2_STD_PAL_BG) {
+ config |= TEMIC_SET_PAL_BG;
+
+ } else if (t->std & V4L2_STD_PAL_I) {
config |= TEMIC_SET_PAL_I;
- break;
- case 'd':
- case 'D':
+
+ } else if (t->std & V4L2_STD_PAL_DK) {
config |= TEMIC_SET_PAL_DK;
- break;
- case 'l':
- case 'L':
+
+ } else if (t->std & V4L2_STD_SECAM_L) {
config |= TEMIC_SET_PAL_L;
- break;
- case 'b':
- case 'B':
- case 'g':
- case 'G':
- default:
- config |= TEMIC_SET_PAL_BG;
- break;
+
}
break;
case TUNER_PHILIPS_FQ1216ME:
config &= ~0x0f;
- switch (pal[0]) {
- case 'i':
- case 'I':
+
+ if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+ config |= PHILIPS_SET_PAL_BGDK;
+
+ } else if (t->std & V4L2_STD_PAL_I) {
config |= PHILIPS_SET_PAL_I;
- break;
- case 'l':
- case 'L':
+
+ } else if (t->std & V4L2_STD_SECAM_L) {
config |= PHILIPS_SET_PAL_L;
- break;
- case 'd':
- case 'D':
- case 'b':
- case 'B':
- case 'g':
- case 'G':
- config |= PHILIPS_SET_PAL_BGDK;
- break;
+
}
break;
/* 0x01 -> ATSC antenna input 2 */
/* 0x02 -> NTSC antenna input 1 */
/* 0x03 -> NTSC antenna input 2 */
-
config &= ~0x03;
-#ifdef VIDEO_MODE_ATSC
- if (VIDEO_MODE_ATSC != t->mode)
+ if (t->std & V4L2_STD_ATSC)
config |= 2;
-#endif
/* FIXME: input */
break;
}
t->radio_freq(c,freq);
}
+static void set_freq(struct i2c_client *c, unsigned long freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ if (t->radio) {
+ dprintk("tuner: radio freq set to %lu.%02lu\n",
+ freq/16,freq%16*100/16);
+ set_radio_freq(c,freq);
+ } else {
+ dprintk("tuner: tv freq set to %lu.%02lu\n",
+ freq/16,freq%16*100/16);
+ set_tv_freq(c, freq);
+ }
+ t->freq = freq;
+}
+
static void set_type(struct i2c_client *c, unsigned int type, char *source)
{
struct tuner *t = i2c_get_clientdata(c);
}
}
+static char *pal = "-";
+MODULE_PARM(pal,"s");
+
+static int tuner_fixup_std(struct tuner *t)
+{
+ if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
+ /* get more precise norm info from insmod option */
+ switch (pal[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ dprintk("insmod fixup: PAL => PAL-BG\n");
+ t->std = V4L2_STD_PAL_BG;
+ break;
+ case 'i':
+ case 'I':
+ dprintk("insmod fixup: PAL => PAL-I\n");
+ t->std = V4L2_STD_PAL_I;
+ break;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ dprintk("insmod fixup: PAL => PAL-DK\n");
+ t->std = V4L2_STD_PAL_DK;
+ break;
+ }
+ }
+ return 0;
+}
+
/* ---------------------------------------------------------------------- */
static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
set_type(client, type, "insmod option");
printk("tuner: The type=<n> insmod option will go away soon.\n");
printk("tuner: Please use the tuner=<n> option provided by\n");
- printk("tuner: tv card core driver (bttv, saa7134, ...) instead.\n");
+ printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n");
}
return 0;
}
return 0;
}
+#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \
+ printk("tuner: switching to v4l2\n"); \
+ t->using_v4l2 = 1;
+#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \
+ printk("tuner: ignore v4l1 call\n"); \
+ return 0; }
+
static int
tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
kernel pointer here... */
case VIDIOCSCHAN:
{
+ static const v4l2_std_id map[] = {
+ [ VIDEO_MODE_PAL ] = V4L2_STD_PAL,
+ [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M,
+ [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
+ [ 4 /* bttv */ ] = V4L2_STD_PAL_M,
+ [ 5 /* bttv */ ] = V4L2_STD_PAL_N,
+ [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
+ };
struct video_channel *vc = arg;
+ CHECK_V4L2;
t->radio = 0;
- t->mode = vc->norm;
+ if (vc->norm < ARRAY_SIZE(map))
+ t->std = map[vc->norm];
+ tuner_fixup_std(t);
if (t->freq)
set_tv_freq(client,t->freq);
return 0;
{
unsigned long *v = arg;
- if (t->radio) {
- dprintk("tuner: radio freq set to %lu.%02lu\n",
- (*v)/16,(*v)%16*100/16);
- set_radio_freq(client,*v);
- } else {
- dprintk("tuner: tv freq set to %lu.%02lu\n",
- (*v)/16,(*v)%16*100/16);
- set_tv_freq(client,*v);
- }
- t->freq = *v;
+ CHECK_V4L2;
+ set_freq(client,*v);
return 0;
}
case VIDIOCGTUNER:
{
struct video_tuner *vt = arg;
+ CHECK_V4L2;
if (t->radio)
vt->signal = tuner_signal(client);
return 0;
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
+
+ CHECK_V4L2;
if (t->radio)
va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
return 0;
}
+
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ SWITCH_V4L2;
+ t->radio = 0;
+ t->std = *id;
+ tuner_fixup_std(t);
+ if (t->freq)
+ set_freq(client,t->freq);
+ break;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ SWITCH_V4L2;
+ if (V4L2_TUNER_ANALOG_TV == f->type) {
+ t->radio = 0;
+ }
+ if (V4L2_TUNER_RADIO == f->type) {
+ if (!t->radio) {
+ set_tv_freq(client,400*16);
+ t->radio = 1;
+ }
+ }
+ t->freq = f->frequency;
+ set_freq(client,t->freq);
+ break;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *tuner = arg;
+
+ SWITCH_V4L2;
+ if (t->radio)
+ tuner->signal = tuner_signal(client);
+ break;
+ }
default:
/* nothing */
break;