diff options
author | Gerd Knorr <devnull@localhost> | 2004-10-05 12:57:08 +0000 |
---|---|---|
committer | Gerd Knorr <devnull@localhost> | 2004-10-05 12:57:08 +0000 |
commit | bcc9e747d2ce00c7e3d9238508fc04ce32958ef3 (patch) | |
tree | b02a6ee38c72ed96bd55cb236d0e1bc5b0696e67 /linux/drivers/media | |
parent | b5ec404857ece5b3a8203e9fac09be563a35f3ab (diff) | |
download | mediapointer-dvb-s2-bcc9e747d2ce00c7e3d9238508fc04ce32958ef3.tar.gz mediapointer-dvb-s2-bcc9e747d2ce00c7e3d9238508fc04ce32958ef3.tar.bz2 |
- misc build fixes.
- start switching over msp34xx to v4l2.
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/video/bttv-i2c.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/msp3400-driver.c | 520 | ||||
-rw-r--r-- | linux/drivers/media/video/msp3400.c | 520 |
3 files changed, 469 insertions, 575 deletions
diff --git a/linux/drivers/media/video/bttv-i2c.c b/linux/drivers/media/video/bttv-i2c.c index 131231718..8880d872f 100644 --- a/linux/drivers/media/video/bttv-i2c.c +++ b/linux/drivers/media/video/bttv-i2c.c @@ -1,5 +1,5 @@ /* - $Id: bttv-i2c.c,v 1.8 2004/09/22 11:47:11 kraxel Exp $ + $Id: bttv-i2c.c,v 1.9 2004/10/05 12:57:08 kraxel Exp $ bttv-i2c.c -- all the i2c code is here @@ -459,10 +459,12 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, btv); btv->i2c_client.adapter = &btv->c.i2c_adap; +#ifdef I2C_CLASS_TV_ANALOG if (bttv_tvcards[btv->c.type].no_video) btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; if (bttv_tvcards[btv->c.type].has_dvb) btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; +#endif if (btv->use_i2c_hw) { btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); diff --git a/linux/drivers/media/video/msp3400-driver.c b/linux/drivers/media/video/msp3400-driver.c index a1991985c..c0f090a91 100644 --- a/linux/drivers/media/video/msp3400-driver.c +++ b/linux/drivers/media/video/msp3400-driver.c @@ -78,25 +78,22 @@ static int dolby = 0; static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual (msp34xxg only) 0x00a0-0x03c0 */ -#define DFP_COUNT 0x41 -static const int bl_dfp[] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a, - 0x0b, 0x0d, 0x0e, 0x10 -}; - struct msp3400c { int rev1,rev2; int opmode; int mode; int norm; - int stereo; int nicam_on; int acb; int main, second; /* sound carrier */ int input; int source; /* see msp34xxg_set_source */ + /* v4l2 */ + int audmode; + int rxsubchans; + int muted; int volume, balance; int bass, treble; @@ -430,8 +427,9 @@ static void msp3400c_setmode(struct i2c_client *client, int type) int i; dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type); - msp->mode = type; - msp->stereo = VIDEO_SOUND_MONO; + msp->mode = type; + msp->audmode = V4L2_TUNER_MODE_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */ msp_init_data[type].ad_cv); @@ -481,65 +479,67 @@ static void msp3400c_setmode(struct i2c_client *client, int type) } } -// given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask -static int best_audio_mode(int mode) +static int best_audio_mode(int rxsubchans) { - if (mode & VIDEO_SOUND_STEREO) - return VIDEO_SOUND_STEREO; - if (mode & VIDEO_SOUND_LANG1) - return VIDEO_SOUND_LANG1; - if (mode & VIDEO_SOUND_LANG2) - return VIDEO_SOUND_LANG2; - return VIDEO_SOUND_MONO; + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + return V4L2_TUNER_MODE_LANG1; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + return V4L2_TUNER_MODE_LANG2; + return V4L2_TUNER_MODE_MONO; } /* turn on/off nicam + stereo */ -static void msp3400c_setstereo(struct i2c_client *client, int mode) +static void msp3400c_set_audmode(struct i2c_client *client, int audmode) { static char *strmode[16] = { #if __GNUC__ >= 3 - [ 0 ... 15 ] = "invalid", + [ 0 ... 15 ] = "invalid", #endif - [ VIDEO_SOUND_MONO ] = "mono", - [ VIDEO_SOUND_STEREO ] = "stereo", - [ VIDEO_SOUND_LANG1 ] = "lang1", - [ VIDEO_SOUND_LANG2 ] = "lang2", + [ V4L2_TUNER_MODE_MONO ] = "mono", + [ V4L2_TUNER_MODE_STEREO ] = "stereo", + [ V4L2_TUNER_MODE_LANG1 ] = "lang1", + [ V4L2_TUNER_MODE_LANG2 ] = "lang2", }; struct msp3400c *msp = i2c_get_clientdata(client); int nicam=0; /* channel source: FM/AM or nicam */ int src=0; BUG_ON(msp->opmode == OPMODE_SIMPLER); + msp->audmode = audmode; /* switch demodulator */ switch (msp->mode) { case MSP_MODE_FM_TERRA: - dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); break; - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_LANG2: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000); break; } break; case MSP_MODE_FM_SAT: - dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",strmode[mode]); - switch (mode) { - case VIDEO_SOUND_MONO: + dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n", + strmode[audmode]); + switch (audmode) { + case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; } @@ -547,21 +547,25 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); if (msp->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n", + strmode[audmode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n", + strmode[audmode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n", + strmode[audmode]); break; default: dprintk(KERN_DEBUG "msp3400: mono setstereo\n"); @@ -569,15 +573,15 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) } /* switch audio */ - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: src = 0x0020 | nicam; #if 0 /* spatial effect */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000); #endif break; - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: if (msp->mode == MSP_MODE_AM_NICAM) { dprintk("msp3400: switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ @@ -586,10 +590,10 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) src = 0x0200; break; } - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: src = 0x0000 | nicam; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: src = 0x0010 | nicam; break; } @@ -633,33 +637,6 @@ msp3400c_print_mode(struct msp3400c *msp) } } -#if 0 -static void -msp3400c_restore_dfp(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - for (i = 0; i < DFP_COUNT; i++) { - if (-1 == msp->dfp_regs[i]) - continue; - msp3400c_write(client,I2C_MSP3400C_DFP, i, msp->dfp_regs[i]); - } -} - -/* if the dfp_regs is set, set what's in there. - * Otherwise, set the default value */ -static int msp3400c_write_dfp_with_default(struct i2c_client *client, int addr, - int default_value) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int value=default_value; - if ( addr< DFP_COUNT && -1 != msp->dfp_regs[addr] ) - value=msp->dfp_regs[addr]; - return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value); -} -#endif - /* ----------------------------------------------------------------------- */ struct REGISTER_DUMP { @@ -680,8 +657,8 @@ autodetect_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); int val; - int newstereo = msp->stereo; - int newnicam = msp->nicam_on; + int rxsubchans = msp->rxsubchans; + int newnicam = msp->nicam_on; int update = 0; switch (msp->mode) { @@ -692,11 +669,11 @@ autodetect_stereo(struct i2c_client *client) dprintk(KERN_DEBUG "msp34xx: stereo detect register: %d\n",val); if (val > 4096) { - newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; } else if (val < -4096) { - newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } newnicam = 0; break; @@ -713,27 +690,27 @@ autodetect_stereo(struct i2c_client *client) switch ((val & 0x1e) >> 1) { case 0: case 8: - newstereo = VIDEO_SOUND_STEREO; + rxsubchans = V4L2_TUNER_SUB_STEREO; break; case 1: case 9: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1; break; case 2: case 10: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1 - | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; break; default: - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; break; } newnicam=1; } else { newnicam = 0; - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } break; case MSP_MODE_BTSC: @@ -746,16 +723,16 @@ autodetect_stereo(struct i2c_client *client) (val & 0x0040) ? "stereo" : "mono", (val & 0x0080) ? ", nicam 2nd mono" : "", (val & 0x0100) ? ", bilingual/SAP" : ""); - newstereo = VIDEO_SOUND_MONO; - if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO; - if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO; + if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; + if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; break; } - if (newstereo != msp->stereo) { + if (rxsubchans != msp->rxsubchans) { update = 1; - dprintk(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n", - msp->stereo,newstereo); - msp->stereo = newstereo; + dprintk(KERN_DEBUG "msp34xx: watch: rxsubchans %d => %d\n", + msp->rxsubchans,rxsubchans); + msp->rxsubchans = rxsubchans; } if (newnicam != msp->nicam_on) { update = 1; @@ -800,7 +777,7 @@ static void watch_stereo(struct i2c_client *client) struct msp3400c *msp = i2c_get_clientdata(client); if (autodetect_stereo(client)) - msp3400c_setstereo(client,best_audio_mode(msp->stereo)); + msp3400c_set_audmode(client,best_audio_mode(msp->rxsubchans)); if (once) msp->watch_stereo = 0; if (msp->watch_stereo) @@ -934,7 +911,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 1 && HAVE_NICAM(msp)) { /* B/G NICAM */ @@ -961,7 +938,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 0 && msp->norm == VIDEO_MODE_SECAM) { @@ -969,7 +946,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp3400c_setcarrier(client, msp->second, msp->main); /* volume prescale for SCART (AM mono input) */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); @@ -992,8 +969,8 @@ static int msp3400c_thread(void *data) msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; msp3400c_setcarrier(client, msp->second, msp->main); - msp->stereo = VIDEO_SOUND_MONO; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); break; } @@ -1201,29 +1178,30 @@ static int msp3410d_thread(void *data) else msp->mode = MSP_MODE_FM_NICAM2; /* just turn on stereo */ - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 1; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; case 0x0009: msp->mode = MSP_MODE_AM_NICAM; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp->nicam_on = 1; - msp3400c_setstereo(client,VIDEO_SOUND_MONO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; break; case 0x0020: /* BTSC */ /* just turn on stereo */ - msp->mode = MSP_MODE_BTSC; - msp->stereo = VIDEO_SOUND_STEREO; + msp->mode = MSP_MODE_BTSC; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 0; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; case 0x0040: /* FM radio */ msp->mode = MSP_MODE_FM_RADIO; - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp->nicam_on = 0; msp->watch_stereo = 0; /* not needed in theory if HAVE_RADIO(), but @@ -1249,7 +1227,8 @@ static int msp3410d_thread(void *data) case 0x0004: case 0x0005: msp->mode = MSP_MODE_FM_TERRA; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp->audmode = V4L2_TUNER_MODE_MONO; msp->nicam_on = 0; msp->watch_stereo = 1; break; @@ -1420,148 +1399,61 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) msp->source=source; } -/* get the current stereo mode and return it as a V4L1 stereo value (Use V4L2 calls whenever possible) */ -static int msp34xxg_get_v4l1_stereo(struct i2c_client *client) +static void msp34xxg_detect_stereo(struct i2c_client *client) { - /* This is not really clear: the API says that the mode should - * be the current mode, but the old driver returned what the - * mode *could* be (like rxsubchans in v4l2). I'll just - * follow what the API says... - * - * The most important point is, I think, that if someone does a get - * and then a set with this value, nothing should have changed. It - * used not to be the case and that was extremely confusing: one would - * do a GET, change mute to 1, then a SET with the same pointer and the - * stereo mode would have changed, the watcher thread killed... (see - * handler for VIDIOCSAUDIO) - */ struct msp3400c *msp = i2c_get_clientdata(client); - switch (msp->source) { - case 1: /* stereo or A|B */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2|VIDEO_SOUND_STEREO; - case 3: /* stereo or A */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_STEREO; - case 4: /* stereo or B */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_STEREO; - case 0: /* mono */ - return VIDEO_SOUND_MONO; - default: /* scart input */ - return VIDEO_SOUND_STEREO; - } -} - -/* set the current stereo mode given a v4l1 mode (Use V4L2 calls whenever possible) */ -static void msp34xxg_set_v4l1_stereo(struct i2c_client *client, int stereo) -{ - int source; - - if ((stereo & VIDEO_SOUND_LANG1) && (stereo & VIDEO_SOUND_LANG2)) - source = 1; /* stereo or A|B */ - else if (stereo & VIDEO_SOUND_LANG1) - source = 3; /* stereo or A */ - else if (stereo & VIDEO_SOUND_LANG2) - source = 4; /* stereo or B */ - else if (stereo & VIDEO_SOUND_STEREO) - source = 3; /* stereo or A */ - else - source = 0; /* mono only */ - msp34xxg_set_source(client, source); -} - -#if 0 -static void msp34xxg_get_v4l2_stereo(struct i2c_client *client, int *rxsubchans, - int *audmode) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - if (rxsubchans) { - int status = msp3400c_read(client, - I2C_MSP3400C_DEM, - 0x0200 /* STATUS */); - int is_bilingual = status&0x100; - int is_stereo = status&0x40; - int val=0; - if (is_stereo) - val |= V4L2_TUNER_SUB_STEREO; - else - val |= V4L2_TUNER_SUB_MONO; - if (is_bilingual) { - val |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; - /* I'm supposed to check whether it's SAP or not - * and set only LANG2/SAP in this case. Yet, the MSP - * does a lot of work to hide this and handle everything - * the same way. I don't want to work around it so unless - * this is a problem, I'll handle SAP just like lang1/lang2. - */ - } - dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", - status, is_stereo, is_bilingual, val); - *rxsubchans=val; - } - if (audmode) { - int val; - switch (msp->source) { - case 0: /* mono only */ - val = V4L2_TUNER_MODE_MONO; - break; - - case 1: /* stereo or A|B */ - case 2: /* scart input (stereo) */ - /* I'm surprised, but according to v4l2 spec, that - * is what V4L2_TUNER_MODE_STEREO *may* mean: - * > When the tuner receives bilingual audio it may play - * > different languages on the left and right channel or - * > the primary language on both channels. - * I chose the 2nd interpretation since there's no - * BILINGUAL mode. - */ - val = V4L2_TUNER_MODE_STEREO; - break; - - default: - case 3: /* stereo or A */ - val = V4L2_TUNER_MODE_LANG1; - break; - case 4: /* stereo or B */ - val = V4L2_TUNER_MODE_LANG2; - break; - } - dprintk("msp34xxg: source=%d -> audmode=%d\n", - msp->source, val); - *audmode=val; + int status = msp3400c_read(client, + I2C_MSP3400C_DEM, + 0x0200 /* STATUS */); + int is_bilingual = status&0x100; + int is_stereo = status&0x40; + + msp->rxsubchans = 0; + if (is_stereo) + msp->rxsubchans |= V4L2_TUNER_SUB_STEREO; + else + msp->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (is_bilingual) { + msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; + /* I'm supposed to check whether it's SAP or not + * and set only LANG2/SAP in this case. Yet, the MSP + * does a lot of work to hide this and handle everything + * the same way. I don't want to work around it so unless + * this is a problem, I'll handle SAP just like lang1/lang2. + */ } + dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", + status, is_stereo, is_bilingual, msp->rxsubchans); } -static void msp34xxg_set_v4l2_stereo(struct i2c_client *client, int audmode) +static void msp34xxg_set_audmode(struct i2c_client *client, int audmode) { + struct msp3400c *msp = i2c_get_clientdata(client); int source = 0; switch (audmode) { - case V4L2_TUNER_MODE_MONO: - source=0; /* mono only */ - break; - - case V4L2_TUNER_MODE_STEREO: - source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ - /* problem: that could also mean 2 (scart input) */ - break; - - case V4L2_TUNER_MODE_LANG1: - source=3; /* stereo or A */ - break; - - case V4L2_TUNER_MODE_LANG2: - source=4; /* stereo or B */ - break; - - default: /* doing nothing: a safe, sane default */ - return; + case V4L2_TUNER_MODE_MONO: + source=0; /* mono only */ + break; + case V4L2_TUNER_MODE_STEREO: + source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ + /* problem: that could also mean 2 (scart input) */ + break; + case V4L2_TUNER_MODE_LANG1: + source=3; /* stereo or A */ + break; + case V4L2_TUNER_MODE_LANG2: + source=4; /* stereo or B */ + break; + default: /* doing nothing: a safe, sane default */ + audmode = 0; + return; } - + msp->audmode = audmode; msp34xxg_set_source(client, source); } -#endif + /* ----------------------------------------------------------------------- */ @@ -1684,20 +1576,23 @@ static int msp_attach(struct i2c_adapter *adap, int addr, printk(" +simpler"); if (HAVE_RADIO(msp)) printk(" +radio"); - printk("\n"); /* version-specific initialization */ switch (msp->opmode) { case OPMODE_MANUAL: + printk(" mode=manual"); thread_func = msp3400c_thread; break; case OPMODE_SIMPLE: + printk(" mode=simple"); thread_func = msp3410d_thread; break; case OPMODE_SIMPLER: + printk(" mode=simpler"); msp34xxg_reset(c); break; } + printk("\n"); /* startup control thread if needed */ if (thread_func) { @@ -1771,6 +1666,81 @@ static void msp_wake_thread(struct i2c_client *client) wake_up_interruptible(&msp->wq); } +/* ----------------------------------------------------------------------- */ + +static int mode_v4l2_to_v4l1(int rxsubchans) +{ + int mode = 0; + + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + mode |= VIDEO_SOUND_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + mode |= VIDEO_SOUND_LANG2; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + mode |= VIDEO_SOUND_LANG1; + if (0 == mode) + mode |= VIDEO_SOUND_MONO; + return mode; +} + +static int mode_v4l1_to_v4l2(int mode) +{ + if (mode & VIDEO_SOUND_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (mode & VIDEO_SOUND_LANG2) + return V4L2_TUNER_MODE_LANG2; + if (mode & VIDEO_SOUND_LANG1) + return V4L2_TUNER_MODE_LANG1; + return V4L2_TUNER_MODE_MONO; +} + +static void msp_any_rescan(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + msp_wake_thread(client); + break; + case OPMODE_SIMPLER: + msp34xxg_reset(client); + break; + } +} + +static void msp_any_detect_stereo(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + autodetect_stereo(client); + break; + case OPMODE_SIMPLER: + msp34xxg_detect_stereo(client); + break; + } +} + +static void msp_any_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + msp->watch_stereo=0; + del_timer(&msp->wake_stereo); + msp3400c_set_audmode(client, audmode); + break; + case OPMODE_SIMPLER: + msp34xxg_set_audmode(client, audmode); + break; + } +} + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1810,11 +1780,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } if (scart) { - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); if (msp->opmode != OPMODE_SIMPLER) - msp3400c_setstereo(client, msp->stereo); + msp3400c_set_audmode(client, msp->audmode); } if (msp->active) msp->restart = 1; @@ -1824,7 +1795,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n"); - msp->watch_stereo=0; + msp->watch_stereo = 0; del_timer(&msp->wake_stereo); switch (msp->opmode) { case OPMODE_MANUAL: @@ -1865,12 +1836,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) va->bass = msp->bass; va->treble = msp->treble; - if (msp->opmode == OPMODE_SIMPLER) { - va->mode = msp34xxg_get_v4l1_stereo(client); - } else if (msp->norm != VIDEO_MODE_RADIO) { - autodetect_stereo(client); - va->mode = msp->stereo; - } + msp_any_detect_stereo(client); + va->mode = mode_v4l2_to_v4l1(msp->rxsubchans); break; } case VIDIOCSAUDIO: @@ -1889,16 +1856,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); - if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) { - if (msp->opmode == OPMODE_SIMPLER) { - msp34xxg_set_v4l1_stereo(client, va->mode); - } else { - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp->stereo = va->mode & 0x0f; - msp3400c_setstereo(client,va->mode & 0x0f); - } - } + if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) + msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); break; } case VIDIOCSCHAN: @@ -1907,58 +1866,45 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - msp_wake_thread(client); - break; - case OPMODE_SIMPLER: - msp34xxg_reset(client); - break; - } + msp_any_rescan(client); break; } + case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ dprintk(KERN_DEBUG "msp34xx: VIDIOCSFREQ\n"); - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - msp_wake_thread(client); - break; - case OPMODE_SIMPLER: - msp34xxg_reset(client); - break; - } + msp_any_rescan(client); break; } -#if 0 + /* --- v4l2 ioctls --- */ case VIDIOC_G_TUNER: { - struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; - vt->capability|=V4L2_TUNER_CAP_STEREO|V4L2_TUNER_CAP_LANG1|V4L2_TUNER_CAP_LANG2; - - /* get rxsubchans and audmode */ - if (IS_MSP34XX_G(msp)) { - msp34xxg_get_v4l2_stereo(client, &vt->rxsubchans, &vt->audmode); - } + struct v4l2_tuner *vt = arg; + + msp_any_detect_stereo(client); + vt->audmode = msp->audmode; + vt->rxsubchans = msp->rxsubchans; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1| + V4L2_TUNER_CAP_LANG2; break; } case VIDIOC_S_TUNER: { struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; + /* only set audmode */ - if (vt->audmode!=-1) { - if (IS_MSP34XX_G(msp)) { - msp34xxg_set_v4l2_stereo(client, vt->audmode); - } + if (vt->audmode != -1 && + vt->audmode != 0) { + msp_any_set_audmode(client, vt->audmode); } break; } -#endif + /* msp34xx specific */ case MSP_SET_MATRIX: { struct msp_matrix *mspm = arg; diff --git a/linux/drivers/media/video/msp3400.c b/linux/drivers/media/video/msp3400.c index a1991985c..c0f090a91 100644 --- a/linux/drivers/media/video/msp3400.c +++ b/linux/drivers/media/video/msp3400.c @@ -78,25 +78,22 @@ static int dolby = 0; static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual (msp34xxg only) 0x00a0-0x03c0 */ -#define DFP_COUNT 0x41 -static const int bl_dfp[] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a, - 0x0b, 0x0d, 0x0e, 0x10 -}; - struct msp3400c { int rev1,rev2; int opmode; int mode; int norm; - int stereo; int nicam_on; int acb; int main, second; /* sound carrier */ int input; int source; /* see msp34xxg_set_source */ + /* v4l2 */ + int audmode; + int rxsubchans; + int muted; int volume, balance; int bass, treble; @@ -430,8 +427,9 @@ static void msp3400c_setmode(struct i2c_client *client, int type) int i; dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type); - msp->mode = type; - msp->stereo = VIDEO_SOUND_MONO; + msp->mode = type; + msp->audmode = V4L2_TUNER_MODE_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */ msp_init_data[type].ad_cv); @@ -481,65 +479,67 @@ static void msp3400c_setmode(struct i2c_client *client, int type) } } -// given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask -static int best_audio_mode(int mode) +static int best_audio_mode(int rxsubchans) { - if (mode & VIDEO_SOUND_STEREO) - return VIDEO_SOUND_STEREO; - if (mode & VIDEO_SOUND_LANG1) - return VIDEO_SOUND_LANG1; - if (mode & VIDEO_SOUND_LANG2) - return VIDEO_SOUND_LANG2; - return VIDEO_SOUND_MONO; + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + return V4L2_TUNER_MODE_LANG1; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + return V4L2_TUNER_MODE_LANG2; + return V4L2_TUNER_MODE_MONO; } /* turn on/off nicam + stereo */ -static void msp3400c_setstereo(struct i2c_client *client, int mode) +static void msp3400c_set_audmode(struct i2c_client *client, int audmode) { static char *strmode[16] = { #if __GNUC__ >= 3 - [ 0 ... 15 ] = "invalid", + [ 0 ... 15 ] = "invalid", #endif - [ VIDEO_SOUND_MONO ] = "mono", - [ VIDEO_SOUND_STEREO ] = "stereo", - [ VIDEO_SOUND_LANG1 ] = "lang1", - [ VIDEO_SOUND_LANG2 ] = "lang2", + [ V4L2_TUNER_MODE_MONO ] = "mono", + [ V4L2_TUNER_MODE_STEREO ] = "stereo", + [ V4L2_TUNER_MODE_LANG1 ] = "lang1", + [ V4L2_TUNER_MODE_LANG2 ] = "lang2", }; struct msp3400c *msp = i2c_get_clientdata(client); int nicam=0; /* channel source: FM/AM or nicam */ int src=0; BUG_ON(msp->opmode == OPMODE_SIMPLER); + msp->audmode = audmode; /* switch demodulator */ switch (msp->mode) { case MSP_MODE_FM_TERRA: - dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001); break; - case VIDEO_SOUND_MONO: - case VIDEO_SOUND_LANG1: - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_MONO: + case V4L2_TUNER_MODE_LANG1: + case V4L2_TUNER_MODE_LANG2: msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000); break; } break; case MSP_MODE_FM_SAT: - dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",strmode[mode]); - switch (mode) { - case VIDEO_SOUND_MONO: + dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n", + strmode[audmode]); + switch (audmode) { + case V4L2_TUNER_MODE_MONO: msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; - case VIDEO_SOUND_STEREO: + case V4L2_TUNER_MODE_STEREO: msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); break; } @@ -547,21 +547,25 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) case MSP_MODE_FM_NICAM1: case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: - dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n", + strmode[audmode]); msp3400c_setcarrier(client,msp->second,msp->main); if (msp->nicam_on) nicam=0x0100; break; case MSP_MODE_BTSC: - dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n", + strmode[audmode]); nicam=0x0300; break; case MSP_MODE_EXTERN: - dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n", + strmode[audmode]); nicam = 0x0200; break; case MSP_MODE_FM_RADIO: - dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]); + dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n", + strmode[audmode]); break; default: dprintk(KERN_DEBUG "msp3400: mono setstereo\n"); @@ -569,15 +573,15 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) } /* switch audio */ - switch (mode) { - case VIDEO_SOUND_STEREO: + switch (audmode) { + case V4L2_TUNER_MODE_STEREO: src = 0x0020 | nicam; #if 0 /* spatial effect */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000); #endif break; - case VIDEO_SOUND_MONO: + case V4L2_TUNER_MODE_MONO: if (msp->mode == MSP_MODE_AM_NICAM) { dprintk("msp3400: switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ @@ -586,10 +590,10 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode) src = 0x0200; break; } - case VIDEO_SOUND_LANG1: + case V4L2_TUNER_MODE_LANG1: src = 0x0000 | nicam; break; - case VIDEO_SOUND_LANG2: + case V4L2_TUNER_MODE_LANG2: src = 0x0010 | nicam; break; } @@ -633,33 +637,6 @@ msp3400c_print_mode(struct msp3400c *msp) } } -#if 0 -static void -msp3400c_restore_dfp(struct i2c_client *client) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int i; - - for (i = 0; i < DFP_COUNT; i++) { - if (-1 == msp->dfp_regs[i]) - continue; - msp3400c_write(client,I2C_MSP3400C_DFP, i, msp->dfp_regs[i]); - } -} - -/* if the dfp_regs is set, set what's in there. - * Otherwise, set the default value */ -static int msp3400c_write_dfp_with_default(struct i2c_client *client, int addr, - int default_value) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - int value=default_value; - if ( addr< DFP_COUNT && -1 != msp->dfp_regs[addr] ) - value=msp->dfp_regs[addr]; - return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value); -} -#endif - /* ----------------------------------------------------------------------- */ struct REGISTER_DUMP { @@ -680,8 +657,8 @@ autodetect_stereo(struct i2c_client *client) { struct msp3400c *msp = i2c_get_clientdata(client); int val; - int newstereo = msp->stereo; - int newnicam = msp->nicam_on; + int rxsubchans = msp->rxsubchans; + int newnicam = msp->nicam_on; int update = 0; switch (msp->mode) { @@ -692,11 +669,11 @@ autodetect_stereo(struct i2c_client *client) dprintk(KERN_DEBUG "msp34xx: stereo detect register: %d\n",val); if (val > 4096) { - newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; } else if (val < -4096) { - newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; } else { - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } newnicam = 0; break; @@ -713,27 +690,27 @@ autodetect_stereo(struct i2c_client *client) switch ((val & 0x1e) >> 1) { case 0: case 8: - newstereo = VIDEO_SOUND_STEREO; + rxsubchans = V4L2_TUNER_SUB_STEREO; break; case 1: case 9: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1; break; case 2: case 10: - newstereo = VIDEO_SOUND_MONO - | VIDEO_SOUND_LANG1 - | VIDEO_SOUND_LANG2; + rxsubchans = V4L2_TUNER_SUB_MONO + | V4L2_TUNER_SUB_LANG1 + | V4L2_TUNER_SUB_LANG2; break; default: - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; break; } newnicam=1; } else { newnicam = 0; - newstereo = VIDEO_SOUND_MONO; + rxsubchans = V4L2_TUNER_SUB_MONO; } break; case MSP_MODE_BTSC: @@ -746,16 +723,16 @@ autodetect_stereo(struct i2c_client *client) (val & 0x0040) ? "stereo" : "mono", (val & 0x0080) ? ", nicam 2nd mono" : "", (val & 0x0100) ? ", bilingual/SAP" : ""); - newstereo = VIDEO_SOUND_MONO; - if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO; - if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1; + rxsubchans = V4L2_TUNER_SUB_MONO; + if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; + if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; break; } - if (newstereo != msp->stereo) { + if (rxsubchans != msp->rxsubchans) { update = 1; - dprintk(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n", - msp->stereo,newstereo); - msp->stereo = newstereo; + dprintk(KERN_DEBUG "msp34xx: watch: rxsubchans %d => %d\n", + msp->rxsubchans,rxsubchans); + msp->rxsubchans = rxsubchans; } if (newnicam != msp->nicam_on) { update = 1; @@ -800,7 +777,7 @@ static void watch_stereo(struct i2c_client *client) struct msp3400c *msp = i2c_get_clientdata(client); if (autodetect_stereo(client)) - msp3400c_setstereo(client,best_audio_mode(msp->stereo)); + msp3400c_set_audmode(client,best_audio_mode(msp->rxsubchans)); if (once) msp->watch_stereo = 0; if (msp->watch_stereo) @@ -934,7 +911,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_55[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 1 && HAVE_NICAM(msp)) { /* B/G NICAM */ @@ -961,7 +938,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; } else if (max2 == 0 && msp->norm == VIDEO_MODE_SECAM) { @@ -969,7 +946,7 @@ static int msp3400c_thread(void *data) msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); msp->nicam_on = 0; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); msp3400c_setcarrier(client, msp->second, msp->main); /* volume prescale for SCART (AM mono input) */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); @@ -992,8 +969,8 @@ static int msp3400c_thread(void *data) msp3400c_setmode(client, MSP_MODE_FM_TERRA); msp->nicam_on = 0; msp3400c_setcarrier(client, msp->second, msp->main); - msp->stereo = VIDEO_SOUND_MONO; - msp3400c_setstereo(client, VIDEO_SOUND_MONO); + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO); break; } @@ -1201,29 +1178,30 @@ static int msp3410d_thread(void *data) else msp->mode = MSP_MODE_FM_NICAM2; /* just turn on stereo */ - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 1; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; case 0x0009: msp->mode = MSP_MODE_AM_NICAM; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; msp->nicam_on = 1; - msp3400c_setstereo(client,VIDEO_SOUND_MONO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_MONO); msp->watch_stereo = 1; break; case 0x0020: /* BTSC */ /* just turn on stereo */ - msp->mode = MSP_MODE_BTSC; - msp->stereo = VIDEO_SOUND_STEREO; + msp->mode = MSP_MODE_BTSC; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; msp->nicam_on = 0; msp->watch_stereo = 1; - msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO); break; case 0x0040: /* FM radio */ msp->mode = MSP_MODE_FM_RADIO; - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp->nicam_on = 0; msp->watch_stereo = 0; /* not needed in theory if HAVE_RADIO(), but @@ -1249,7 +1227,8 @@ static int msp3410d_thread(void *data) case 0x0004: case 0x0005: msp->mode = MSP_MODE_FM_TERRA; - msp->stereo = VIDEO_SOUND_MONO; + msp->rxsubchans = V4L2_TUNER_SUB_MONO; + msp->audmode = V4L2_TUNER_MODE_MONO; msp->nicam_on = 0; msp->watch_stereo = 1; break; @@ -1420,148 +1399,61 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) msp->source=source; } -/* get the current stereo mode and return it as a V4L1 stereo value (Use V4L2 calls whenever possible) */ -static int msp34xxg_get_v4l1_stereo(struct i2c_client *client) +static void msp34xxg_detect_stereo(struct i2c_client *client) { - /* This is not really clear: the API says that the mode should - * be the current mode, but the old driver returned what the - * mode *could* be (like rxsubchans in v4l2). I'll just - * follow what the API says... - * - * The most important point is, I think, that if someone does a get - * and then a set with this value, nothing should have changed. It - * used not to be the case and that was extremely confusing: one would - * do a GET, change mute to 1, then a SET with the same pointer and the - * stereo mode would have changed, the watcher thread killed... (see - * handler for VIDIOCSAUDIO) - */ struct msp3400c *msp = i2c_get_clientdata(client); - switch (msp->source) { - case 1: /* stereo or A|B */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2|VIDEO_SOUND_STEREO; - case 3: /* stereo or A */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_STEREO; - case 4: /* stereo or B */ - return VIDEO_SOUND_LANG1|VIDEO_SOUND_STEREO; - case 0: /* mono */ - return VIDEO_SOUND_MONO; - default: /* scart input */ - return VIDEO_SOUND_STEREO; - } -} - -/* set the current stereo mode given a v4l1 mode (Use V4L2 calls whenever possible) */ -static void msp34xxg_set_v4l1_stereo(struct i2c_client *client, int stereo) -{ - int source; - - if ((stereo & VIDEO_SOUND_LANG1) && (stereo & VIDEO_SOUND_LANG2)) - source = 1; /* stereo or A|B */ - else if (stereo & VIDEO_SOUND_LANG1) - source = 3; /* stereo or A */ - else if (stereo & VIDEO_SOUND_LANG2) - source = 4; /* stereo or B */ - else if (stereo & VIDEO_SOUND_STEREO) - source = 3; /* stereo or A */ - else - source = 0; /* mono only */ - msp34xxg_set_source(client, source); -} - -#if 0 -static void msp34xxg_get_v4l2_stereo(struct i2c_client *client, int *rxsubchans, - int *audmode) -{ - struct msp3400c *msp = i2c_get_clientdata(client); - - if (rxsubchans) { - int status = msp3400c_read(client, - I2C_MSP3400C_DEM, - 0x0200 /* STATUS */); - int is_bilingual = status&0x100; - int is_stereo = status&0x40; - int val=0; - if (is_stereo) - val |= V4L2_TUNER_SUB_STEREO; - else - val |= V4L2_TUNER_SUB_MONO; - if (is_bilingual) { - val |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; - /* I'm supposed to check whether it's SAP or not - * and set only LANG2/SAP in this case. Yet, the MSP - * does a lot of work to hide this and handle everything - * the same way. I don't want to work around it so unless - * this is a problem, I'll handle SAP just like lang1/lang2. - */ - } - dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", - status, is_stereo, is_bilingual, val); - *rxsubchans=val; - } - if (audmode) { - int val; - switch (msp->source) { - case 0: /* mono only */ - val = V4L2_TUNER_MODE_MONO; - break; - - case 1: /* stereo or A|B */ - case 2: /* scart input (stereo) */ - /* I'm surprised, but according to v4l2 spec, that - * is what V4L2_TUNER_MODE_STEREO *may* mean: - * > When the tuner receives bilingual audio it may play - * > different languages on the left and right channel or - * > the primary language on both channels. - * I chose the 2nd interpretation since there's no - * BILINGUAL mode. - */ - val = V4L2_TUNER_MODE_STEREO; - break; - - default: - case 3: /* stereo or A */ - val = V4L2_TUNER_MODE_LANG1; - break; - case 4: /* stereo or B */ - val = V4L2_TUNER_MODE_LANG2; - break; - } - dprintk("msp34xxg: source=%d -> audmode=%d\n", - msp->source, val); - *audmode=val; + int status = msp3400c_read(client, + I2C_MSP3400C_DEM, + 0x0200 /* STATUS */); + int is_bilingual = status&0x100; + int is_stereo = status&0x40; + + msp->rxsubchans = 0; + if (is_stereo) + msp->rxsubchans |= V4L2_TUNER_SUB_STEREO; + else + msp->rxsubchans |= V4L2_TUNER_SUB_MONO; + if (is_bilingual) { + msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2; + /* I'm supposed to check whether it's SAP or not + * and set only LANG2/SAP in this case. Yet, the MSP + * does a lot of work to hide this and handle everything + * the same way. I don't want to work around it so unless + * this is a problem, I'll handle SAP just like lang1/lang2. + */ } + dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", + status, is_stereo, is_bilingual, msp->rxsubchans); } -static void msp34xxg_set_v4l2_stereo(struct i2c_client *client, int audmode) +static void msp34xxg_set_audmode(struct i2c_client *client, int audmode) { + struct msp3400c *msp = i2c_get_clientdata(client); int source = 0; switch (audmode) { - case V4L2_TUNER_MODE_MONO: - source=0; /* mono only */ - break; - - case V4L2_TUNER_MODE_STEREO: - source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ - /* problem: that could also mean 2 (scart input) */ - break; - - case V4L2_TUNER_MODE_LANG1: - source=3; /* stereo or A */ - break; - - case V4L2_TUNER_MODE_LANG2: - source=4; /* stereo or B */ - break; - - default: /* doing nothing: a safe, sane default */ - return; + case V4L2_TUNER_MODE_MONO: + source=0; /* mono only */ + break; + case V4L2_TUNER_MODE_STEREO: + source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ + /* problem: that could also mean 2 (scart input) */ + break; + case V4L2_TUNER_MODE_LANG1: + source=3; /* stereo or A */ + break; + case V4L2_TUNER_MODE_LANG2: + source=4; /* stereo or B */ + break; + default: /* doing nothing: a safe, sane default */ + audmode = 0; + return; } - + msp->audmode = audmode; msp34xxg_set_source(client, source); } -#endif + /* ----------------------------------------------------------------------- */ @@ -1684,20 +1576,23 @@ static int msp_attach(struct i2c_adapter *adap, int addr, printk(" +simpler"); if (HAVE_RADIO(msp)) printk(" +radio"); - printk("\n"); /* version-specific initialization */ switch (msp->opmode) { case OPMODE_MANUAL: + printk(" mode=manual"); thread_func = msp3400c_thread; break; case OPMODE_SIMPLE: + printk(" mode=simple"); thread_func = msp3410d_thread; break; case OPMODE_SIMPLER: + printk(" mode=simpler"); msp34xxg_reset(c); break; } + printk("\n"); /* startup control thread if needed */ if (thread_func) { @@ -1771,6 +1666,81 @@ static void msp_wake_thread(struct i2c_client *client) wake_up_interruptible(&msp->wq); } +/* ----------------------------------------------------------------------- */ + +static int mode_v4l2_to_v4l1(int rxsubchans) +{ + int mode = 0; + + if (rxsubchans & V4L2_TUNER_SUB_STEREO) + mode |= VIDEO_SOUND_STEREO; + if (rxsubchans & V4L2_TUNER_SUB_LANG2) + mode |= VIDEO_SOUND_LANG2; + if (rxsubchans & V4L2_TUNER_SUB_LANG1) + mode |= VIDEO_SOUND_LANG1; + if (0 == mode) + mode |= VIDEO_SOUND_MONO; + return mode; +} + +static int mode_v4l1_to_v4l2(int mode) +{ + if (mode & VIDEO_SOUND_STEREO) + return V4L2_TUNER_MODE_STEREO; + if (mode & VIDEO_SOUND_LANG2) + return V4L2_TUNER_MODE_LANG2; + if (mode & VIDEO_SOUND_LANG1) + return V4L2_TUNER_MODE_LANG1; + return V4L2_TUNER_MODE_MONO; +} + +static void msp_any_rescan(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + msp_wake_thread(client); + break; + case OPMODE_SIMPLER: + msp34xxg_reset(client); + break; + } +} + +static void msp_any_detect_stereo(struct i2c_client *client) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + autodetect_stereo(client); + break; + case OPMODE_SIMPLER: + msp34xxg_detect_stereo(client); + break; + } +} + +static void msp_any_set_audmode(struct i2c_client *client, int audmode) +{ + struct msp3400c *msp = i2c_get_clientdata(client); + + switch (msp->opmode) { + case OPMODE_MANUAL: + case OPMODE_SIMPLE: + msp->watch_stereo=0; + del_timer(&msp->wake_stereo); + msp3400c_set_audmode(client, audmode); + break; + case OPMODE_SIMPLER: + msp34xxg_set_audmode(client, audmode); + break; + } +} + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1810,11 +1780,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } if (scart) { - msp->stereo = VIDEO_SOUND_STEREO; + msp->rxsubchans = V4L2_TUNER_SUB_STEREO; + msp->audmode = V4L2_TUNER_MODE_STEREO; msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); if (msp->opmode != OPMODE_SIMPLER) - msp3400c_setstereo(client, msp->stereo); + msp3400c_set_audmode(client, msp->audmode); } if (msp->active) msp->restart = 1; @@ -1824,7 +1795,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: AUDC_SET_RADIO\n"); msp->norm = VIDEO_MODE_RADIO; dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n"); - msp->watch_stereo=0; + msp->watch_stereo = 0; del_timer(&msp->wake_stereo); switch (msp->opmode) { case OPMODE_MANUAL: @@ -1865,12 +1836,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) va->bass = msp->bass; va->treble = msp->treble; - if (msp->opmode == OPMODE_SIMPLER) { - va->mode = msp34xxg_get_v4l1_stereo(client); - } else if (msp->norm != VIDEO_MODE_RADIO) { - autodetect_stereo(client); - va->mode = msp->stereo; - } + msp_any_detect_stereo(client); + va->mode = mode_v4l2_to_v4l1(msp->rxsubchans); break; } case VIDIOCSAUDIO: @@ -1889,16 +1856,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); - if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) { - if (msp->opmode == OPMODE_SIMPLER) { - msp34xxg_set_v4l1_stereo(client, va->mode); - } else { - msp->watch_stereo=0; - del_timer(&msp->wake_stereo); - msp->stereo = va->mode & 0x0f; - msp3400c_setstereo(client,va->mode & 0x0f); - } - } + if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) + msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode)); break; } case VIDIOCSCHAN: @@ -1907,58 +1866,45 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm); msp->norm = vc->norm; - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - msp_wake_thread(client); - break; - case OPMODE_SIMPLER: - msp34xxg_reset(client); - break; - } + msp_any_rescan(client); break; } + case VIDIOCSFREQ: + case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ dprintk(KERN_DEBUG "msp34xx: VIDIOCSFREQ\n"); - switch (msp->opmode) { - case OPMODE_MANUAL: - case OPMODE_SIMPLE: - msp_wake_thread(client); - break; - case OPMODE_SIMPLER: - msp34xxg_reset(client); - break; - } + msp_any_rescan(client); break; } -#if 0 + /* --- v4l2 ioctls --- */ case VIDIOC_G_TUNER: { - struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; - vt->capability|=V4L2_TUNER_CAP_STEREO|V4L2_TUNER_CAP_LANG1|V4L2_TUNER_CAP_LANG2; - - /* get rxsubchans and audmode */ - if (IS_MSP34XX_G(msp)) { - msp34xxg_get_v4l2_stereo(client, &vt->rxsubchans, &vt->audmode); - } + struct v4l2_tuner *vt = arg; + + msp_any_detect_stereo(client); + vt->audmode = msp->audmode; + vt->rxsubchans = msp->rxsubchans; + vt->capability = V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1| + V4L2_TUNER_CAP_LANG2; break; } case VIDIOC_S_TUNER: { struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; + /* only set audmode */ - if (vt->audmode!=-1) { - if (IS_MSP34XX_G(msp)) { - msp34xxg_set_v4l2_stereo(client, vt->audmode); - } + if (vt->audmode != -1 && + vt->audmode != 0) { + msp_any_set_audmode(client, vt->audmode); } break; } -#endif + /* msp34xx specific */ case MSP_SET_MATRIX: { struct msp_matrix *mspm = arg; |