All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Adam K Kirchhoff <adamk@voicenet.com>
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: Re: Yamaha 754 question...
Date: Thu, 16 May 2002 12:25:03 +0200	[thread overview]
Message-ID: <s5h7km45r0g.wl@alsa2.suse.de> (raw)
In-Reply-To: <Pine.LNX.4.10.10205141059020.5776-100000@sorrow.ashke.com>

[-- Attachment #1: Type: text/plain, Size: 960 bytes --]

At Tue, 14 May 2002 11:13:56 -0400 (EDT),
Adam K Kirchhoff wrote:
> 
> 
> OK...  So I got around to testing how snd_ymfpci_ac3_init and
> snd_ymfpci_ac3_done are being handled.  You'll have to tell me if the
> results sound good, though.
> 
> Playing back one small wav file (3930 bytes) with "play" (so it's not
> using any sound daemons) results in entering _init one and entering _done
> once.
> 
> Playing back a slightly larger wav file (12250 bytes) results in entering
> _init 3 times, and _done once.
> 
> An even larger wav file: _init 4 times, _done once...
> 
> The largest wav file I can find will still only enter _init 4 times...
> _done only ever seems to get called once (as you'd expect).

hmm, init can be called multiple times.  i forgot it.

the following is the revised patch.
now ac3_init and _done are called at module init/end stage, so there
will be no problems any more to switch 2ch/4ch accidentally.
could you give a try?


Takashi

[-- Attachment #2: ymfpci-4ch-2.dif --]
[-- Type: application/octet-stream, Size: 13131 bytes --]

Index: alsa-kernel/include/ymfpci.h
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/ymfpci.h,v
retrieving revision 1.5
diff -u -r1.5 ymfpci.h
--- alsa-kernel/include/ymfpci.h	18 Feb 2002 09:25:29 -0000	1.5
+++ alsa-kernel/include/ymfpci.h	16 May 2002 10:19:59 -0000
@@ -264,9 +264,9 @@
 	snd_ymfpci_pcm_type_t type;
 	snd_pcm_substream_t *substream;
 	ymfpci_voice_t *voices[2];	/* playback only */
-	int running: 1,
-	    spdif: 1,
-	    mode4ch : 1;	
+	int running: 1;
+	int output_front: 1;
+	int output_rear: 1;
 	u32 period_size;		/* cached from runtime->period_size */
 	u32 buffer_size;		/* cached from runtime->buffer_size */
 	u32 period_pos;
@@ -333,6 +333,9 @@
 	snd_kcontrol_t *ctl_vol_spdifrec;
 	unsigned short spdif_bits, spdif_pcm_bits;
 	snd_kcontrol_t *spdif_pcm_ctl;
+	int mode_dup4ch;
+	int rear_opened;
+	int spdif_opened;
 
 	spinlock_t reg_lock;
 	spinlock_t voice_lock;
Index: alsa-kernel/pci/ymfpci/ymfpci_main.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/ymfpci/ymfpci_main.c,v
retrieving revision 1.16
diff -u -r1.16 ymfpci_main.c
--- alsa-kernel/pci/ymfpci/ymfpci_main.c	26 Apr 2002 09:32:48 -0000	1.16
+++ alsa-kernel/pci/ymfpci/ymfpci_main.c	16 May 2002 10:12:41 -0000
@@ -453,7 +453,8 @@
 
 static void snd_ymfpci_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
 				      int rate, int w_16, unsigned long addr,
-				      unsigned int end, int eff2)
+				      unsigned int end,
+				      int output_front, int output_rear)
 {
 	u32 format;
 	u32 delta = snd_ymfpci_calc_delta(rate);
@@ -499,19 +500,20 @@
 		bank->eff3_gain_end = 0;
 
 		if (!stereo) {
-			if (!eff2) {
+			if (output_front) {
 				bank->left_gain = 
 				bank->right_gain =
 				bank->left_gain_end =
 				bank->right_gain_end = cpu_to_le32(0x40000000);
-			} else {
+			}
+			if (output_rear) {
 				bank->eff2_gain =
 				bank->eff2_gain_end =
 				bank->eff3_gain =
 				bank->eff3_gain_end = cpu_to_le32(0x40000000);
 			}
 		} else {
-			if (!eff2) {
+			if (output_front) {
 				if ((voice->number & 1) == 0) {
 					bank->left_gain =
 					bank->left_gain_end = cpu_to_le32(0x40000000);
@@ -520,7 +522,8 @@
 					bank->right_gain =
 					bank->right_gain_end = cpu_to_le32(0x40000000);
 				}
-			} else {
+			}
+			if (output_rear) {
 				if ((voice->number & 1) == 0) {
 					bank->eff3_gain =
 					bank->eff3_gain_end = cpu_to_le32(0x40000000);
@@ -534,13 +537,11 @@
 	}
 }
 
-static int snd_ymfpci_ac3_init(ymfpci_t *chip)
+static int __devinit snd_ymfpci_ac3_init(ymfpci_t *chip)
 {
 	unsigned char *ptr;
 	dma_addr_t ptr_addr;
 
-	if (chip->ac3_tmp_base != NULL)
-		return -EBUSY;
 	if ((ptr = snd_malloc_pci_pages(chip->pci, 4096, &ptr_addr)) == NULL)
 		return -ENOMEM;
 
@@ -568,7 +569,7 @@
 	snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT,
 			  snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) & ~(3 << 3));
 	spin_unlock_irq(&chip->reg_lock);
-	snd_ymfpci_irq_wait(chip);
+	// snd_ymfpci_irq_wait(chip);
 	if (chip->ac3_tmp_base) {
 		snd_free_pci_pages(chip->pci, 4096, chip->ac3_tmp_base, chip->ac3_tmp_base_addr);
 		chip->ac3_tmp_base = NULL;
@@ -579,7 +580,6 @@
 static int snd_ymfpci_playback_hw_params(snd_pcm_substream_t * substream,
 					 snd_pcm_hw_params_t * hw_params)
 {
-	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
 	int err;
@@ -588,9 +588,6 @@
 		return err;
 	if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0)
 		return err;
-	if (ypcm->spdif || ypcm->mode4ch)
-		if ((err = snd_ymfpci_ac3_init(chip)) < 0)
-			return err;
 	return 0;
 }
 
@@ -600,7 +597,6 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 	
-	
 	if (runtime->private_data == NULL)
 		return 0;
 	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
@@ -616,8 +612,6 @@
 		snd_ymfpci_voice_free(chip, ypcm->voices[0]);
 		ypcm->voices[0] = NULL;
 	}
-	if (ypcm->spdif || ypcm->mode4ch)
-		snd_ymfpci_ac3_done(chip);
 	return 0;
 }
 
@@ -639,7 +633,8 @@
 					  snd_pcm_format_width(runtime->format) == 16,
 					  runtime->dma_addr,
 					  ypcm->buffer_size,
-					  ypcm->spdif || ypcm->mode4ch);
+					  ypcm->output_front,
+					  ypcm->output_rear);
 	return 0;
 }
 
