[alsa-devel] [PATCH 1/2] opti93x: add support for Opti93x codec in cs4231-lib
From: Krzysztof Helt krzysztof.h1@wp.pl
This patch adds support for WSS compatible Opti93x codec to the cs4231-lib.
Signed-off-by: Krzysztof Helt krzysztof.h1@wp.pl
--- This patch was sent some time ago but was not accepted due to regression of the driver on the opti 930 chip. The regression is fixed with already accepted patch, so it should work now. The patch was prepared against the 2.6.26-rc5 kernel. Tested on Opti 930, 931 and 933.
The previous repost: http://mailman.alsa-project.org/pipermail/alsa-devel/2008-January/005679.htm...
diff -urp linux-rc2/include/sound/cs4231-regs.h linux-rc5/include/sound/cs4231-regs.h --- linux-rc2/include/sound/cs4231-regs.h 2008-04-17 04:49:44.000000000 +0200 +++ linux-rc5/include/sound/cs4231-regs.h 2008-06-08 00:33:55.041903713 +0200 @@ -177,4 +177,12 @@ #define CS4236_RIGHT_WAVE 0x1c /* right wavetable serial port volume */ #define CS4236_VERSION 0x9c /* chip version and ID */
+/* definitions for extended registers - OPTI93X */ +#define OPTi931_AUX_LEFT_INPUT 0x10 +#define OPTi931_AUX_RIGHT_INPUT 0x11 +#define OPTi93X_MIC_LEFT_INPUT 0x14 +#define OPTi93X_MIC_RIGHT_INPUT 0x15 +#define OPTi93X_OUT_LEFT 0x16 +#define OPTi93X_OUT_RIGHT 0x17 + #endif /* __SOUND_CS4231_REGS_H */ diff -urp linux-rc2/include/sound/cs4231.h linux-rc5/include/sound/cs4231.h --- linux-rc2/include/sound/cs4231.h 2008-04-17 04:49:44.000000000 +0200 +++ linux-rc5/include/sound/cs4231.h 2008-06-08 00:35:54.808064369 +0200 @@ -58,6 +58,7 @@ /* compatible, but clones */ #define CS4231_HW_INTERWAVE 0x1000 /* InterWave chip */ #define CS4231_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */ +#define CS4231_HW_OPTI93X 0x1102 /* Opti 930/931/933 */
/* defines for codec.hwshare */ #define CS4231_HWSHARE_IRQ (1<<0) @@ -120,6 +121,8 @@ unsigned char snd_cs4236_ext_in(struct s void snd_cs4231_mce_up(struct snd_cs4231 *chip); void snd_cs4231_mce_down(struct snd_cs4231 *chip);
+void snd_cs4231_overrange(struct snd_cs4231 *chip); + irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id);
const char *snd_cs4231_chip_id(struct snd_cs4231 *chip); diff -urp linux-rc2/sound/isa/cs423x/cs4231_lib.c linux-rc5/sound/isa/cs423x/cs4231_lib.c --- linux-rc2/sound/isa/cs423x/cs4231_lib.c 2008-04-17 04:49:44.000000000 +0200 +++ linux-rc5/sound/isa/cs423x/cs4231_lib.c 2008-06-08 00:38:32.130878968 +0200 @@ -119,6 +119,42 @@ static unsigned char snd_cs4231_original 0x00, /* 1f/31 - cbrl */ };
+static unsigned char snd_opti93x_original_image[32] = +{ + 0x00, /* 00/00 - l_mixout_outctrl */ + 0x00, /* 01/01 - r_mixout_outctrl */ + 0x88, /* 02/02 - l_cd_inctrl */ + 0x88, /* 03/03 - r_cd_inctrl */ + 0x88, /* 04/04 - l_a1/fm_inctrl */ + 0x88, /* 05/05 - r_a1/fm_inctrl */ + 0x80, /* 06/06 - l_dac_inctrl */ + 0x80, /* 07/07 - r_dac_inctrl */ + 0x00, /* 08/08 - ply_dataform_reg */ + 0x00, /* 09/09 - if_conf */ + 0x00, /* 0a/10 - pin_ctrl */ + 0x00, /* 0b/11 - err_init_reg */ + 0x0a, /* 0c/12 - id_reg */ + 0x00, /* 0d/13 - reserved */ + 0x00, /* 0e/14 - ply_upcount_reg */ + 0x00, /* 0f/15 - ply_lowcount_reg */ + 0x88, /* 10/16 - reserved/l_a1_inctrl */ + 0x88, /* 11/17 - reserved/r_a1_inctrl */ + 0x88, /* 12/18 - l_line_inctrl */ + 0x88, /* 13/19 - r_line_inctrl */ + 0x88, /* 14/20 - l_mic_inctrl */ + 0x88, /* 15/21 - r_mic_inctrl */ + 0x80, /* 16/22 - l_out_outctrl */ + 0x80, /* 17/23 - r_out_outctrl */ + 0x00, /* 18/24 - reserved */ + 0x00, /* 19/25 - reserved */ + 0x00, /* 1a/26 - reserved */ + 0x00, /* 1b/27 - reserved */ + 0x00, /* 1c/28 - cap_dataform_reg */ + 0x00, /* 1d/29 - reserved */ + 0x00, /* 1e/30 - cap_upcount_reg */ + 0x00 /* 1f/31 - cap_lowcount_reg */ +}; + /* * Basic I/O functions */ @@ -895,7 +931,7 @@ static int snd_cs4231_capture_prepare(st return 0; }
-static void snd_cs4231_overrange(struct snd_cs4231 *chip) +void snd_cs4231_overrange(struct snd_cs4231 *chip) { unsigned long flags; unsigned char res; @@ -1054,8 +1090,11 @@ static int snd_cs4231_probe(struct snd_c chip->image[CS4231_IFACE_CTRL] = (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) | (chip->single_dma ? CS4231_SINGLE_DMA : 0); - chip->image[CS4231_ALT_FEATURE_1] = 0x80; - chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01; + if (chip->hardware != CS4231_HW_OPTI93X) { + chip->image[CS4231_ALT_FEATURE_1] = 0x80; + chip->image[CS4231_ALT_FEATURE_2] = + chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01; + } ptr = (unsigned char *) &chip->image; snd_cs4231_mce_down(chip); spin_lock_irqsave(&chip->reg_lock, flags); @@ -1376,6 +1415,7 @@ const char *snd_cs4231_chip_id(struct sn case CS4231_HW_INTERWAVE: return "AMD InterWave"; case CS4231_HW_OPL3SA2: return chip->card->shortname; case CS4231_HW_AD1845: return "AD1845"; + case CS4231_HW_OPTI93X: return "OPTi 93x"; default: return "???"; } } @@ -1401,8 +1441,13 @@ static int snd_cs4231_new(struct snd_car chip->rate_constraint = snd_cs4231_xrate; chip->set_playback_format = snd_cs4231_playback_format; chip->set_capture_format = snd_cs4231_capture_format; - memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); - + if (chip->hardware == CS4231_HW_OPTI93X) + memcpy(&chip->image, &snd_opti93x_original_image, + sizeof(snd_opti93x_original_image)); + else + memcpy(&chip->image, &snd_cs4231_original_image, + sizeof(snd_cs4231_original_image)); + *rchip = chip; return 0; } @@ -1790,6 +1835,48 @@ CS4231_SINGLE("Loopback Capture Switch", CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1) };
+static struct snd_kcontrol_new snd_opti93x_controls[] = { +CS4231_DOUBLE("Master Playback Switch", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), +CS4231_DOUBLE("Master Playback Volume", 0, + OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), +CS4231_DOUBLE("PCM Playback Switch", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +CS4231_DOUBLE("PCM Playback Volume", 0, + CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1), +CS4231_DOUBLE("FM Playback Switch", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("FM Playback Volume", 0, + CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1), +CS4231_DOUBLE("Line Playback Switch", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +CS4231_DOUBLE("Line Playback Volume", 0, + CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1), +CS4231_DOUBLE("Mic Playback Switch", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Mic Playback Volume", 0, + OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), +CS4231_DOUBLE("Mic Boost", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), +CS4231_DOUBLE("CD Playback Switch", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("CD Playback Volume", 0, + CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1), +CS4231_DOUBLE("Aux Playback Switch", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Aux Playback Volume", 0, + OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), +CS4231_DOUBLE("Capture Volume", 0, + CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +{ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = snd_cs4231_info_mux, + .get = snd_cs4231_get_mux, + .put = snd_cs4231_put_mux, +} +}; + int snd_cs4231_mixer(struct snd_cs4231 *chip) { struct snd_card *card; @@ -1802,10 +1889,22 @@ int snd_cs4231_mixer(struct snd_cs4231 *
strcpy(card->mixername, chip->pcm->name);
- for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0) - return err; - } + if (chip->hardware == CS4231_HW_OPTI93X) + for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_opti93x_controls[idx], + chip)); + if (err < 0) + return err; + } + else + for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { + err = snd_ctl_add(card, + snd_ctl_new1(&snd_cs4231_controls[idx], + chip)); + if (err < 0) + return err; + } return 0; }
@@ -1815,6 +1914,7 @@ EXPORT_SYMBOL(snd_cs4236_ext_out); EXPORT_SYMBOL(snd_cs4236_ext_in); EXPORT_SYMBOL(snd_cs4231_mce_up); EXPORT_SYMBOL(snd_cs4231_mce_down); +EXPORT_SYMBOL(snd_cs4231_overrange); EXPORT_SYMBOL(snd_cs4231_interrupt); EXPORT_SYMBOL(snd_cs4231_chip_id); EXPORT_SYMBOL(snd_cs4231_create);
--------------------------------------------------------------- Sprawdz jak zdobyc zdrowy usmiech! Kliknij >> http://link.interia.pl/f1e26
On 09-06-08 23:07, Krzysztof Helt wrote:
From: Krzysztof Helt krzysztof.h1@wp.pl
This patch adds support for WSS compatible Opti93x codec to the cs4231-lib.
Signed-off-by: Krzysztof Helt krzysztof.h1@wp.pl
This patch was sent some time ago but was not accepted due to regression of the driver on the opti 930 chip. The regression is fixed with already accepted patch, so it should work now.
Could you elaborate a bit? Yesterday's patch removing the QS1000 from 82C930 fixed the 930 staying silent but the regression this introduced previously at least appeared to be a different one.
Post QS1000, 82C930 appeared to work fine, just didn't actually produce a signal onto its analog out. Post CS4231, 82C930 wasn't just silent but didn't even generate any interrupts anymore.
I didn't compare with your old code...
The patch was prepared against the 2.6.26-rc5 kernel. Tested on Opti 930, 931 and 933.
Tested-by: Rene Herman rene.herman@gmail.com
also on 930, 931 and 933 for playback, capture on 930 and 931. So whatever the answer to the above, it appears that problem is now also fixed. Which is very good; this is a rather welcome unification/cleanup as far as I'm concerned.
The mixer levels do seem different between the old and new driver. Does that make sense? The new one appears to be a bit louder so there might be an offset issue somewhere I suppose. I didn't compare that closely.
Rene.
On Tue, 10 Jun 2008 01:21:43 +0200 Rene Herman rene.herman@keyaccess.nl wrote:
On 09-06-08 23:07, Krzysztof Helt wrote:
From: Krzysztof Helt krzysztof.h1@wp.pl
This patch adds support for WSS compatible Opti93x codec to the cs4231-lib.
Signed-off-by: Krzysztof Helt krzysztof.h1@wp.pl
This patch was sent some time ago but was not accepted due to regression of the driver on the opti 930 chip. The regression is fixed with already accepted patch, so it should work now.
Could you elaborate a bit? Yesterday's patch removing the QS1000 from 82C930 fixed the 930 staying silent but the regression this introduced previously at least appeared to be a different one.
Post QS1000, 82C930 appeared to work fine, just didn't actually produce a signal onto its analog out. Post CS4231, 82C930 wasn't just silent but didn't even generate any interrupts anymore.
It seems that setting something in the digital input register broke sound on the Opti930 before cs4321 patches (silence) and after using cs4231 library (no interrupts).
I didn't compare with your old code...
No changes in the code. Finally, I hunted the opti 930 on an online auction, so I was able to test the old patches. After the QS1000 patch everything got magically fixed and no changes were required.
also on 930, 931 and 933 for playback, capture on 930 and 931. So whatever the answer to the above, it appears that problem is now also fixed. Which is very good; this is a rather welcome unification/cleanup as far as I'm concerned.
The mixer levels do seem different between the old and new driver. Does that make sense? The new one appears to be a bit louder so there might be an offset issue somewhere I suppose. I didn't compare that closely.
I will check this. I haven't had time yet. I will try investigating this week.
Regards, Krzysztof
--------------------------------------------------------------- Sprawdz jak zdobyc zdrowy usmiech! Kliknij >> http://link.interia.pl/f1e26
On Tue, 10 Jun 2008 01:21:43 +0200 Rene Herman rene.herman@keyaccess.nl wrote:
The mixer levels do seem different between the old and new driver. Does that make sense? The new one appears to be a bit louder so there might be an offset issue somewhere I suppose. I didn't compare that closely.
I have tried to reproduce this on an opti930 card. I do not hear any difference. I tried at 100% and 75% (both PCM and Master) levels. I used the script which reloaded an old and new driver and played a wav file. I run it in a loop. The thing I noticed is that the old driver often produced noise (say more than 1 in 4 tries) instead of the sound. The new driver (cs4231) never. The old and new driver produced a click before playing the sound (50% probability).
I have checked the mixer code. It is not changed.
What do you do to get a different sound level? (card model, level settings).
Regards, Krzysztof
---------------------------------------------------------------------- Podbij Dziki Zachod!Gra strategiczna online Sprawdz >>> http://link.interia.pl/f1dff
On 15-06-08 19:33, Krzysztof Helt wrote:
I have tried to reproduce this on an opti930 card. I do not hear any difference. I tried at 100% and 75% (both PCM and Master) levels. I used the script which reloaded an old and new driver and played a wav file. I run it in a loop. The thing I noticed is that the old driver often produced noise (say more than 1 in 4 tries) instead of the sound. The new driver (cs4231) never. The old and new driver produced a click before playing the sound (50% probability).
I have checked the mixer code. It is not changed.
What do you do to get a different sound level? (card model, level settings).
I've restested (quite extensively by now...) and have not been able to reproduce. I do have quit a few 931 and 933 cards, all alike physically but likely not all the same post the onboard amp. What MAY have happened is that I mistakingly grabbed another one during testing while I was busy switching 930, 931 and 933 cards (and kernels).
Doubt it a bit but well, I'm just not reproducing now. I do believe it was a 931 on which I observed the level difference; let's just conclude this must have been an error on my part.
Rene.
participants (2)
-
Krzysztof Helt
-
Rene Herman