All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benny Sjostrand <gorm@cucumelo.org>
To: alsa-devel@lists.sourceforge.net
Subject: preliminary [PATCH] cs46xx independant PCM - Rear channel
Date: Sun, 20 Oct 2002 20:03:55 +0200	[thread overview]
Message-ID: <3DB2F00B.3020706@cucumelo.org> (raw)

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

Hi!

With this patch it should be possible to play a indpendent PCM stream to 
the "Rear" channel
on a cs46xx based HW.
Well, I guess I dont need to tell you that this patch probably works 
fine with a Game Thater XP card,
and probably some touches are neeeded for other cs46xx based soundcards.

The DSP will send the main PCM stream to the codec on slot 3 and 4, and for
the Rear channel it send the PCM stream it uses slot 7 and 8, which works
fine in a dual cs4294 combination setting the secondary codec in 
extended mode.

With other combinations probably we need experiment a little bit to find
out how configure the codecs.

NOTE: sound is no longer duplicated in main and rear channels, so you need
to run something like "aplay -D hw:0,1" to feed some sound in rear 
channel now.

Still left to have PCM channels for Center and LFE, and here I would
need some suggestion how to proceed. Is it possible in some how
to create a Mono PCM channel for this purpose with the ALSA API ??

/Benny


[-- Attachment #2: cs46xx.patch --]
[-- Type: text/plain, Size: 21280 bytes --]

diff -Naur --exclude=CVS alsa-kernel/include/cs46xx.h ../cvs/alsa-kernel/include/cs46xx.h
--- alsa-kernel/include/cs46xx.h	Fri Aug 23 17:51:18 2002
+++ ../cvs/alsa-kernel/include/cs46xx.h	Sat Oct 19 21:23:11 2002
@@ -1790,6 +1790,7 @@
 	struct pci_dev *pci;
 	snd_card_t *card;
 	snd_pcm_t *pcm;
+
 	snd_rawmidi_t *rmidi;
 	snd_rawmidi_substream_t *midi_input;
 	snd_rawmidi_substream_t *midi_output;
@@ -1814,12 +1815,15 @@
 	struct pm_dev *pm_dev;
 #endif
 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
-  int current_gpio;
+    int current_gpio;
 #endif
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	struct semaphore spos_mutex;
 
 	dsp_spos_instance_t * dsp_spos_instance;
+
+	snd_pcm_t *pcm_rear;
+	snd_pcm_t *pcm_iec958;
 #else /* for compatibility */
 	cs46xx_pcm_t *playback_pcm;
 	unsigned int play_ctl;
@@ -1832,6 +1836,8 @@
 		      cs46xx_t **rcodec);
 
 int snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
+int snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
+int snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
 int snd_cs46xx_mixer(cs46xx_t *chip);
 int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
 void snd_cs46xx_gameport(cs46xx_t *chip);
diff -Naur --exclude=CVS alsa-kernel/include/cs46xx_dsp_spos.h ../cvs/alsa-kernel/include/cs46xx_dsp_spos.h
--- alsa-kernel/include/cs46xx_dsp_spos.h	Fri Aug 23 17:51:18 2002
+++ ../cvs/alsa-kernel/include/cs46xx_dsp_spos.h	Sun Oct 20 13:14:12 2002
@@ -54,6 +54,9 @@
 #define DSP_MAX_PCM_CHANNELS 32
 #define DSP_MAX_SRC_NR       6
 
+#define DSP_PCM_MAIN_CHANNEL 1
+#define DSP_PCM_REAR_CHANNEL 2
+
 struct _dsp_module_desc_t;
 
 typedef struct _symbol_entry_t {
@@ -129,6 +132,8 @@
 	u32 unlinked;
 	dsp_scb_descriptor_t * pcm_reader_scb;
 	dsp_scb_descriptor_t * src_scb;
+	dsp_scb_descriptor_t * mixer_scb;
+    int pcm_channel_id;
 
 	void * private_data;
 } pcm_channel_descriptor_t;
