Update of /cvsroot/alsa/alsa-driver/lowlevel/pci
In directory usw-pr-cvs1:/tmp/cvs-serv21598/lowlevel/pci
Modified Files:
Tag: ver-0-5-patches
ymfpci.c
Log Message:
Added more mixer volume controls.
Index: ymfpci.c
===================================================================
RCS file: /cvsroot/alsa/alsa-driver/lowlevel/pci/ymfpci.c,v
retrieving revision 1.2.2.16
retrieving revision 1.2.2.17
diff -u -r1.2.2.16 -r1.2.2.17
--- ymfpci.c 2001/06/01 12:17:23 1.2.2.16
+++ ymfpci.c 2001/07/10 12:58:43 1.2.2.17
@@ -181,7 +181,8 @@
spin_lock_irqsave(&codec->reg_lock, flags);
if (codec->start_count++ > 1)
goto __end;
- snd_ymfpci_writel(codec, YDSXGR_MODE, 3);
+ snd_ymfpci_writel(codec, YDSXGR_MODE,
+ snd_ymfpci_readl(codec, YDSXGR_MODE) | 3);
codec->active_bank = snd_ymfpci_readl(codec, YDSXGR_CTRLSELECT);
__end:
spin_unlock_irqrestore(&codec->reg_lock, flags);
@@ -195,7 +196,8 @@
spin_lock_irqsave(&codec->reg_lock, flags);
if (--codec->start_count > 0)
goto __end;
- snd_ymfpci_writel(codec, YDSXGR_MODE, 0);
+ snd_ymfpci_writel(codec, YDSXGR_MODE,
+ snd_ymfpci_readl(codec, YDSXGR_MODE) & ~3);
while (timeout-- > 0) {
if ((snd_ymfpci_readl(codec, YDSXGR_STATUS) & 2) == 0)
break;
@@ -827,6 +829,8 @@
spin_lock_irqsave(&codec->reg_lock, flags);
snd_ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL,
snd_ymfpci_readw(codec, YDSXGR_SPDIFOUTCTRL) | 2);
+ snd_ymfpci_writel(codec, YDSXGR_MODE,
+ snd_ymfpci_readl(codec, YDSXGR_MODE) | (1 << 30));
spin_unlock_irqrestore(&codec->reg_lock, flags);
return 0;
}
@@ -973,6 +977,8 @@
unsigned long flags;
spin_lock_irqsave(&codec->reg_lock, flags);
+ snd_ymfpci_writel(codec, YDSXGR_MODE,
+ snd_ymfpci_readl(codec, YDSXGR_MODE) & ~(1 << 30));
snd_ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL,
snd_ymfpci_readw(codec, YDSXGR_SPDIFOUTCTRL) & ~2);
snd_ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS,
@@ -1095,9 +1101,10 @@
snd_switch_t * uswitch)
{
ymfpci_t *codec = snd_magic_cast(ymfpci_t, kswitch->private_data, -ENXIO);
+ int reg = (int)kswitch->private_value;
uswitch->type = SND_SW_TYPE_BOOLEAN;
- uswitch->value.enable = snd_ymfpci_readl(codec, YDSXGR_SPDIFOUTCTRL) & 1;
+ uswitch->value.enable = snd_ymfpci_readl(codec, reg) & 1;
return 0;
}
@@ -1107,85 +1114,119 @@
{
unsigned long flags;
ymfpci_t *codec = snd_magic_cast(ymfpci_t, kswitch->private_data, -ENXIO);
+ int reg = (int)kswitch->private_value;
if (uswitch->type != SND_SW_TYPE_BOOLEAN)
return -EINVAL;
spin_lock_irqsave(&codec->reg_lock, flags);
- snd_ymfpci_writel(codec, YDSXGR_SPDIFOUTCTRL,
- (snd_ymfpci_readl(codec, YDSXGR_SPDIFOUTCTRL) & ~1) |
+ snd_ymfpci_writel(codec, reg,
+ (snd_ymfpci_readl(codec, reg) & ~1) |
(uswitch->value.enable ? 1 : 0));
spin_unlock_irqrestore(&codec->reg_lock, flags);
return 0;
}
-static snd_kswitch_t snd_ymfpci_mixer_spdif =
+static snd_kswitch_t snd_ymfpci_mixer_spdif_out =
{
name: "S/PDIF output",
get: (snd_get_switch_t *)snd_ymfpci_get_spdif,
set: (snd_set_switch_t *)snd_ymfpci_set_spdif,
+ private_value: YDSXGR_SPDIFOUTCTRL
};
+static snd_kswitch_t snd_ymfpci_mixer_spdif_in =
+{
+ name: "S/PDIF input",
+ get: (snd_get_switch_t *)snd_ymfpci_get_spdif,
+ set: (snd_set_switch_t *)snd_ymfpci_set_spdif,
+ private_value: YDSXGR_SPDIFINCTRL
+};
+
/*
* mixer elements for record source
*/
+
+#define YMFPCI_VOL_MAX 16383
+
+static int snd_ymfpci_mixer_volume_update(snd_kmixer_element_t *element, int w_flag, int *volume, int reg_offset)
+{
+ ymfpci_t *codec;
+ int change = 0;
+ unsigned long flags;
+ unsigned int volreg, oldreg;
+ codec = snd_magic_cast(ymfpci_t, element->private_data, -ENXIO);
+ if (w_flag) {
+ volreg = (unsigned int)volume[0] | ((unsigned int)volume[1] << 16);
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ oldreg = snd_ymfpci_readl(codec, reg_offset);
+ snd_ymfpci_writel(codec, reg_offset, volreg);
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ change = (oldreg != volreg);
+ } else {
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ volume[0] = snd_ymfpci_readw(codec, reg_offset);
+ volume[1] = snd_ymfpci_readw(codec, reg_offset + 2);
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ }
+ return change;
+}
-#define REC_VOL_MAX 16383
+static int snd_ymfpci_mixer_volume_group(snd_kmixer_group_t *group,
+ snd_kmixer_file_t *file, int w_flag,
+ snd_mixer_group_t *ugroup,
+ snd_kmixer_element_t *me,
+ int reg_offset)
+{
+ ymfpci_t *codec;
+ int voices[2];
+ int change = 0;
+ codec = snd_magic_cast(ymfpci_t, group->private_data, -ENXIO);
+ if (!w_flag) {
+ ugroup->channels = SND_MIXER_CHN_MASK_STEREO;
+ ugroup->caps = SND_MIXER_GRPCAP_VOLUME;
+ ugroup->min = 0;
+ ugroup->max = YMFPCI_VOL_MAX;
+ ugroup->mute = 0;
+ snd_ymfpci_mixer_volume_update(me, 0, voices, reg_offset);
+ ugroup->volume.names.front_left = voices[0];
+ ugroup->volume.names.front_right = voices[1];
+ } else {
+ voices[0] = ugroup->volume.names.front_left;
+ voices[1] = ugroup->volume.names.front_right;
+ if (snd_ymfpci_mixer_volume_update(me, 1, voices, reg_offset)) {
+ snd_mixer_element_value_change_all_file(file, me, 0);
+ change = 1;
+ }
+ }
+ return change;
+}
-#define RECORD_VOLUME(ename,reg_offset)\
-static int snd_ymfpci_volume_##ename(snd_kmixer_element_t *element, int w_flag, int *volume)\
+#define YMFPCI_VOLUME(ename,reg_offset)\
+static int snd_ymfpci_mixer_volume_##ename(snd_kmixer_element_t *element, int w_flag, int *volume)\
{\
- ymfpci_t *codec;\
- int change = 0;\
- unsigned long flags;\
- unsigned int volreg, oldreg;\
- codec = snd_magic_cast(ymfpci_t, element->private_data, -ENXIO);\
- if (w_flag) {\
- volreg = (unsigned int)volume[0] | ((unsigned int)volume[1] << 16);\
- spin_lock_irqsave(&codec->reg_lock, flags);\
- oldreg = snd_ymfpci_readl(codec, reg_offset);\
- snd_ymfpci_writel(codec, reg_offset, volreg);\
- spin_unlock_irqrestore(&codec->reg_lock, flags);\
- change = (oldreg != volreg);\
- } else {\
- spin_lock_irqsave(&codec->reg_lock, flags);\
- volume[0] = snd_ymfpci_readw(codec, reg_offset);\
- volume[1] = snd_ymfpci_readw(codec, reg_offset + 2);\
- spin_unlock_irqrestore(&codec->reg_lock, flags);\
- }\
- return change;\
+ return snd_ymfpci_mixer_volume_update(element, w_flag, volume, reg_offset);\
}\
static int snd_ymfpci_mixer_group_##ename(snd_kmixer_group_t *group,\
snd_kmixer_file_t *file, int w_flag,\
snd_mixer_group_t *ugroup)\
{\
- ymfpci_t *codec;\
- int voices[2];\
- int change = 0;\
- codec = snd_magic_cast(ymfpci_t, group->private_data, -ENXIO);\
- if (!w_flag) {\
- ugroup->channels = SND_MIXER_CHN_MASK_STEREO;\
- ugroup->caps = SND_MIXER_GRPCAP_VOLUME;\
- ugroup->min = 0;\
- ugroup->max = REC_VOL_MAX;\
- ugroup->mute = 0;\
- snd_ymfpci_volume_##ename(codec->me_vol_##ename, 0, voices);\
- ugroup->volume.names.front_left = voices[0];\
- ugroup->volume.names.front_right = voices[1];\
- } else {\
- voices[0] = ugroup->volume.names.front_left;\
- voices[1] = ugroup->volume.names.front_right;\
- if (snd_ymfpci_volume_##ename(codec->me_vol_##ename, 1, voices)) {\
- snd_mixer_element_value_change_all_file(file, codec->me_vol_##ename, 0);\
- change = 1;\
- }\
- }\
- return change;\
-}
-
-RECORD_VOLUME(recsrc, YDSXGR_NATIVEDACINVOL)
-RECORD_VOLUME(adcrec, YDSXGR_PRIADCLOOPVOL)
-RECORD_VOLUME(spdifrec, YDSXGR_SPDIFLOOPVOL)
+ ymfpci_t *codec = snd_magic_cast(ymfpci_t, group->private_data, -ENXIO);\
+ return snd_ymfpci_mixer_volume_group(group, file, w_flag, ugroup,\
+ codec->me_vol_##ename, reg_offset);\
+}
+
+YMFPCI_VOLUME(waveout, YDSXGR_NATIVEDACOUTVOL)
+YMFPCI_VOLUME(waveloop, YDSXGR_NATIVEDACLOOPVOL)
+YMFPCI_VOLUME(recsrc, YDSXGR_NATIVEDACINVOL)
+YMFPCI_VOLUME(recsrc2, YDSXGR_NATIVEADCINVOL)
+YMFPCI_VOLUME(adcout, YDSXGR_PRIADCOUTVOL)
+YMFPCI_VOLUME(adcrec, YDSXGR_PRIADCLOOPVOL)
+/* looks like ZV ports are used as SPDIF usually */
+YMFPCI_VOLUME(spdifout, YDSXGR_ZVOUTVOL)
+YMFPCI_VOLUME(spdifrec, YDSXGR_ZVLOOPVOL)
+YMFPCI_VOLUME(zoomout, YDSXGR_SPDIFOUTVOL)
+YMFPCI_VOLUME(zoomloop, YDSXGR_SPDIFLOOPVOL)
/*
@@ -1198,14 +1239,30 @@
codec->mixer = NULL;
}
+#define APPEND_VOLUME_MIXER(mixer, name, index, ossname, suffix, chip, route) \
+do {\
+ snd_kmixer_group_t *group;\
+ snd_kmixer_element_t *me;\
+ if ((group = snd_mixer_lib_group_ctrl(mixer, name, index, ossname,\
+ snd_ymfpci_mixer_group_##suffix, chip)) == NULL)\
+ return -ENOMEM;\
+ if ((me = snd_mixer_lib_volume1(mixer, name, index, 2, loopback_range,\
+ snd_ymfpci_mixer_volume_##suffix, chip)) == NULL)\
+ return -ENOMEM;\
+ if (snd_mixer_group_element_add(mixer, group, me) < 0)\
+ return -ENOMEM;\
+ chip->me_vol_##suffix = me;\
+ if (route && snd_mixer_element_route_add(mixer, me, route) < 0)\
+ return -ENOMEM;\
+} while (0)
+
int snd_ymfpci_mixer(ymfpci_t * codec, int device, snd_pcm_t * pcm, snd_kmixer_t ** rmixer)
{
ac97_t ac97;
snd_kmixer_t *mixer;
- snd_kmixer_group_t *group;
static struct snd_mixer_element_volume1_range loopback_range[2] = {
- {0, REC_VOL_MAX, -3450, 0},
- {0, REC_VOL_MAX, -3450, 0}
+ {0, YMFPCI_VOL_MAX, -3450, 0},
+ {0, YMFPCI_VOL_MAX, -3450, 0}
};
int err;
@@ -1218,38 +1275,29 @@
if ((err = snd_ac97_mixer(codec->card, device, &ac97, 1, &pcm->device, &mixer)) < 0)
return err;
codec->ac97 = snd_magic_cast(ac97_t, mixer->private_data, -ENXIO);
- snd_mixer_switch_new(mixer, &snd_ymfpci_mixer_spdif, codec);
+ snd_mixer_switch_new(mixer, &snd_ymfpci_mixer_spdif_out, codec);
+ snd_mixer_switch_new(mixer, &snd_ymfpci_mixer_spdif_in, codec);
/* record source */
- if ((group = snd_mixer_lib_group_ctrl(mixer, "Capture Volume", 0, SND_MIXER_OSS_RECLEV,
- snd_ymfpci_mixer_group_recsrc, codec)) == NULL)
- return -ENOMEM;
- if ((codec->me_vol_recsrc = snd_mixer_lib_volume1(mixer, "Capture Volume", 0, 2,
- loopback_range, snd_ymfpci_volume_recsrc, codec)) == NULL)
- return -ENOMEM;
- if (snd_mixer_group_element_add(mixer, group, codec->me_vol_recsrc) < 0)
- return -ENOMEM;
+ APPEND_VOLUME_MIXER(mixer, "Capture Volume", 0, SND_MIXER_OSS_RECLEV, recsrc, codec, NULL);
/* AC97 -> record volume */
- if ((group = snd_mixer_lib_group_ctrl(mixer, "ADC Record", 0, SND_MIXER_OSS_DIGITAL2,
- snd_ymfpci_mixer_group_adcrec, codec)) == NULL)
- return -ENOMEM;
- if ((codec->me_vol_adcrec = snd_mixer_lib_volume1(mixer, "ADC Record", 0, 2,
- loopback_range, snd_ymfpci_volume_adcrec, codec)) == NULL)
- return -ENOMEM;
- if (snd_mixer_group_element_add(mixer, group, codec->me_vol_adcrec) < 0 ||
- /*snd_mixer_element_route_add(mixer, ac97.me_capture, codec->me_vol_adcrec) ||*/
- snd_mixer_element_route_add(mixer, codec->me_vol_adcrec, codec->me_vol_recsrc))
- return -ENOMEM;
+ APPEND_VOLUME_MIXER(mixer, "ADC Record", 0, SND_MIXER_OSS_DIGITAL2, adcrec, codec, codec->me_vol_recsrc);
/* SPDIF -> record volume */
- if ((group = snd_mixer_lib_group_ctrl(mixer, "SPDIF Record", 0, SND_MIXER_OSS_DIGITAL3,
- snd_ymfpci_mixer_group_spdifrec, codec)) == NULL)
- return -ENOMEM;
- if ((codec->me_vol_spdifrec = snd_mixer_lib_volume1(mixer, "SPDIF Record", 0, 2,
- loopback_range, snd_ymfpci_volume_spdifrec, codec)) == NULL)
- return -ENOMEM;
- if (snd_mixer_group_element_add(mixer, group, codec->me_vol_spdifrec) < 0 ||
- snd_mixer_element_route_add(mixer, codec->me_vol_spdifrec, codec->me_vol_recsrc))
- return -ENOMEM;
+ APPEND_VOLUME_MIXER(mixer, "SPDIF Record", 0, SND_MIXER_OSS_DIGITAL3, spdifrec, codec, codec->me_vol_recsrc);
+ /* capture volume #2 */
+ APPEND_VOLUME_MIXER(mixer, "Capture Volume", 1, SND_MIXER_OSS_UNKNOWN, recsrc2, codec, NULL);
+ /* capture playback volume */
+ APPEND_VOLUME_MIXER(mixer, "ADC Playback Volume", 0, SND_MIXER_OSS_UNKNOWN, adcout, codec, NULL);
+ /* spdif playback volume */
+ APPEND_VOLUME_MIXER(mixer, "SPDIF Playback Volume", 0, SND_MIXER_OSS_UNKNOWN, spdifout, codec, NULL);
+ /* Wave Out */
+ APPEND_VOLUME_MIXER(mixer, "Wave Playback Volume", 0, SND_MIXER_OSS_UNKNOWN, waveout, codec, NULL);
+ /* Wave Capture */
+ APPEND_VOLUME_MIXER(mixer, "Wave Catpure Volume", 0, SND_MIXER_OSS_UNKNOWN, waveloop, codec, NULL);
+ /* SPDIF #2 (Zoom) Out */
+ APPEND_VOLUME_MIXER(mixer, "SPDIF Playback Volume", 1, SND_MIXER_OSS_UNKNOWN, zoomout, codec, NULL);
+ /* SPDIF #2 (Zoom) Capture */
+ APPEND_VOLUME_MIXER(mixer, "SPDIF Record", 1, SND_MIXER_OSS_UNKNOWN, zoomloop, codec, codec->me_vol_recsrc);
*rmixer = codec->mixer = mixer;
return 0;
@@ -1380,7 +1428,7 @@
static int snd_ymfpci_memalloc(ymfpci_t *codec)
{
long size, playback_ctrl_size;
- int voice, bank;
+ int voice, bank, reg;
u8 *ptr;
playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES;
@@ -1451,13 +1499,19 @@
(SND_PCM_AES1_CON_PCM_CODER << 8));
/* S/PDIF input initialization */
- snd_ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 1);
+ snd_ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 0);
+ /* digital mixer setup */
+ for (reg = 0x80; reg < 0xc0; reg += 4)
+ snd_ymfpci_writel(codec, reg, 0);
/* move this volume setup to mixer */
snd_ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
/*snd_ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0x3fff3fff);*/ /* FIXME: may cause buzz on ymf754?? */
+ snd_ymfpci_writel(codec, YDSXGR_ZVOUTVOL, 0x3fff3fff);
+ snd_ymfpci_writel(codec, YDSXGR_SPDIFOUTVOL, 0x3fff3fff);
snd_ymfpci_writel(codec, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
snd_ymfpci_writel(codec, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
+ snd_ymfpci_writel(codec, YDSXGR_PRIADCLOOPVOL, 0x3fff3fff);
return 0;
}
@@ -1469,12 +1523,15 @@
YDSXGR_SPDIFOUTSTATUS,
YDSXGR_SPDIFINCTRL,
/* volumes */
+ YDSXGR_PRIADCOUTVOL,
YDSXGR_PRIADCLOOPVOL,
YDSXGR_NATIVEDACINVOL,
YDSXGR_NATIVEDACOUTVOL,
// YDSXGR_BUF441OUTVOL,
YDSXGR_NATIVEADCINVOL,
YDSXGR_SPDIFLOOPVOL,
+ YDSXGR_SPDIFOUTVOL,
+ YDSXGR_ZVOUTVOL,
/* address bases */
YDSXGR_PLAYCTRLBASE,
YDSXGR_RECCTRLBASE,
|