All of lore.kernel.org
 help / color / mirror / Atom feed
* cs46xx thinkpad resume fix - #bug1946
@ 2007-07-14 15:55 Pavel Kysilka
  2007-07-16  9:24 ` Takashi Iwai
  0 siblings, 1 reply; 7+ messages in thread
From: Pavel Kysilka @ 2007-07-14 15:55 UTC (permalink / raw)
  To: alsa-devel

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

   Hi,

attached patch fix resume on thinkpad notebooks with cs46xx chip.
Tested with Thinkpad A21m.

Patch is opposite latest linus git 2.6.22.

Bug #1946 may be closed.

Signed-off-by: Pavel Kysilka <pavelk@bsys.cz>

 Pavel Kysilka



________ Information from NOD32 ________
This message was checked by NOD32 Antivirus System for Linux Mail Servers.
http://www.eset.com

[-- Attachment #2: cs46xx_thinkpad_resume_fix.diff --]
[-- Type: text/plain, Size: 441 bytes --]

diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index bef1f6d..73f66d7 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3715,6 +3715,7 @@ int snd_cs46xx_resume(struct pci_dev *pci)
 	chip->active_ctrl(chip, 1); /* force to on */
 
 	snd_cs46xx_chip_init(chip);
+	snd_cs46xx_start_dsp(chip); /* upload dsp code */
 
 #if 0
 	snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 

[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-14 15:55 cs46xx thinkpad resume fix - #bug1946 Pavel Kysilka
@ 2007-07-16  9:24 ` Takashi Iwai
  2007-07-17 10:50   ` Takashi Iwai
  0 siblings, 1 reply; 7+ messages in thread
From: Takashi Iwai @ 2007-07-16  9:24 UTC (permalink / raw)
  To: Pavel Kysilka; +Cc: alsa-devel

At Sat, 14 Jul 2007 17:55:52 +0200,
Pavel Kysilka wrote:
> 
>    Hi,
> 
> attached patch fix resume on thinkpad notebooks with cs46xx chip.
> Tested with Thinkpad A21m.
> 
> Patch is opposite latest linus git 2.6.22.
> 
> Bug #1946 may be closed.
> 
> Signed-off-by: Pavel Kysilka <pavelk@bsys.cz>

Oh, thanks for hunting this long-standing bug!

I think, however, it cannot be applied as it is.
First, snd_cs46xx_start_dsp() calls cs46xx_dsp_load_module(), and the
latter function isn't designed for the PM resume.  We'd need a special
resume function just for clearing area & reloading the dsp images
according to the already loaded DSP modules.

Second, __devinit prefix for snd_cs46xx_start_dsp() has to be removed
if it's called from the PM handler.


Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-16  9:24 ` Takashi Iwai
@ 2007-07-17 10:50   ` Takashi Iwai
  2007-07-17 22:26     ` Pavel Kysilka
  0 siblings, 1 reply; 7+ messages in thread
From: Takashi Iwai @ 2007-07-17 10:50 UTC (permalink / raw)
  To: Pavel Kysilka; +Cc: alsa-devel

At Mon, 16 Jul 2007 11:24:45 +0200,
I wrote:
> 
> At Sat, 14 Jul 2007 17:55:52 +0200,
> Pavel Kysilka wrote:
> > 
> >    Hi,
> > 
> > attached patch fix resume on thinkpad notebooks with cs46xx chip.
> > Tested with Thinkpad A21m.
> > 
> > Patch is opposite latest linus git 2.6.22.
> > 
> > Bug #1946 may be closed.
> > 
> > Signed-off-by: Pavel Kysilka <pavelk@bsys.cz>
> 
> Oh, thanks for hunting this long-standing bug!
> 
> I think, however, it cannot be applied as it is.
> First, snd_cs46xx_start_dsp() calls cs46xx_dsp_load_module(), and the
> latter function isn't designed for the PM resume.  We'd need a special
> resume function just for clearing area & reloading the dsp images
> according to the already loaded DSP modules.
> 
> Second, __devinit prefix for snd_cs46xx_start_dsp() has to be removed
> if it's called from the PM handler.

Looking at the code more deeply, I suspect whether it really works
when CONFIG_SND_CS46XX_NEW_DSP=y.  snd_cs46xx_start_dsp() involves
with many calls that add SCBs and co, which will eventually overflow.

