Comment 4 for bug 100114

Revision history for this message
TJ (tj) wrote :

Re: unloading the module. It was in-use even after I stopped GDM and was working from a console.

I've been debugging this issue and have made a little progress, albeit not the kind we want.

The difference in the outputs reported here and in bug #55071 pre- and post-suspend of codex#0 is not of consequence. It represents the stereo-input device amplifier state, where 0x80 is mute. If after resume you use the volume control to alter the Recording->Capture state or level you'll see the change reflected in the Amp-In vals of Node 9.

You can obtain the same value during normal operations by toggling 'audio recording from capture' and reducing the level to zero; Node 9 will show val 0x80.

The user experience of this issue sounds to me like a problem I dealt with back in the 1980's and it is to do with handling of DMA buffers. To my ear at least, our current issue sounds like the DMA buffer isn't being updated when the device exhausts its contents, and the DMA transfer to the device is looping several times from the same buffer. What should happen is the device should raise an interrupt which hda_intel.c::azx_interrupt() should handle by setting up a new DMA transfer from another buffer that is ready to go.

Some observations:

The patch in use on these Sony Vaio FE4x series is Sigmatel.

In hda_codec.c::snd_hda_suspend() the code calls a patch-specific suspend function:

  if (codec->patch_ops.suspend)
   codec->patch_ops.suspend(codec, state);

and during resume hda_codec.c::snd_hda_resume() calls the reciprical resume function:

  if (codec->patch_ops.resume)
   codec->patch_ops.resume(codec);

However (this may or may-not be significant) the Sigmatel patch only defines a resume function (checking the other patches they all seem to omit a suspend function). In patch_sigmatel.c:1854

#ifdef CONFIG_PM
 .resume = stac92xx_resume,
#endif

There is a note in hda_codec.c::snd_hda_suspend() which may or may not be a clue:

/* FIXME: should handle power widget capabilities */

and another at hda_intel.c:1056 in struct snd_pcm_hardware azx_pcm_hw.info

     /* No full-resume yet implemented */
     /* SNDRV_PCM_INFO_RESUME |*/

Which, according to include/sound/asound.h:252:

#define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */

When I find some time I am going to build a debug-kernel with hda_intel.c outputting debug info to test if hda_codec.c::snd_hda_resume() is missing something or possibly snd_hda_suspend() is neglecting to fully save the state.