patch-2.4.0-test11 linux/drivers/media/video/msp3400.c
Next file: linux/drivers/media/video/planb.c
Previous file: linux/drivers/media/video/id.h
Back to the patch index
Back to the overall index
- Lines: 435
- Date:
Sun Nov 12 20:47:19 2000
- Orig file:
v2.4.0-test10/linux/drivers/media/video/msp3400.c
- Orig date:
Sun Aug 6 12:45:28 2000
diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/msp3400.c linux/drivers/media/video/msp3400.c
@@ -88,8 +88,10 @@
int norm;
int stereo;
int nicam_on;
+ int acb;
int main, second; /* sound carrier */
+ int muted;
int left, right; /* volume */
int bass, treble;
@@ -299,6 +301,43 @@
#define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
+/* ----------------------------------------------------------------------- */
+
+#define SCART_MASK 0
+#define SCART_IN1 1
+#define SCART_IN2 2
+#define SCART_IN1_DA 3
+#define SCART_IN2_DA 4
+#define SCART_IN3 5
+#define SCART_IN4 6
+#define SCART_MONO 7
+#define SCART_MUTE 8
+
+static int scarts[3][9] = {
+ /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
+ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
+ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
+ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
+};
+
+static char *scart_names[] = {
+ "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
+};
+
+static void
+msp3400c_set_scart(struct i2c_client *client, int in, int out)
+{
+ struct msp3400c *msp = client->data;
+
+ if (-1 == scarts[out][in])
+ return;
+
+ dprintk("msp34xx: scart switch: %s => %d\n",scart_names[in],out);
+ msp->acb &= ~scarts[out][SCART_MASK];
+ msp->acb |= scarts[out][in];
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb);
+}
+
/* ------------------------------------------------------------------------ */
static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2)
@@ -310,18 +349,21 @@
msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
}
-static void msp3400c_setvolume(struct i2c_client *client, int left, int right)
+static void msp3400c_setvolume(struct i2c_client *client,
+ int muted, int left, int right)
{
- int vol,val,balance;
+ int vol = 0,val = 0,balance = 0;
- vol = (left > right) ? left : right;
- val = (vol * 0x73 / 65535) << 8;
- balance = 0;
- if (vol > 0)
+ if (!muted) {
+ vol = (left > right) ? left : right;
+ val = (vol * 0x73 / 65535) << 8;
+ }
+ if (vol > 0) {
balance = ((right-left) * 127) / vol;
+ }
- dprintk("msp34xx: setvolume: %d:%d 0x%02x 0x%02x\n",
- left,right,val>>8,balance);
+ dprintk("msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n",
+ muted ? "on" : "off", left, right, val>>8, balance);
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
/* scart - on/off only */
@@ -470,11 +512,8 @@
if (msp->mode == MSP_MODE_AM_NICAM) {
dprintk("msp3400: switching to AM mono\n");
/* AM mono decoding is handled by tuner, not MSP chip */
- /* so let's redirect sound from tuner via SCART */
- /* volume prescale for SCART */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
- /* SCART switching control register*/
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, 0xe900);
+ /* SCART switching control register */
+ msp3400c_set_scart(client,SCART_MONO,0);
src = 0x0200;
break;
}
@@ -711,7 +750,7 @@
restart:
msp->restart = 0;
- msp3400c_setvolume(client, 0, 0);
+ msp3400c_setvolume(client, msp->muted, 0, 0);
msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
val1 = val2 = 0;
max1 = max2 = -1;
@@ -829,6 +868,8 @@
msp->nicam_on = 0;
msp3400c_setstereo(client, VIDEO_SOUND_MONO);
msp3400c_setcarrier(client, msp->second, msp->main);
+ /* volume prescale for SCART (AM mono input) */
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
msp->watch_stereo = 1;
} else if (max2 == 0 && msp->nicam) {
/* D/K NICAM */
@@ -854,7 +895,7 @@
}
/* unmute */
- msp3400c_setvolume(client, msp->left, msp->right);
+ msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
if (msp->watch_stereo)
mod_timer(&msp->wake_stereo, jiffies+5*HZ);
@@ -941,9 +982,6 @@
if (msp->rmmod || signal_pending(current))
goto done;
- if (VIDEO_MODE_RADIO == msp->norm)
- continue; /* nothing to do */
-
msp->active = 1;
if (msp->watch_stereo) {
@@ -966,6 +1004,11 @@
/* put into sane state (and mute) */
msp3400c_reset(client);
+ /* set various prescales */
+ msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */
+ msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
+ msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */
+
/* start autodetect */
switch (msp->norm) {
case VIDEO_MODE_PAL:
@@ -978,7 +1021,11 @@
break;
case VIDEO_MODE_SECAM:
mode = 0x0003;
- std = 1;
+ std = 1;
+ break;
+ case VIDEO_MODE_RADIO:
+ mode = 0x0003;
+ std = 0x0040;
break;
default:
mode = 0x0003;
@@ -987,8 +1034,7 @@
}
msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode);
msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std);
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403);
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00);
+
if (debug) {
int i;
for (i = 0; modelist[i].name != NULL; i++)
@@ -1019,7 +1065,7 @@
}
}
for (i = 0; modelist[i].name != NULL; i++)
- if (modelist[i].retval == val)
+ if (modelist[i].retval == val)
break;
dprintk("msp3410: current mode: %s (0x%04x)\n",
modelist[i].name ? modelist[i].name : "unknown",
@@ -1035,11 +1081,24 @@
msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
}
- /* set prescale / stereo */
+ /* set stereo */
switch (val) {
+ case 0x0008: /* B/G NICAM */
+ case 0x000a: /* I NICAM */
+ if (val == 0x0008)
+ msp->mode = MSP_MODE_FM_NICAM1;
+ else
+ msp->mode = MSP_MODE_FM_NICAM2;
+ /* just turn on stereo */
+ msp->stereo = VIDEO_SOUND_STEREO;
+ msp->nicam_on = 1;
+ msp->watch_stereo = 1;
+ msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
+ break;
case 0x0009:
msp->mode = MSP_MODE_AM_NICAM;
msp->stereo = VIDEO_SOUND_MONO;
+ msp->nicam_on = 1;
msp3400c_setstereo(client,VIDEO_SOUND_MONO);
msp->watch_stereo = 1;
break;
@@ -1047,26 +1106,31 @@
/* just turn on stereo */
msp->mode = MSP_MODE_BTSC;
msp->stereo = VIDEO_SOUND_STEREO;
+ msp->nicam_on = 0;
msp->watch_stereo = 1;
msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
- /* set prescale */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
+ break;
+ case 0x0040: /* FM radio */
+ msp->mode = MSP_MODE_FM_RADIO;
+ msp->stereo = VIDEO_SOUND_STEREO;
+ msp->nicam_on = 0;
+ msp->watch_stereo = 0;
+ /* scart routing */
+ msp3400c_set_scart(client,SCART_IN2,0);
+ msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220);
break;
case 0x0003:
msp->mode = MSP_MODE_FM_TERRA;
msp->stereo = VIDEO_SOUND_MONO;
+ msp->nicam_on = 0;
msp->watch_stereo = 1;
- /* fall */
- default:
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* NICAM */
break;
}
-
+
/* unmute */
msp3400c_setbass(client, msp->bass);
msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->left, msp->right);
+ msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
if (msp->watch_stereo)
mod_timer(&msp->wake_stereo, jiffies+HZ);
@@ -1093,22 +1157,18 @@
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
static struct i2c_driver driver = {
- "i2c msp3400 driver",
- I2C_DRIVERID_MSP3400,
- I2C_DF_NOTIFY,
- msp_probe,
- msp_detach,
- msp_command,
+ name: "i2c msp3400 driver",
+ id: I2C_DRIVERID_MSP3400,
+ flags: I2C_DF_NOTIFY,
+ attach_adapter: msp_probe,
+ detach_client: msp_detach,
+ command: msp_command,
};
static struct i2c_client client_template =
{
- "unset",
- -1,
- 0,
- 0,
- NULL,
- &driver
+ name: "(unset)",
+ driver: &driver,
};
static int msp_attach(struct i2c_adapter *adap, int addr,
@@ -1150,8 +1210,9 @@
}
rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e);
- rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f);
- if (0 == rev1 && 0 == rev2) {
+ if (-1 != rev1)
+ rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f);
+ if ((-1 == rev1) || (0 == rev1 && 0 == rev2)) {
kfree(msp);
printk("msp3400: error while reading chip version\n");
return -1;
@@ -1180,7 +1241,7 @@
msp->wake_stereo.data = (unsigned long)msp;
/* hello world :-) */
- printk(KERN_INFO "msp3400: init: chip=%s",c->name);
+ printk(KERN_INFO "msp34xx: init: chip=%s",c->name);
if (msp->nicam)
printk(", has NICAM support");
printk("\n");
@@ -1194,11 +1255,6 @@
msp->notify = NULL;
wake_up_interruptible(&msp->wq);
-#ifdef REGISTER_MIXER
- if ((msp->mixer_num = register_sound_mixer(&msp3400c_mixer_fops,mixer)) < 0)
- printk(KERN_ERR "msp3400c: cannot allocate mixer device\n");
-#endif
-
/* update our own array */
for (i = 0; i < MSP3400_MAX; i++) {
if (NULL == msps[i]) {
@@ -1218,11 +1274,6 @@
struct msp3400c *msp = (struct msp3400c*)client->data;
int i;
-#ifdef REGISTER_MIXER
- if (msp->mixer_num >= 0)
- unregister_sound_mixer(msp->mixer_num);
-#endif
-
/* shutdown control thread */
del_timer(&msp->wake_stereo);
if (msp->thread)
@@ -1260,29 +1311,47 @@
static int msp_command(struct i2c_client *client,unsigned int cmd, void *arg)
{
struct msp3400c *msp = (struct msp3400c*)client->data;
+ __u16 *sarg = arg;
#if 0
int *iarg = (int*)arg;
- __u16 *sarg = arg;
#endif
switch (cmd) {
+ case AUDC_SET_INPUT:
+#if 1
+ /* hauppauge 44xxx scart switching */
+ switch (*sarg) {
+ case AUDIO_RADIO:
+ msp3400c_set_scart(client,SCART_IN2,0);
+ break;
+ case AUDIO_EXTERN:
+ msp3400c_set_scart(client,SCART_IN1,0);
+ break;
+ default:
+ if (*sarg & AUDIO_MUTE)
+ msp3400c_set_scart(client,SCART_MUTE,0);
+ break;
+ }
+#endif
+ break;
+
case AUDC_SET_RADIO:
msp->norm = VIDEO_MODE_RADIO;
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
+ dprintk("msp34xx: switching to radio mode\n");
if (msp->simple) {
- msp3400c_reset(client);
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, 0x0003); /* automatic */
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, 0x0040); /* FM Radio */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM prescale */
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->left, msp->right);
+ /* the thread will do for us */
+ msp3400c_setvolume(client,msp->muted,0,0);
+ if (msp->active)
+ msp->restart = 1;
+ wake_up_interruptible(&msp->wq);
} else {
+ /* set msp3400 to FM radio mode */
msp3400c_setmode(client,MSP_MODE_FM_RADIO);
msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
- msp3400c_setvolume(client,msp->left, msp->right);
+ msp3400c_setvolume(client,msp->muted,msp->left,msp->right);
}
break;
@@ -1295,7 +1364,10 @@
va->flags |= VIDEO_AUDIO_VOLUME |
VIDEO_AUDIO_BASS |
- VIDEO_AUDIO_TREBLE;
+ VIDEO_AUDIO_TREBLE |
+ VIDEO_AUDIO_MUTABLE;
+ if (msp->muted)
+ va->flags |= VIDEO_AUDIO_MUTE;
va->volume=MAX(msp->left,msp->right);
va->balance=(32768*MIN(msp->left,msp->right))/
(va->volume ? va->volume : 1);
@@ -1304,21 +1376,24 @@
va->bass = msp->bass;
va->treble = msp->treble;
- autodetect_stereo(client);
- va->mode = msp->stereo;
+ if (msp->norm != VIDEO_MODE_RADIO) {
+ autodetect_stereo(client);
+ va->mode = msp->stereo;
+ }
break;
}
case VIDIOCSAUDIO:
{
struct video_audio *va = arg;
+ msp->muted = (va->flags & VIDEO_AUDIO_MUTE);
msp->left = (MIN(65536 - va->balance,32768) *
va->volume) / 32768;
msp->right = (MIN(va->balance,32768) *
va->volume) / 32768;
msp->bass = va->bass;
msp->treble = va->treble;
- msp3400c_setvolume(client,msp->left, msp->right);
+ msp3400c_setvolume(client,msp->muted,msp->left,msp->right);
msp3400c_setbass(client,msp->bass);
msp3400c_settreble(client,msp->treble);
@@ -1334,13 +1409,14 @@
{
struct video_channel *vc = arg;
+ dprintk("msp34xx: switching to TV mode\n");
msp->norm = vc->norm;
break;
}
case VIDIOCSFREQ:
{
/* new channel -- kick audio carrier scan */
- msp3400c_setvolume(client,0,0);
+ msp3400c_setvolume(client,msp->muted,0,0);
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
if (msp->active)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)