@@ -141,8 +146,12 @@
 
 	segment_desc_t code;
 
-	/* PCM playback */
+	/* Main PCM playback mixer */
 	dsp_scb_descriptor_t * master_mix_scb;
+
+    /* Rear PCM playback mixer */
+    dsp_scb_descriptor_t * rear_mix_scb;
+
 	int npcm_channels;
 	int nsrc_scb;
 	pcm_channel_descriptor_t pcm_channels[DSP_MAX_PCM_CHANNELS];
diff -Naur --exclude=CVS alsa-kernel/pci/ac97/ac97_codec.c ../cvs/alsa-kernel/pci/ac97/ac97_codec.c
--- alsa-kernel/pci/ac97/ac97_codec.c	Wed Sep 18 12:58:33 2002
+++ ../cvs/alsa-kernel/pci/ac97/ac97_codec.c	Sun Oct 20 19:15:04 2002
@@ -966,7 +966,7 @@
 		reg = AC97_CENTER_LFE_MASTER;
 		mask = 0x0080;
 		break;
-	case AC97_SURROUND_MASTER:
+	case AC97_SURROUND_MASTER:      
 		if ((ac97->ext_id & 0x80) == 0)
 			return 0;
 		break;
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/cs46xx.c ../cvs/alsa-kernel/pci/cs46xx/cs46xx.c
--- alsa-kernel/pci/cs46xx/cs46xx.c	Thu Aug 15 14:13:09 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx.c	Sun Oct 20 19:41:42 2002
@@ -110,6 +110,10 @@
 		snd_card_free(card);
 		return err;
 	}
+    if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
+        snd_card_free(card);
+        return err;
+    }
 	if ((err = snd_cs46xx_mixer(chip)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -132,6 +136,7 @@
 		snd_card_free(card);
 		return err;
 	}
+
 	pci_set_drvdata(pci, chip);
 	dev++;
 	return 0;
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/cs46xx_lib.c ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c
--- alsa-kernel/pci/cs46xx/cs46xx_lib.c	Mon Sep 30 19:50:51 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.c	Sun Oct 20 19:21:05 2002
@@ -15,8 +15,8 @@
  *  TODO:
  *    - Secondary CODEC on some soundcards
  *    - SPDIF input support for other sample rates then 48khz
- *    - Independent PCM channels for rear output
  *    - Posibility to mix the SPDIF output with analog sources.
+ *    - PCM channels for Center and LFE on secondary codec
  *
  *  NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
  *        is default configuration), no SPDIF, no secondary codec, no
@@ -994,7 +994,21 @@
 		runtime->dma_area = cpcm->hw_area;
 		runtime->dma_addr = cpcm->hw_addr;
 		runtime->dma_bytes = cpcm->hw_size;
-		substream->ops = &snd_cs46xx_playback_ops;
+
+        snd_assert (cpcm->pcm_channel != NULL);
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+        if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
+          substream->ops = &snd_cs46xx_playback_ops;
+        } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
+          substream->ops = &snd_cs46xx_playback_rear_ops;
+        } else {
+          snd_assert(0);
+        }
+#else
+        substream->ops = &snd_cs46xx_playback_ops;
+#endif
+
 	} else {
 		if (runtime->dma_area == cpcm->hw_area) {
 			runtime->dma_area = NULL;
@@ -1003,7 +1017,21 @@
 		}
 		if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
 			return err;
-		substream->ops = &snd_cs46xx_playback_indirect_ops;
+
+        snd_assert (cpcm->pcm_channel != NULL);
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+        if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
+          substream->ops = &snd_cs46xx_playback_indirect_ops;
+        } else if (cpcm->pcm_channel->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
+          substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
+        } else {
+          snd_assert(0);
+        }
+#else
+        substream->ops = &snd_cs46xx_playback_indirect_ops;
+#endif
+
 	}
 
 	return 0;