I made a patch blindly to do the resume work in a saner way, but of
course, it's totally untested.  Could you check whether it works?


thanks,

Takashi

diff -r 67544a207969 include/cs46xx.h
--- a/include/cs46xx.h	Tue Jul 17 11:52:24 2007 +0200
+++ b/include/cs46xx.h	Tue Jul 17 12:49:37 2007 +0200
@@ -1723,6 +1723,10 @@ struct snd_cs46xx {
 	struct snd_cs46xx_pcm *playback_pcm;
 	unsigned int play_ctl;
 #endif
+
+#ifdef CONFIG_PM
+	u32 *saved_regs;
+#endif
 };
 
 int snd_cs46xx_create(struct snd_card *card,
diff -r 67544a207969 include/cs46xx_dsp_spos.h
--- a/include/cs46xx_dsp_spos.h	Tue Jul 17 11:52:24 2007 +0200
+++ b/include/cs46xx_dsp_spos.h	Tue Jul 17 12:49:37 2007 +0200
@@ -107,6 +107,7 @@ struct dsp_scb_descriptor {
 	char scb_name[DSP_MAX_SCB_NAME];
 	u32 address;
 	int index;
+	u32 *data;
 
 	struct dsp_scb_descriptor * sub_list_ptr;
 	struct dsp_scb_descriptor * next_scb_ptr;
@@ -127,6 +128,7 @@ struct dsp_task_descriptor {
 	int size;
 	u32 address;
 	int index;
+	u32 *data;
 };
 
 struct dsp_pcm_channel_descriptor {
diff -r 67544a207969 pci/cs46xx/cs46xx_lib.c
--- a/pci/cs46xx/cs46xx_lib.c	Tue Jul 17 11:52:24 2007 +0200
+++ b/pci/cs46xx/cs46xx_lib.c	Tue Jul 17 12:49:37 2007 +0200
@@ -2897,6 +2897,10 @@ static int snd_cs46xx_free(struct snd_cs
 	}
 #endif
 	
+#ifdef CONFIG_PM
+	kfree(chip->saved_regs);
+#endif
+
 	pci_disable_device(chip->pci);
 	kfree(chip);
 	return 0;
@@ -3140,6 +3144,23 @@ static int snd_cs46xx_chip_init(struct s
 /*
  *  start and load DSP 
  */
+
+static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
+{
+	unsigned int tmp;
+
+	snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
+        
+	tmp = snd_cs46xx_peek(chip, BA1_PFIE);
+	tmp &= ~0x0000f03f;
+	snd_cs46xx_poke(chip, BA1_PFIE, tmp);	/* playback interrupt enable */
+
+	tmp = snd_cs46xx_peek(chip, BA1_CIE);
+	tmp &= ~0x0000003f;
+	tmp |=  0x00000001;
+	snd_cs46xx_poke(chip, BA1_CIE, tmp);	/* capture interrupt enable */
+}
+
 int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
 {	
 	unsigned int tmp;
@@ -3214,19 +3235,7 @@ int __devinit snd_cs46xx_start_dsp(struc
 
 	snd_cs46xx_proc_start(chip);
 
-	/*
-	 *  Enable interrupts on the part.
-	 */
-	snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
-        
-	tmp = snd_cs46xx_peek(chip, BA1_PFIE);
-	tmp &= ~0x0000f03f;
-	snd_cs46xx_poke(chip, BA1_PFIE, tmp);	/* playback interrupt enable */
-
-	tmp = snd_cs46xx_peek(chip, BA1_CIE);
-	tmp &= ~0x0000003f;
-	tmp |=  0x00000001;
-	snd_cs46xx_poke(chip, BA1_CIE, tmp);	/* capture interrupt enable */
+	cs46xx_enable_stream_irqs(chip);
 	
 #ifndef CONFIG_SND_CS46XX_NEW_DSP
 	/* set the attenuation to 0dB */ 
@@ -3665,11 +3674,19 @@ static struct cs_card_type __devinitdata
  * APM support
  */
 #ifdef CONFIG_PM
+static unsigned int saved_regs[] = {
+	BA0_ACOSV,
+	BA0_ASER_FADDR,
+	BA0_ASER_MASTER,
+	BA1_PVOL,
+	BA1_CVOL,
+};
+
 int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_cs46xx *chip = card->private_data;
-	int amp_saved;
+	int i, amp_saved;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	chip->in_suspend = 1;
@@ -3679,6 +3696,10 @@ int snd_cs46xx_suspend(struct pci_dev *p
 
 	snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
 	snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
+
+	/* save some registers */
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+		chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]);
 
 	amp_saved = chip->amplifier;
 	/* turn off amp */
@@ -3698,7 +3719,7 @@ int snd_cs46xx_resume(struct pci_dev *pc
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_cs46xx *chip = card->private_data;
-	int amp_saved;
+	int i, amp_saved;
 
 	pci_set_power_state(pci, PCI_D0);
 	pci_restore_state(pci);
@@ -3715,6 +3736,16 @@ int snd_cs46xx_resume(struct pci_dev *pc
 	chip->active_ctrl(chip, 1); /* force to on */
 
 	snd_cs46xx_chip_init(chip);
+
+	snd_cs46xx_reset(chip);
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+	cs46xx_dsp_resume(chip);
+	/* restore some registers */
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+		snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]);
+#else
+	snd_cs46xx_download_image(chip);
+#endif
 
 #if 0
 	snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 
@@ -3729,6 +3760,13 @@ int snd_cs46xx_resume(struct pci_dev *pc
 
 	snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
 	snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
+
+	/* reset playback/capture */
+	snd_cs46xx_set_play_sample_rate(chip, 8000);
+	snd_cs46xx_set_capture_sample_rate(chip, 8000);
+	snd_cs46xx_proc_start(chip);
+
+	cs46xx_enable_stream_irqs(chip);
 
 	if (amp_saved)
 		chip->amplifier_ctrl(chip, 1); /* turn amp on */
@@ -3896,6 +3934,15 @@ int __devinit snd_cs46xx_create(struct s
 	
 	snd_cs46xx_proc_init(card, chip);
 
+#ifdef CONFIG_PM
+	chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) *
+				   ARRAY_SIZE(saved_regs), GFP_KERNEL);
+	if (!chip->saved_regs) {
+		snd_cs46xx_free(chip);
+		return -ENOMEM;
+	}
+#endif
+
 	chip->active_ctrl(chip, -1); /* disable CLKRUN */
 
 	snd_card_set_dev(card, &pci->dev);
diff -r 67544a207969 pci/cs46xx/cs46xx_lib.h
--- a/pci/cs46xx/cs46xx_lib.h	Tue Jul 17 11:52:24 2007 +0200
+++ b/pci/cs46xx/cs46xx_lib.h	Tue Jul 17 12:49:37 2007 +0200
@@ -86,6 +86,9 @@ struct dsp_spos_instance *cs46xx_dsp_spo
 struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip);
 void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip);
 int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module);
+#ifdef CONFIG_PM
+int cs46xx_dsp_resume(struct snd_cs46xx * chip);
+#endif
 struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name,
 						   int symbol_type);
 #ifdef CONFIG_PROC_FS
diff -r 67544a207969 pci/cs46xx/dsp_spos.c
--- a/pci/cs46xx/dsp_spos.c	Tue Jul 17 11:52:24 2007 +0200
+++ b/pci/cs46xx/dsp_spos.c	Tue Jul 17 12:49:37 2007 +0200
@@ -306,13 +306,59 @@ void  cs46xx_dsp_spos_destroy (struct sn
 	mutex_unlock(&chip->spos_mutex);
 }
 
+static int dsp_load_parameter(struct snd_cs46xx *chip,
+			      struct dsp_segment_desc *parameter)
+{
+	u32 doffset, dsize;
+
+	if (!parameter) {
+		snd_printdd("dsp_spos: module got no parameter segment\n");
+		return 0;
+	}
+
+	doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
+	dsize   = parameter->size * 4;
+
+	snd_printdd("dsp_spos: "
+		    "downloading parameter data to chip (%08x-%08x)\n",
+		    doffset,doffset + dsize);
+	if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
+		snd_printk(KERN_ERR "dsp_spos: "
+			   "failed to download parameter data to DSP\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int dsp_load_sample(struct snd_cs46xx *chip,
+			   struct dsp_segment_desc *sample)
+{
+	u32 doffset, dsize;
+
+	if (!sample) {
+		snd_printdd("dsp_spos: module got no sample segment\n");
+		return 0;
+	}
+
+	doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
+	dsize   =  sample->size * 4;
+
+	snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
+		    doffset,doffset + dsize);
+
+	if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
+		snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
 int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
 {
 	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
 	struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
-	struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
-	struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
 	u32 doffset, dsize;
+	int err;
 
 	if (ins->nmodules == DSP_MAX_MODULES - 1) {
 		snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_c
 		snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
 	}
   
-	if (parameter == NULL) {
-		snd_printdd("dsp_spos: module got no parameter segment\n");
-	} else {
-		if (ins->nmodules > 0) {
-			snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
-		}
-
-		doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
-		dsize   = parameter->size * 4;
-
-		snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
-			    doffset,doffset + dsize);
-
-		if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
-			snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
-			return -EINVAL;
-		}
-	}
+	err = dsp_load_parameter(chip, get_segment_desc(module,
+							SEGTYPE_SP_PARAMETER));
+	if (err < 0)
+		return err;
 
 	if (ins->nmodules == 0) {
 		snd_printdd("dsp_spos: clearing sample area\n");
 		snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
 	}
 
-	if (sample == NULL) {
-		snd_printdd("dsp_spos: module got no sample segment\n");
-	} else {
-		if (ins->nmodules > 0) {
-			snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
-		}
-
-		doffset = (sample->offset * 4  + DSP_SAMPLE_BYTE_OFFSET);
-		dsize   =  sample->size * 4;
-
-		snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
-			    doffset,doffset + dsize);
-
-		if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
-			snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
-			return -EINVAL;
-		}
-	}
-
+	err = dsp_load_sample(chip, get_segment_desc(module,
+						     SEGTYPE_SP_SAMPLE));
+	if (err < 0)
+		return err;
 
 	if (ins->nmodules == 0) {
 		snd_printdd("dsp_spos: clearing code area\n");
@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip,
 		return NULL;
 	}
 
