From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Re: Yamaha 754 question... Date: Mon, 13 May 2002 13:39:03 +0200 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: Mime-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: multipart/mixed; boundary="Multipart_Mon_May_13_13:39:03_2002-1" Return-path: In-Reply-To: Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: Adam K Kirchhoff Cc: alsa-devel@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Mon_May_13_13:39:03_2002-1 Content-Type: text/plain; charset=US-ASCII At Fri, 10 May 2002 12:46:07 -0400 (EDT), Adam K Kirchhoff wrote: > > > No comment on this one? :-( oh, you had bad luck ;) now i did a very quick-n-dirty hack, the recipe was finished in 15 minutes. can you try the attached patch? btw i've not tested at all (nor have i the hardware).. Takashi --Multipart_Mon_May_13_13:39:03_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="ymfpci-4ch.dif" Content-Transfer-Encoding: 7bit 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 13 May 2002 11:30:46 -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; @@ -304,6 +304,9 @@ dma_addr_t bank_base_capture_addr; dma_addr_t bank_base_effect_addr; dma_addr_t work_base_addr; + + struct semaphore ac3_mutex; + int ac3_inited; void *ac3_tmp_base; dma_addr_t ac3_tmp_base_addr; @@ -333,6 +336,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 13 May 2002 11:33:53 -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); @@ -539,10 +542,19 @@ unsigned char *ptr; dma_addr_t ptr_addr; - if (chip->ac3_tmp_base != NULL) + down(&chip->ac3_mutex); + if (chip->ac3_inited) { + up(&chip->ac3_mutex); + return 0; + } + if (chip->ac3_tmp_base != NULL) { + up(&chip->ac3_mutex); return -EBUSY; - if ((ptr = snd_malloc_pci_pages(chip->pci, 4096, &ptr_addr)) == NULL) + } + if ((ptr = snd_malloc_pci_pages(chip->pci, 4096, &ptr_addr)) == NULL) { + up(&chip->ac3_mutex); return -ENOMEM; + } chip->ac3_tmp_base = ptr; chip->ac3_tmp_base_addr = ptr_addr; @@ -559,20 +571,31 @@ snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) | 3 << 3); spin_unlock_irq(&chip->reg_lock); + chip->ac3_inited++; + up(&chip->ac3_mutex); return 0; } static int snd_ymfpci_ac3_done(ymfpci_t *chip) { - spin_lock_irq(&chip->reg_lock); - 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); - 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; + down(&chip->ac3_mutex); + if (! chip->ac3_inited) { + up(&chip->ac3_mutex); + return 0; } + chip->ac3_inited--; + if (! chip->ac3_inited) { + spin_lock_irq(&chip->reg_lock); + 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); + 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; + } + } + up(&chip->ac3_mutex); return 0; } @@ -588,7 +611,7 @@ return err; if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0) return err; - if (ypcm->spdif || ypcm->mode4ch) + if (ypcm->output_rear) if ((err = snd_ymfpci_ac3_init(chip)) < 0) return err; return 0; @@ -616,7 +639,7 @@ snd_ymfpci_voice_free(chip, ypcm->voices[0]); ypcm->voices[0] = NULL; } - if (ypcm->spdif || ypcm->mode4ch) + if (ypcm->output_rear) snd_ymfpci_ac3_done(chip); return 0; } @@ -639,7 +662,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 +866,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 +886,31 @@ return 0; } +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 (! chip->rear_opened) + snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, + (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0030) | 0x0010); + if (! chip->spdif_opened && ! chip->rear_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30)); + 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 +919,25 @@ 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)); + if (! chip->rear_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30)); 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 +949,20 @@ 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)); + if (! chip->rear_opened) + snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, + (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0030) | 0x0010); + if (! chip->spdif_opened && ! chip->rear_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30)); + 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 +1000,38 @@ 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); + unsigned long flags; + + spin_lock_irqsave(&chip->reg_lock, flags); + chip->rear_opened--; + if (! chip->rear_opened && ! chip->spdif_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30)); + if (! chip->rear_opened) + snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, + (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010); + 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; + if (! chip->rear_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30)); snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2); snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); @@ -970,7 +1039,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 +1048,15 @@ 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); + chip->rear_opened--; + if (! chip->rear_opened && ! chip->spdif_opened) + snd_ymfpci_writel(chip, YDSXGR_MODE, + snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30)); + if (! chip->rear_opened) + snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, + (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010); 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 +1518,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 +1564,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, +}, }; @@ -2114,6 +2223,7 @@ spin_lock_init(&chip->voice_lock); init_waitqueue_head(&chip->interrupt_sleep); atomic_set(&chip->interrupt_sleep_count, 0); + init_MUTEX(&chip->ac3_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; --Multipart_Mon_May_13_13:39:03_2002-1-- _______________________________________________________________ Have big pipes? SourceForge.net is looking for download mirrors. We supply the hardware. You get the recognition. Email Us: bandwidth@sourceforge.net