@@ -1054,7 +1082,9 @@
 		int unlinked = cpcm->pcm_channel->unlinked;
 		cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
 
-		if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr)) == NULL) {
+		if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, 
+                                                                 cpcm->hw_addr,
+                                                                 cpcm->pcm_channel->pcm_channel_id)) == NULL) {
 			snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
 			up (&chip->spos_mutex);
 			return -ENXIO;
@@ -1320,7 +1350,7 @@
 		snd_magic_kfree(cpcm);
 }
 
-static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
+static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	cs46xx_pcm_t * cpcm;
@@ -1342,7 +1372,7 @@
 	cpcm->substream = substream;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	down (&chip->spos_mutex);
-	cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr);
+	cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, runtime->rate, cpcm, cpcm->hw_addr,pcm_channel_id);
 
 	if (cpcm->pcm_channel == NULL) {
 		snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
@@ -1365,6 +1395,22 @@
 	return 0;
 }
 
+static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream) {
+  snd_printd("open front channel\n");
+  return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
+}
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+static int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream) {
+  snd_printd("open rear channel\n");
+  return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
+}
+
+static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream) {
+  return -EBUSY;
+}
+#endif
+
 static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
@@ -1422,11 +1468,35 @@
 	return 0;
 }
 
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
+	.open =			snd_cs46xx_playback_open_rear,
+	.close =		snd_cs46xx_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =	snd_cs46xx_playback_hw_params,
+	.hw_free =		snd_cs46xx_playback_hw_free,
+	.prepare =		snd_cs46xx_playback_prepare,
+	.trigger =		snd_cs46xx_playback_trigger,
+	.pointer =		snd_cs46xx_playback_direct_pointer,
+};
+
+snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
+	.open =			snd_cs46xx_playback_open_iec958,
+	.close =		snd_cs46xx_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =	snd_cs46xx_playback_hw_params,
+	.hw_free =		snd_cs46xx_playback_hw_free,
+	.prepare =		snd_cs46xx_playback_prepare,
+	.trigger =		snd_cs46xx_playback_trigger,
+	.pointer =		snd_cs46xx_playback_direct_pointer,
+};
+#endif
+
 snd_pcm_ops_t snd_cs46xx_playback_ops = {
 	.open =			snd_cs46xx_playback_open,
 	.close =		snd_cs46xx_playback_close,
 	.ioctl =		snd_pcm_lib_ioctl,
-	.hw_params =		snd_cs46xx_playback_hw_params,
+	.hw_params =	snd_cs46xx_playback_hw_params,
 	.hw_free =		snd_cs46xx_playback_hw_free,
 	.prepare =		snd_cs46xx_playback_prepare,
 	.trigger =		snd_cs46xx_playback_trigger,
@@ -1445,6 +1515,18 @@
 	.pointer =		snd_cs46xx_playback_indirect_pointer,
 };
 
+snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
+	.open =			snd_cs46xx_playback_open_rear,
+	.close =		snd_cs46xx_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_cs46xx_playback_hw_params,
+	.hw_free =		snd_cs46xx_playback_hw_free,
+	.prepare =		snd_cs46xx_playback_prepare,
+	.trigger =		snd_cs46xx_playback_trigger,
+	.copy =			snd_cs46xx_playback_copy,
+	.pointer =		snd_cs46xx_playback_indirect_pointer,
+};
+
 snd_pcm_ops_t snd_cs46xx_capture_ops = {
 	.open =			snd_cs46xx_capture_open,
 	.close =		snd_cs46xx_capture_close,
@@ -1475,6 +1557,20 @@
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
+static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
+{
+	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	chip->pcm_rear = NULL;
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
+{
+	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	chip->pcm_iec958 = NULL;
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 #define MAX_PLAYBACK_CHANNELS	(DSP_MAX_PCM_CHANNELS - 1)
 #else
@@ -1490,6 +1586,7 @@
 		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
 		return err;
+
 	pcm->private_data = chip;
 	pcm->private_free = snd_cs46xx_pcm_free;
 
@@ -1505,13 +1602,72 @@
 
 	if (rpcm)
 		*rpcm = pcm;
+
+	return 0;
+}
+
+
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm) {
+	snd_pcm_t *pcm;
+	int err;
+
+	if (rpcm)
+		*rpcm = NULL;
+
+	if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
+		return err;
+
+	pcm->private_data = chip;
+	pcm->private_free = snd_cs46xx_pcm_rear_free;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
+
+	/* global setup */
+	pcm->info_flags = 0;
+	strcpy(pcm->name, "CS46xx - Rear");
+	chip->pcm_rear = pcm;
+
+	snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);
+
+	if (rpcm)
+		*rpcm = pcm;
+
 	return 0;
 }
 