-	strcpy(ins->tasks[ins->ntask].task_name,name);
+	if (name)
+		strcpy(ins->tasks[ins->ntask].task_name, name);
+	else
+		strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
 	ins->tasks[ins->ntask].address = dest;
 	ins->tasks[ins->ntask].size = size;
 
@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip,
 	desc = (ins->tasks + ins->ntask);
 	ins->ntask++;
 
-	add_symbol (chip,name,dest,SYMBOL_PARAMETER);
+	if (name)
+		add_symbol (chip,name,dest,SYMBOL_PARAMETER);
 	return desc;
 }
 
@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx
 
 	desc = _map_scb (chip,name,dest);
 	if (desc) {
+		desc->data = scb_data;
 		_dsp_create_scb(chip,scb_data,dest);
 	} else {
 		snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_
 
 	desc = _map_task_tree (chip,name,dest,size);
 	if (desc) {
+		desc->data = task_data;
 		_dsp_create_task_tree(chip,task_data,dest,size);
 	} else {
 		snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct
 			0x0000ffff
 		};
     
-		/* dirty hack ... */
-		_dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2);
+		if (!cs46xx_dsp_create_task_tree(chip, NULL,
+						 (u32 *)&mix2_ostream_spb,
+						 WRITE_BACK_SPB, 2))
+			goto _fail_end;
 	}
 
 	/* input sample converter */