@@ -842,7 +837,7 @@
 		snd_magic_kfree(ypcm);
 }
 
-static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -862,6 +857,53 @@
 	return 0;
 }
 
+/* call with spinlock held */
+static void ymfpci_open_extension(ymfpci_t *chip)
+{
+	if (! chip->rear_opened) {
+		if (! chip->spdif_opened) /* set AC3 */
+			snd_ymfpci_writel(chip, YDSXGR_MODE,
+					  snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30));
+		/* enable second codec (4CHEN) */
+		snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,
+				  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010);
+	}
+}
+
+/* call with spinlock held */
+static void ymfpci_close_extension(ymfpci_t *chip)
+{
+	if (! chip->rear_opened) {
+		if (! chip->spdif_opened)
+			snd_ymfpci_writel(chip, YDSXGR_MODE,
+					  snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30));
+		snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,
+				  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) & ~0x0010);
+	}
+}
+
+static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
+{
+	ymfpci_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	ymfpci_pcm_t *ypcm;
+	unsigned long flags;
+	int err;
+	
+	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
+		return err;
+	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm->output_front = 1;
+	ypcm->output_rear = chip->mode_dup4ch ? 1 : 0;
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	if (ypcm->output_rear) {
+		ymfpci_open_extension(chip);
+		chip->rear_opened++;
+	}
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	return 0;
+}
+
 static int snd_ymfpci_playback_spdif_open(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
@@ -870,25 +912,23 @@
 	unsigned long flags;
 	int err;
 	
-	if ((err = snd_ymfpci_playback_open(substream)) < 0)
+	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
 	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
-	ypcm->spdif = 1;
+	ypcm->output_front = 0;
+	ypcm->output_rear = 1;
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);
-	snd_ymfpci_writel(chip, YDSXGR_MODE,
-			  snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30));
+	ymfpci_open_extension(chip);
 	chip->spdif_pcm_bits = chip->spdif_bits;
 	snd_ymfpci_writel(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);
+	chip->spdif_opened++;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	chip->spdif_pcm_ctl->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
 		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);
-
-	/* FIXME? True value is 256/48 = 5.33333 ms */
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
 	return 0;
 }
 
@@ -900,19 +940,15 @@
 	unsigned long flags;
 	int err;
 	
-	if ((err = snd_ymfpci_playback_open(substream)) < 0)
+	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
 	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
-	ypcm->mode4ch = 1;
+	ypcm->output_front = 0;
+	ypcm->output_rear = 1;
 	spin_lock_irqsave(&chip->reg_lock, flags);
-	snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,
-			  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0030) | 0x0010);
-	snd_ymfpci_writel(chip, YDSXGR_MODE,
-			  snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30));
+	ymfpci_open_extension(chip);
+	chip->rear_opened++;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
-
-	/* FIXME? True value is 256/48 = 5.33333 ms */
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
 	return 0;
 }
 