+int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm) {
+	snd_pcm_t *pcm;
+	int err;
+
+	if (rpcm)
+		*rpcm = NULL;
+
+	if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
+		return err;
+
+	pcm->private_data = chip;
+	pcm->private_free = snd_cs46xx_pcm_iec958_free;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
+
+	/* global setup */
+	pcm->info_flags = 0;
+	strcpy(pcm->name, "CS46xx - IEC958");
+	chip->pcm_rear = pcm;
+
+	snd_pcm_lib_preallocate_pci_pages_for_all(chip->pci, pcm, 64*1024, 256*1024);
+
+	if (rpcm)
+		*rpcm = pcm;
+
+    return 0;
+}
+#endif
+
 /*
  *  Mixer routines
  */
-
 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
 {
 	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
@@ -1927,6 +2083,47 @@
 	.put = snd_herc_spdif_select_put,
 },
 };
+
+
+static void snd_cs46xx_sec_codec_reset (ac97_t * ac97) {
+  signed long end_time;
+  int err;
+
+  /* reset to defaults */
+  snd_ac97_write(ac97, AC97_RESET, 0);	
+
+  /* set codec in extended mode */
+  snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
+
+  udelay(50);
+
+  /* it's necessary to wait awhile until registers are accessible after RESET */
+  /* because the PCM or MASTER volume registers can be modified, */
+  /* the REC_GAIN register is used for tests */
+  end_time = jiffies + HZ;
+  do {
+    unsigned short ext_mid;
+    
+    /* use preliminary reads to settle the communication */
+    snd_ac97_read(ac97, AC97_RESET);
+    snd_ac97_read(ac97, AC97_VENDOR_ID1);
+    snd_ac97_read(ac97, AC97_VENDOR_ID2);
+    /* modem? */
+    ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+    if (ext_mid != 0xffff && (ext_mid & 1) != 0)
+      return;
+
+    /* test if we can write to the record gain volume register */
+    snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
+    if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
+      return;
+
+    set_current_state(TASK_UNINTERRUPTIBLE);
+    schedule_timeout(HZ/100);
+  } while (time_after_eq(end_time, jiffies));
+
+  snd_printk("CS46xx secondary codec dont respond!\n");  
+}
 #endif
 
 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
@@ -2001,11 +2198,18 @@
 	/* well, one codec only ... */
 	goto _end;
  _ok2:
+    /* set secondary codec in extended mode */
+    // snd_cs46xx_ac97_write(&ac97,AC97_CSR_ACMODE,0x3);
+
+    /* use custom reset to set secondary codec in
+       extended mode */
+    ac97.reset = snd_cs46xx_sec_codec_reset;
+
 	if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) < 0)
 		return err;
 	chip->nr_ac97_codecs = 2;
-    
-	/* add cs4630 mixer controls */
+
+    // snd_cs46xx_ac97_write(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX],AC97_CSR_ACMODE,0x3);
  _end:
 
 	/* dosoundcard specific mixer setup */
@@ -2016,6 +2220,7 @@
     
 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
 