@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct
 	return 0;
 }
 
-
 static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
 {
 	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct
 
 	return 0;
 }
+
+#ifdef CONFIG_PM
+int cs46xx_dsp_resume(struct snd_cs46xx * chip)
+{
+	struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+	int i, err;
+
+	/* clear parameter, sample and code areas */
+	snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET,
+			     DSP_PARAMETER_BYTE_SIZE);
+	snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET,
+			     DSP_SAMPLE_BYTE_SIZE);
+	snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
+
+	for (i = 0; i < ins->nmodules; i++) {
+		struct dsp_module_desc *module = &ins->modules[i];
+		struct dsp_segment_desc *seg;
+		u32 doffset, dsize;
+
+		seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER);
+		err = dsp_load_parameter(chip, seg);
+		if (err < 0)
+			return err;
+
+		seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE);
+		err = dsp_load_sample(chip, seg);
+		if (err < 0)
+			return err;
+
+		seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM);
+		if (!seg)
+			continue;
+
+		doffset = seg->offset * 4 + module->load_address * 4
+			+ DSP_CODE_BYTE_OFFSET;
+		dsize   = seg->size * 4;
+		err = snd_cs46xx_download(chip,
+					  ins->code.data + module->load_address,
+					  doffset, dsize);
+		if (err < 0)
+			return err;
+	}
+
+	for (i = 0; i < ins->ntask; i++) {
+		struct dsp_task_descriptor *t = &ins->tasks[i];
+		_dsp_create_task_tree(chip, t->data, t->address, t->size);
+	}
+
+	for (i = 0; i < ins->nscb; i++) {
+		struct dsp_scb_descriptor *s = &ins->scbs[i];
+		if (s->deleted)
+			continue;
+		_dsp_create_scb(chip, s->data, s->address);
+	}
+
+	return 0;
+}
+#endif

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-17 10:50   ` Takashi Iwai
@ 2007-07-17 22:26     ` Pavel Kysilka
  2007-07-18 13:51       ` chris
  2007-07-19  9:34       ` Takashi Iwai
  0 siblings, 2 replies; 7+ messages in thread
