From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Requested: CMI8330 testers? Date: Mon, 16 Dec 2002 16:15:41 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Mon_Dec_16_16:15:41_2002-1" Return-path: Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: alsa-devel@lists.sourceforge.net Cc: alsa-user@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Mon_Dec_16_16:15:41_2002-1 Content-Type: text/plain; charset=US-ASCII Hi, can anyone who owns the CMI8330 ISA test the attached patch? the patch will change the pcm interface of this soundchip as a more reasonable way. the playback and capture are combined into one pcm. it's for the latest cvs version. not sure whether it's applicable to rc6. please check whether the full-duplex works. it's enough to run aplay and arecord simultaneously. thanks, Takashi --Multipart_Mon_Dec_16_16:15:41_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="cmi8330-pcm-fix.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/core/pcm.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm.c,v retrieving revision 1.20 diff -u -r1.20 pcm.c --- alsa-kernel/core/pcm.c 4 Dec 2002 09:37:21 -0000 1.20 +++ alsa-kernel/core/pcm.c 16 Dec 2002 14:04:21 -0000 @@ -774,6 +774,7 @@ runtime->status->state = SNDRV_PCM_STATE_OPEN; substream->runtime = runtime; + substream->private_data = pcm->private_data; pstr->substream_opened++; *rsubstream = substream; return 0; Index: alsa-kernel/include/ad1848.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/ad1848.h,v retrieving revision 1.4 diff -u -r1.4 ad1848.h --- alsa-kernel/include/ad1848.h 13 Aug 2002 16:17:06 -0000 1.4 +++ alsa-kernel/include/ad1848.h 16 Dec 2002 14:35:52 -0000 @@ -162,6 +162,7 @@ ad1848_t ** chip); int snd_ad1848_pcm(ad1848_t * chip, int device, snd_pcm_t **rpcm); +const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction); int snd_ad1848_mixer(ad1848_t * chip); void snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs); Index: alsa-kernel/include/pcm.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/pcm.h,v retrieving revision 1.21 diff -u -r1.21 pcm.h --- alsa-kernel/include/pcm.h 2 Dec 2002 09:25:18 -0000 1.21 +++ alsa-kernel/include/pcm.h 16 Dec 2002 14:03:06 -0000 @@ -50,7 +50,7 @@ typedef struct sndrv_pcm_mmap_control snd_pcm_mmap_control_t; typedef struct sndrv_mask snd_mask_t; -#define _snd_pcm_substream_chip(substream) ((substream)->pcm->private_data) +#define _snd_pcm_substream_chip(substream) ((substream)->private_data) #define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO) #define _snd_pcm_chip(pcm) ((pcm)->private_data) #define snd_pcm_chip(pcm) snd_magic_cast1(chip_t, _snd_pcm_chip(pcm), return -ENXIO) @@ -363,6 +363,7 @@ struct _snd_pcm_substream { snd_pcm_t *pcm; snd_pcm_str_t *pstr; + void *private_data; /* copied from pcm->private_data */ int number; char name[32]; /* substream name */ int stream; /* stream (direction) */ Index: alsa-kernel/include/sb.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/sb.h,v retrieving revision 1.7 diff -u -r1.7 sb.h --- alsa-kernel/include/sb.h 9 Dec 2002 10:52:24 -0000 1.7 +++ alsa-kernel/include/sb.h 16 Dec 2002 14:36:01 -0000 @@ -305,6 +305,7 @@ /* sb16_init.c */ int snd_sb16dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm); +const snd_pcm_ops_t *snd_sb16dsp_get_pcm_ops(int direction); int snd_sb16dsp_configure(sb_t *chip); /* sb16.c */ void snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs); Index: alsa-kernel/isa/cmi8330.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/isa/cmi8330.c,v retrieving revision 1.10 diff -u -r1.10 cmi8330.c --- alsa-kernel/isa/cmi8330.c 22 Oct 2002 09:37:24 -0000 1.10 +++ alsa-kernel/isa/cmi8330.c 16 Dec 2002 15:01:19 -0000 @@ -147,6 +147,15 @@ struct isapnp_dev *cap; struct isapnp_dev *play; #endif + snd_card_t *card; + ad1848_t *wss; + sb_t *sb; + + snd_pcm_t *pcm; + snd_pcm_ops_t playback_ops; + int (*playback_open)(snd_pcm_substream_t *); + snd_pcm_ops_t capture_ops; + int (*capture_open)(snd_pcm_substream_t *); }; static snd_card_t *snd_cmi8330_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; @@ -294,6 +303,79 @@ } #endif +/* + * PCM interface + * + * since we call the different chip interfaces for playback and capture + * directions, we need a trick. + * + * - copy the ops for each direction into a local record. + * - replace the open callback with the new one, which replaces the + * substream->private_data with the corresponding chip instance + * and calls again the original open callback of the chip. + * + */ + +static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream) +{ + struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream); + + /* replace the private_data and call the original open callback */ + substream->private_data = chip->sb; + return chip->playback_open(substream); +} + +static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream) +{ + struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream); + + /* replace the private_data and call the original open callback */ + substream->private_data = chip->wss; + return chip->capture_open(substream); +} + +static void snd_cmi8330_pcm_free(snd_pcm_t *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int __init snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip) +{ + snd_pcm_t *pcm; + const snd_pcm_ops_t *ops; + int err; + + if ((err = snd_pcm_new(card, "CMI8330", 0, 1, 1, &pcm)) < 0) + return err; + strcpy(pcm->name, "CMI8330"); + pcm->private_data = chip; + pcm->private_free = snd_cmi8330_pcm_free; + + /* playback - SB16 */ + ops = snd_sb16dsp_get_pcm_ops(SNDRV_PCM_STREAM_PLAYBACK); + chip->playback_ops = *ops; + chip->playback_open = ops->open; + chip->playback_ops.open = snd_cmi8330_playback_open; + + /* capture - AD1848 */ + ops = snd_ad1848_get_pcm_ops(SNDRV_PCM_STREAM_CAPTURE); + chip->capture_ops = *ops; + chip->capture_open = ops->open; + chip->capture_ops.open = snd_cmi8330_capture_open; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->capture_ops); + + snd_pcm_lib_preallocate_isa_pages_for_all(pcm, 64*1024, 128*1024); + chip->pcm = pcm; + + return 0; +} + + +/* + */ + static void snd_cmi8330_free(snd_card_t *card) { struct snd_cmi8330 *acard = (struct snd_cmi8330 *)card->private_data; @@ -309,12 +391,8 @@ { snd_card_t *card; struct snd_cmi8330 *acard; - ad1848_t *chip_wss; - sb_t *chip_sb; unsigned long flags; int i, err; - snd_pcm_t *pcm, *wss_pcm, *sb_pcm; - snd_pcm_str_t *pstr; #ifdef __ISAPNP__ if (!isapnp[dev]) { @@ -337,6 +415,7 @@ return -ENOMEM; } acard = (struct snd_cmi8330 *)card->private_data; + acard->card = card; card->private_free = snd_cmi8330_free; #ifdef __ISAPNP__ @@ -352,83 +431,60 @@ wssirq[dev], wssdma[dev], AD1848_HW_DETECT, - &chip_wss)) < 0) { + &acard->wss)) < 0) { snd_printk("(AD1848) device busy??\n"); snd_card_free(card); return err; } - if (chip_wss->hardware != AD1848_HW_CMI8330) { + if (acard->wss->hardware != AD1848_HW_CMI8330) { snd_printk("(AD1848) not found during probe\n"); snd_card_free(card); return -ENODEV; } - if ((err = snd_ad1848_pcm(chip_wss, 0, &wss_pcm)) < 0) { - snd_printk("(AD1848) no enough memory??\n"); - snd_card_free(card); - return err; - } if ((err = snd_sbdsp_create(card, sbport[dev], sbirq[dev], snd_sb16dsp_interrupt, sbdma8[dev], sbdma16[dev], - SB_HW_AUTO, &chip_sb)) < 0) { + SB_HW_AUTO, &acard->sb)) < 0) { snd_printk("(SB16) device busy??\n"); snd_card_free(card); return err; } - if ((err = snd_sb16dsp_pcm(chip_sb, 1, &sb_pcm)) < 0) { - snd_printk("(SB16) no enough memory??\n"); - snd_card_free(card); - return err; - } - - if (chip_sb->hardware != SB_HW_16) { + if (acard->sb->hardware != SB_HW_16) { snd_printk("(SB16) not found during probe\n"); snd_card_free(card); return -ENODEV; } + memcpy(&acard->wss->image[16], &snd_cmi8330_image, sizeof(snd_cmi8330_image)); - memcpy(&chip_wss->image[16], &snd_cmi8330_image, sizeof(snd_cmi8330_image)); + spin_lock_irqsave(&acard->wss->reg_lock, flags); + snd_ad1848_out(acard->wss, AD1848_MISC_INFO, /* switch on MODE2 */ + acard->wss->image[AD1848_MISC_INFO] |= 0x40); + spin_unlock_irqrestore(&acard->wss->reg_lock, flags); - spin_lock_irqsave(&chip_wss->reg_lock, flags); - snd_ad1848_out(chip_wss, AD1848_MISC_INFO, /* switch on MODE2 */ - chip_wss->image[AD1848_MISC_INFO] |= 0x40); - spin_unlock_irqrestore(&chip_wss->reg_lock, flags); - - if ((err = snd_cmi8330_mixer(card, chip_wss)) < 0) { + if ((err = snd_cmi8330_mixer(card, acard->wss)) < 0) { snd_printk("failed to create mixers\n"); snd_card_free(card); return err; } - spin_lock_irqsave(&chip_wss->reg_lock, flags); + spin_lock_irqsave(&acard->wss->reg_lock, flags); for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) - snd_ad1848_out(chip_wss, i, chip_wss->image[i]); - spin_unlock_irqrestore(&chip_wss->reg_lock, flags); + snd_ad1848_out(acard->wss, i, acard->wss->image[i]); + spin_unlock_irqrestore(&acard->wss->reg_lock, flags); - /* - * KLUDGE ALERT - * disable AD1848 playback - * disable SB16 capture - */ - pcm = wss_pcm; - pstr = &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; - snd_magic_kfree(pstr->substream); - pstr->substream = 0; - pstr->substream_count = 0; - - pcm = sb_pcm; - pstr = &pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; - snd_magic_kfree(pstr->substream); - pstr->substream = 0; - pstr->substream_count = 0; + if ((err = snd_cmi8330_pcm(card, acard)) < 0) { + snd_printk("failed to create pcms\n"); + snd_card_free(card); + return err; + } strcpy(card->driver, "CMI8330/C3D"); strcpy(card->shortname, "C-Media CMI8330/C3D"); sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - wss_pcm->name, - chip_wss->port, + card->shortname, + acard->wss->port, wssirq[dev], wssdma[dev]); Index: alsa-kernel/isa/ad1848/ad1848_lib.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/isa/ad1848/ad1848_lib.c,v retrieving revision 1.17 diff -u -r1.17 ad1848_lib.c --- alsa-kernel/isa/ad1848/ad1848_lib.c 25 Nov 2002 10:13:55 -0000 1.17 +++ alsa-kernel/isa/ad1848/ad1848_lib.c 16 Dec 2002 14:35:39 -0000 @@ -936,6 +936,12 @@ return 0; } +const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction) +{ + return direction == SNDRV_PCM_STREAM_PLAYBACK ? + &snd_ad1848_playback_ops : &snd_ad1848_capture_ops; +} + /* * MIXER part */ @@ -1160,6 +1166,7 @@ EXPORT_SYMBOL(snd_ad1848_interrupt); EXPORT_SYMBOL(snd_ad1848_create); EXPORT_SYMBOL(snd_ad1848_pcm); +EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); EXPORT_SYMBOL(snd_ad1848_mixer); EXPORT_SYMBOL(snd_ad1848_info_single); EXPORT_SYMBOL(snd_ad1848_get_single); Index: alsa-kernel/isa/sb/sb16_main.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/isa/sb/sb16_main.c,v retrieving revision 1.11 diff -u -r1.11 sb16_main.c --- alsa-kernel/isa/sb/sb16_main.c 25 Nov 2002 10:13:56 -0000 1.11 +++ alsa-kernel/isa/sb/sb16_main.c 16 Dec 2002 14:35:02 -0000 @@ -887,7 +887,14 @@ return 0; } +const snd_pcm_ops_t *snd_sb16dsp_get_pcm_ops(int direction) +{ + return direction == SNDRV_PCM_STREAM_PLAYBACK ? + &snd_sb16_playback_ops : &snd_sb16_capture_ops; +} + EXPORT_SYMBOL(snd_sb16dsp_pcm); +EXPORT_SYMBOL(snd_sb16dsp_get_pcm_ops); EXPORT_SYMBOL(snd_sb16dsp_configure); EXPORT_SYMBOL(snd_sb16dsp_interrupt); --Multipart_Mon_Dec_16_16:15:41_2002-1-- ------------------------------------------------------- This sf.net email is sponsored by: With Great Power, Comes Great Responsibility Learn to use your power at OSDN's High Performance Computing Channel http://hpc.devchannel.org/