+	/* add cs4630 mixer controls */
 	for (idx = 0; idx < sizeof(snd_cs46xx_controls) / 
 		     sizeof(snd_cs46xx_controls[0]); idx++) {
 		snd_kcontrol_t *kctl;
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/cs46xx_lib.h ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h
--- alsa-kernel/pci/cs46xx/cs46xx_lib.h	Mon Aug 26 18:02:05 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/cs46xx_lib.h	Sun Oct 20 14:56:50 2002
@@ -51,6 +51,9 @@
 extern snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;
 extern snd_pcm_ops_t snd_cs46xx_capture_ops;
 extern snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_rear_ops;
+extern snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;
+
 
 
 /*
@@ -185,7 +188,8 @@
                                                           dsp_scb_descriptor_t * snoop_scb,
                                                           dsp_scb_descriptor_t * parent_scb,
                                                           int scb_child_type);
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr);
+pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr,
+                                                          int pcm_channel_id);
 void                       cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,
                                                            pcm_channel_descriptor_t * pcm_channel);
 void                       cs46xx_dsp_set_src_sample_rate(cs46xx_t * chip,dsp_scb_descriptor_t * src, 
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/dsp_spos.c ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c
--- alsa-kernel/pci/cs46xx/dsp_spos.c	Sat Oct  5 11:11:49 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.c	Sun Oct 20 15:02:00 2002
@@ -1017,6 +1017,7 @@
 	dsp_scb_descriptor_t * codec_in_scb;
 	dsp_scb_descriptor_t * src_task_scb;
 	dsp_scb_descriptor_t * master_mix_scb;
+	dsp_scb_descriptor_t * rear_mix_scb;
 	dsp_scb_descriptor_t * record_mix_scb;
 	dsp_scb_descriptor_t * write_back_scb;
 	dsp_scb_descriptor_t * vari_decimate_scb;
@@ -1309,18 +1310,29 @@
 
 	/* create secondary CODEC output */
 	sec_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_II",0x0010,0x0040,
-							    OUTPUTSNOOP_SCB_ADDR,
+							    REAR_MIXER_SCB_ADDR,
 							    SEC_CODECOUT_SCB_ADDR,codec_in_scb,
 							    SCB_ON_PARENT_NEXT_SCB);
 	if (!sec_codec_out_scb) goto _fail_end;
 
+
+	/* create the rear PCM channel  mixer SCB */
+	rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB",
+                                                  MIX_SAMPLE_BUF3,
+                                                  REAR_MIXER_SCB_ADDR,
+                                                  sec_codec_out_scb,
+                                                  SCB_ON_PARENT_SUBLIST_SCB);
+	ins->rear_mix_scb = rear_mix_scb;
+	if (!rear_mix_scb) goto _fail_end;
+
 	/* the magic snooper */
 	magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR,
 							     OUTPUT_SNOOP_BUFFER,
 							     codec_out_scb,
 							     sec_codec_out_scb,
-							     SCB_ON_PARENT_SUBLIST_SCB);
+							     SCB_ON_PARENT_NEXT_SCB);
 
+    
 	if (!magic_snoop_scb) goto _fail_end;
 	ins->ref_snoop_scb = magic_snoop_scb;
 
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/dsp_spos.h ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.h
--- alsa-kernel/pci/cs46xx/dsp_spos.h	Mon Aug 19 12:53:13 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos.h	Sun Oct 20 12:14:33 2002
@@ -73,7 +73,8 @@
 #define SPDIFI_IP_OUTPUT_BUFFER1 0x0E00
 #define SPDIFO_IP_OUTPUT_BUFFER1 0x1000
 #define MIX_SAMPLE_BUF1          0x1400
-#define MIX_SAMPLE_BUF2          0x3000
+#define MIX_SAMPLE_BUF2          0x2D00
+#define MIX_SAMPLE_BUF3          0x2E00
 
 /* Task stack address */
 #define HFG_STACK                0x066A