From: Pavel Kysilka @ 2007-07-17 22:26 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

On Tue Jul 17, 2007 at 12:50:21PM +0200, Takashi Iwai wrote:

  Hi Takashi,

good news below.

> At Mon, 16 Jul 2007 11:24:45 +0200,
> I wrote:
> > 
> > 
<cut/>
> > Oh, thanks for hunting this long-standing bug!
> > 
> > I think, however, it cannot be applied as it is.
> > First, snd_cs46xx_start_dsp() calls cs46xx_dsp_load_module(), and the
> > latter function isn't designed for the PM resume.  We'd need a special
> > resume function just for clearing area & reloading the dsp images
> > according to the already loaded DSP modules.
> > 
> > Second, __devinit prefix for snd_cs46xx_start_dsp() has to be removed
> > if it's called from the PM handler.
> 
> Looking at the code more deeply, I suspect whether it really works
> when CONFIG_SND_CS46XX_NEW_DSP=y.  snd_cs46xx_start_dsp() involves
> with many calls that add SCBs and co, which will eventually overflow.
> 
> I made a patch blindly to do the resume work in a saner way, but of
> course, it's totally untested.  Could you check whether it works?

Patch works perfectly.

Tested option:
- kernel compiled with and without CONFIG_SND_CS46XX_NEW_DSP=y
- play pcm stream, suspend, resume and pcm stream is playing
- play pcm stream, stop playing pcm stream, suspend, resume and play pcm stream

If you need log from resume from notebook, I'll send you this log.

> 
> 
> thanks,
> 
> Takashi
> 

 Many thanks
    Pavel


________ Information from NOD32 ________
This message was checked by NOD32 Antivirus System for Linux Mail Servers.
http://www.eset.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-17 22:26     ` Pavel Kysilka
@ 2007-07-18 13:51       ` chris
  2007-07-19  9:37         ` Takashi Iwai
  2007-07-19  9:34       ` Takashi Iwai
  1 sibling, 1 reply; 7+ messages in thread
From: chris @ 2007-07-18 13:51 UTC (permalink / raw)
  To: Pavel Kysilka; +Cc: Takashi Iwai, alsa-devel

Would this also apply to bug #305?

I'm happy to test this on CentOS 5 then Fedora 7 on a 600X, and write up 
the needed steps for ThinkWiki until the patch is included in the 
distributions.

Chris



On Wed, 18 Jul 2007, Pavel Kysilka wrote:

> On Tue Jul 17, 2007 at 12:50:21PM +0200, Takashi Iwai wrote:
>
>  Hi Takashi,
>
> good news below.
>
>> At Mon, 16 Jul 2007 11:24:45 +0200,
>> I wrote:
>>>
>>>
> <cut/>
>>> Oh, thanks for hunting this long-standing bug!
>>>
>>> I think, however, it cannot be applied as it is.
>>> First, snd_cs46xx_start_dsp() calls cs46xx_dsp_load_module(), and the
>>> latter function isn't designed for the PM resume.  We'd need a special
>>> resume function just for clearing area & reloading the dsp images
>>> according to the already loaded DSP modules.
>>>
>>> Second, __devinit prefix for snd_cs46xx_start_dsp() has to be removed
>>> if it's called from the PM handler.
>>
>> Looking at the code more deeply, I suspect whether it really works
>> when CONFIG_SND_CS46XX_NEW_DSP=y.  snd_cs46xx_start_dsp() involves
>> with many calls that add SCBs and co, which will eventually overflow.
>>
>> I made a patch blindly to do the resume work in a saner way, but of
>> course, it's totally untested.  Could you check whether it works?
>
> Patch works perfectly.
>
> Tested option:
> - kernel compiled with and without CONFIG_SND_CS46XX_NEW_DSP=y
> - play pcm stream, suspend, resume and pcm stream is playing
> - play pcm stream, stop playing pcm stream, suspend, resume and play pcm stream
>
> If you need log from resume from notebook, I'll send you this log.
>
>>
>>
>> thanks,
>>
>> Takashi
>>
>
> Many thanks
>    Pavel
>
>
> ________ Information from NOD32 ________
> This message was checked by NOD32 Antivirus System for Linux Mail Servers.
> http://www.eset.com
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-17 22:26     ` Pavel Kysilka
  2007-07-18 13:51       ` chris
@ 2007-07-19  9:34       ` Takashi Iwai
  1 sibling, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2007-07-19  9:34 UTC (permalink / raw)
  To: Pavel Kysilka; +Cc: alsa-devel

