At Sat, 2 Jun 2007 22:20:04 -0500 (CDT), acallan.alsa@ugnet.org wrote:
I've tried to chase this problem deeper. The chip has two codecs, 1 is audio, 2 is modem. In setup_fg_nodes() [hda_codec.c], the call to snd_hda_get_sub_nodes() returns total_nodes=1 and nid=0x01 for the audio codec. The same call returns total_nodes=39 and nid=0x00 for the modem codec.
Calls to azx_corb_send_cmd() [hda_intel.c] can be seen for AC_PAR_VENDOR_ID, AC_PAR_SUBSYSTEM_ID, AC_PAR_REV_ID, AC_PAR_NODE_COUNT, and AC_PAR_FUNCTION_TYPE for the audio codec. 32 calls to azx_corb_send_cmd() can then be seen for AC_PAR_AUDIO_WIDGET_CAP for the audio codec. For the modem codec, calls to azx_corb_send_cmd() can be seen for AC_PAR_VENDOR_ID, AC_PAR_SUBSYSTEM_ID, AC_PAR_REV_ID, and AC_PAR_NODE_COUNT followed by 39 calls to azx_corb_send_cmd() for AC_PAR_FUNCTION_TYPE for the modem codec. These each return the value AC_GRP_MODEM_FUNCTION and so the codec->mfg ends up being set to the 39th nid (0x26). Everything appears to be going smoothly until read_widget_caps() is called for them modem codec. When snd_hda_get_sub_nodes() is called inside read_widget_caps() for fg_node 0x26, this triggers a call to azx_corb_send_cmd() for AC_PAR_NODE_COUNT. The function azx_rirb_get_response() ends up timing out with the following lines appearing in my dmesg log: hda_intel: azx_get_response timeout, switching to polling mode... hda_intel: azx_get_response timeout, switching to single_cmd mode...
OK, then the problem gets started at reading the widget capabilities. Thanks for the analysis!
From following the code, it appears that chip->single_cmd = 1 from this point on. The note above the function azx_single_send_cmd() makes it clear that this function should not be used for normal operation. And, indeed, after this point, calls to the chip for the audio codec seem to return bogus values (as could be seen in the Default PCM and Node sections of the Codec information at http://pastebin.ca/496293).
Yes, that's already a known issue.
So, I have a few questions:
- Does it make sense that the modem codec would have 39 fg nodes?
That should be OK.
- Does it make sense that the switch to single_cmd mode would possibly
be the cause of the bogus values being returned later? (I haven't really traced much past this point since that comment about azx_single_send_cmd seemed to make it clear that I was already in trouble by this point.)
Yes, some devices have been broken. And, I guess it won't be get recovered even if you don't change to single_cmd mode.
- What other things would it be helpful to look at to try to chase this
problem further?
Could you try the patch below?
thanks,
Takashi diff -r eb7241f88cdd pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Mon Jun 04 09:21:19 2007 +0200 +++ b/pci/hda/hda_codec.c Mon Jun 04 16:11:02 2007 +0200 @@ -562,7 +562,7 @@ int __devinit snd_hda_codec_new(struct h return -ENODEV; }
- if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) { + if (codec->afg && read_widget_caps(codec, codec->afg) < 0) { snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); snd_hda_codec_free(codec); return -ENOMEM; diff -r eb7241f88cdd pci/hda/hda_local.h --- a/pci/hda/hda_local.h Mon Jun 04 09:21:19 2007 +0200 +++ b/pci/hda/hda_local.h Mon Jun 04 16:09:27 2007 +0200 @@ -271,7 +271,7 @@ int snd_hda_parse_pin_def_config(struct */ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) { - if (nid < codec->start_nid || + if (!codec->wcaps || nid < codec->start_nid || nid >= codec->start_nid + codec->num_nodes) return snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); return codec->wcaps[nid - codec->start_nid];