@@ -104,6 +105,7 @@
 #define OUTPUTSNOOPII_SCB_ADDR   0x150
 #define PCMSERIALIN_PCM_SCB_ADDR 0x160
 #define RECORD_MIXER_SCB_ADDR    0x170
+#define REAR_MIXER_SCB_ADDR      0x180
 
 /* hyperforground SCB's*/
 #define HFG_TREE_SCB             0xBA0
diff -Naur --exclude=CVS alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c ../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c
--- alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c	Sat Oct  5 11:11:49 2002
+++ ../cvs/alsa-kernel/pci/cs46xx/dsp_spos_scb_lib.c	Sun Oct 20 14:43:25 2002
@@ -1093,15 +1093,29 @@
 };
 
 
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr)
+pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,
+                                                          u32 sample_rate, void * private_data, 
+                                                          u32 hw_dma_addr,
+                                                          int pcm_channel_id)
 {
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
-	dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb;
+	dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL;
 	/*dsp_scb_descriptor_t * pcm_parent_scb;*/
 	char scb_name[DSP_MAX_SCB_NAME];
 	int i,pcm_index = -1, insert_point, src_index = -1;
 	unsigned long flags;
 
+    switch (pcm_channel_id) {
+    case DSP_PCM_MAIN_CHANNEL:
+      mixer_scb = ins->master_mix_scb;
+      break;
+    case DSP_PCM_REAR_CHANNEL:
+      mixer_scb = ins->rear_mix_scb;
+      break;
+    default:
+      snd_assert (0);
+      return NULL;
+    }
 	/* default sample rate is 44100 */
 	if (!sample_rate) sample_rate = 44100;
 
@@ -1114,7 +1128,9 @@
 		if (i == CS46XX_DSP_CAPTURE_CHANNEL) continue;
 
 		if (ins->pcm_channels[i].active) {
-			if (!src_scb && ins->pcm_channels[i].sample_rate == sample_rate) {
+			if (!src_scb && 
+                ins->pcm_channels[i].sample_rate == sample_rate &&
+                ins->pcm_channels[i].mixer_scb == mixer_scb) {
 				src_scb = ins->pcm_channels[i].src_scb;
 				ins->pcm_channels[i].src_scb->ref_count ++;
 				src_index = ins->pcm_channels[i].src_slot;
@@ -1148,11 +1164,11 @@
 		snd_assert (src_index != -1,return NULL);
 
 		/* we need to create a new SRC SCB */
-		if (ins->master_mix_scb->sub_list_ptr == ins->the_null_scb) {
-			src_parent_scb = ins->master_mix_scb;
+		if (mixer_scb->sub_list_ptr == ins->the_null_scb) {
+			src_parent_scb = mixer_scb;
 			insert_point = SCB_ON_PARENT_SUBLIST_SCB;
 		} else {
-			src_parent_scb = find_next_free_scb(chip,ins->master_mix_scb->sub_list_ptr);
+			src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr);
 			insert_point = SCB_ON_PARENT_NEXT_SCB;
 		}
 
@@ -1180,7 +1196,8 @@
   
 	snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index);
 
-	snd_printdd( "dsp_spos: creating PCM \"%s\"\n",scb_name);
+	snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name,
+                 pcm_channel_id);
 
 	pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name,
 						   pcm_reader_buffer_addr[pcm_index],
@@ -1206,6 +1223,8 @@
 	ins->pcm_channels[pcm_index].src_slot = src_index;
 	ins->pcm_channels[pcm_index].active = 1;
 	ins->pcm_channels[pcm_index].pcm_slot = pcm_index;
+    ins->pcm_channels[pcm_index].mixer_scb = mixer_scb;
+    ins->pcm_channels[pcm_index].pcm_channel_id = pcm_channel_id;
 	ins->npcm_channels ++;
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 

                 reply	other threads:[~2002-10-20 18:03 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=3DB2F00B.3020706@cucumelo.org \
    --to=gorm@cucumelo.org \
    --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.