At Wed, 18 Jul 2007 00:26:42 +0200,
Pavel Kysilka wrote:
> 
> On Tue Jul 17, 2007 at 12:50:21PM +0200, Takashi Iwai wrote:
> 
>   Hi Takashi,
> 
> good news below.
> 
> > At Mon, 16 Jul 2007 11:24:45 +0200,
> > I wrote:
> > > 
> > > 
> <cut/>
> > > Oh, thanks for hunting this long-standing bug!
> > > 
> > > I think, however, it cannot be applied as it is.
> > > First, snd_cs46xx_start_dsp() calls cs46xx_dsp_load_module(), and the
> > > latter function isn't designed for the PM resume.  We'd need a special
> > > resume function just for clearing area & reloading the dsp images
> > > according to the already loaded DSP modules.
> > > 
> > > Second, __devinit prefix for snd_cs46xx_start_dsp() has to be removed
> > > if it's called from the PM handler.
> > 
> > Looking at the code more deeply, I suspect whether it really works
> > when CONFIG_SND_CS46XX_NEW_DSP=y.  snd_cs46xx_start_dsp() involves
> > with many calls that add SCBs and co, which will eventually overflow.
> > 
> > I made a patch blindly to do the resume work in a saner way, but of
> > course, it's totally untested.  Could you check whether it works?
> 
> Patch works perfectly.
> 
> Tested option:
> - kernel compiled with and without CONFIG_SND_CS46XX_NEW_DSP=y
> - play pcm stream, suspend, resume and pcm stream is playing
> - play pcm stream, stop playing pcm stream, suspend, resume and play pcm stream
> 
> If you need log from resume from notebook, I'll send you this log.

Thanks for testing!  That's enough, so far.  I applied the patch to HG
tree now.


Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: cs46xx thinkpad resume fix - #bug1946
  2007-07-18 13:51       ` chris
@ 2007-07-19  9:37         ` Takashi Iwai
  0 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2007-07-19  9:37 UTC (permalink / raw)
  To: chris; +Cc: alsa-devel, Pavel Kysilka

At Wed, 18 Jul 2007 08:51:45 -0500 (CDT),
chris@idlelion.net wrote:
> 
> Would this also apply to bug #305?

Possible.

> I'm happy to test this on CentOS 5 then Fedora 7 on a 600X, and write up 
> the needed steps for ThinkWiki until the patch is included in the 
> distributions.

You can either download the HG repo or take the latest daily snapshot
from
	ftp://ftp.suse.com/pub/projects/alsa/snapshot/driver

I applied the patch today (July 19), so hg20070720 snapshot will
include it.

If the mirror HG repo (hg-mirror.alsa-project.org) is out of sync, you
can try hg.alsa-project.org instead.


Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-07-19  9:37 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-14 15:55 cs46xx thinkpad resume fix - #bug1946 Pavel Kysilka
2007-07-16  9:24 ` Takashi Iwai
2007-07-17 10:50   ` Takashi Iwai
2007-07-17 22:26     ` Pavel Kysilka
2007-07-18 13:51       ` chris
2007-07-19  9:37         ` Takashi Iwai
2007-07-19  9:34       ` Takashi Iwai

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.