@@ -950,19 +986,34 @@
 	return snd_ymfpci_capture_open(substream, 1);
 }
 
-static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_close_1(snd_pcm_substream_t * substream)
 {
 	return 0;
 }
 
+static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
+{
+	ymfpci_t *chip = snd_pcm_substream_chip(substream);
+	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	if (ypcm->output_rear && chip->rear_opened > 0) {
+		chip->rear_opened--;
+		ymfpci_close_extension(chip);
+	}
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	return snd_ymfpci_playback_close_1(substream);
+}
+
 static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
-	snd_ymfpci_writel(chip, YDSXGR_MODE,
-			  snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30));
+	chip->spdif_opened = 0;
+	ymfpci_close_extension(chip);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);
@@ -970,7 +1021,7 @@
 	chip->spdif_pcm_ctl->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
 		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);
-	return snd_ymfpci_playback_close(substream);
+	return snd_ymfpci_playback_close_1(substream);
 }
 
 static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream)
@@ -979,12 +1030,12 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
-	snd_ymfpci_writel(chip, YDSXGR_MODE,
-			  snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30));
-	snd_ymfpci_writew(chip, YDSXGR_SECCONFIG,
-			  (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010);
+	if (chip->rear_opened > 0) {
+		chip->rear_opened--;
+		ymfpci_close_extension(chip);
+	}
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
-	return snd_ymfpci_playback_close(substream);
+	return snd_ymfpci_playback_close_1(substream);
 }
 
 static int snd_ymfpci_capture_close(snd_pcm_substream_t * substream)
@@ -1446,6 +1497,36 @@
 	return change;
 }
 
+/*
+ * 4ch duplication
+ */
+static int snd_ymfpci_info_dup4ch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_ymfpci_get_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = chip->mode_dup4ch;
+	return 0;
+}
+
+static int snd_ymfpci_put_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+	int change;
+	change = (ucontrol->value.integer.value[0] != chip->mode_dup4ch);
+	if (change)
+		chip->mode_dup4ch = !!ucontrol->value.integer.value[0];
+	return change;
+}
+
+
 #define YMFPCI_CONTROLS (sizeof(snd_ymfpci_controls)/sizeof(snd_kcontrol_new_t))
 
 static snd_kcontrol_new_t snd_ymfpci_controls[] __devinitdata = {
@@ -1462,7 +1543,14 @@
 YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL),
 YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL),
 YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL),
-YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL)
+YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL),
+{
+	iface: SNDRV_CTL_ELEM_IFACE_MIXER,
+	name: "4ch Duplication",
+	info: snd_ymfpci_info_dup4ch,
+	get: snd_ymfpci_get_dup4ch,
+	put: snd_ymfpci_put_dup4ch,
+},
 };
 
 
@@ -1952,12 +2040,19 @@
 		snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
 	}
 
+	snd_ymfpci_ac3_done(chip);
+
 	/* Set PCI device to D3 state */
-	// pci_set_power_state(chip->pci, 3);
+#if 0
+	/* FIXME: temporarily disabled, otherwise we cannot fire up
+	 * the chip again unless reboot.  ACPI bug?
+	 */
+	pci_set_power_state(chip->pci, 3);
+#endif
 
 #ifdef CONFIG_PM
 	if (chip->saved_regs)
-		kfree(chip->saved_regs);
+		vfree(chip->saved_regs);
 #endif
 	if (chip->reg_area_virt)
 		iounmap((void *)chip->reg_area_virt);
@@ -2150,8 +2245,11 @@
 		return -EIO;
 	}
 
+	if ((err = snd_ymfpci_ac3_init(chip)) < 0)
+		return err;
+
 #ifdef CONFIG_PM
-	chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32), GFP_KERNEL);
+	chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32));
 	if (chip->saved_regs == NULL) {
 		snd_ymfpci_free(chip);
 		return -ENOMEM;

  reply	other threads:[~2002-05-16 10:25 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-05-08 23:07 Yamaha 754 question Adam K Kirchhoff
2002-05-10 16:46 ` Adam K Kirchhoff
2002-05-10 17:10   ` Andy Wingo
2002-05-13 11:39   ` Takashi Iwai
2002-05-13 12:54     ` Adam K Kirchhoff
2002-05-13 14:30       ` Takashi Iwai
2002-05-13 21:33         ` Adam K Kirchhoff
2002-05-14 15:13           ` Adam K Kirchhoff
2002-05-16 10:25             ` Takashi Iwai [this message]
2002-05-16 13:12               ` Adam K Kirchhoff
2002-05-20 16:36                 ` Adam K Kirchhoff
2002-05-21 10:50                   ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5h7km45r0g.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=adamk@voicenet.com \
    --cc=alsa-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.