Open ydzhou opened 1 year ago
Sorry - meant to reply earlier. Sleep was something I decided not to worry about - there were other issues with hibernation in general for macs so didnt seem worth it. However with the new specific patch_cs8409.c module for Dell laptops which does appear to handle sleep (see the suspend/resume cs42l42 functions - macs will be different because the chip is cs42l83 - similar to cs42l42 but custom chip for Apple (also I think the Apple cs8409 has some differences again special version for Apple). I would suspect the issue is how much the chips are powered down for deep sleep vs s2idle - likely under S2 the chips are powered on enough to retain the boot programming (what will be powered down are the external speaker amp chips which will be the main power hogs - the cs42l83 may also get powered down more than the cs8409). The questions are what state are the chips in after deep sleep and what exactly needs re-initializing. One way would be to redo the full boot initialization of all chips (8409/cs42l83/amps) - however thats quite a long process involving multi thousand HDA commands to the 8409 - but it should always work. patch_cirrus_boot84.h has most of the boot init functions. The primary boot function is patch_cs8409_apple in patch_cirrus_apple.h which calls cs_8409_boot_setup which calls cs_8409_real_config which calls cs_8409_boot_setup_real.
Hibernation works flawless in my mac. I agree with your point about full boot initialization.
I tried to do a manual reload of the sound card by
echo "1" > /sys/bus/pci/devices/{intel sound card}/remove
echo "1" > /sys/bus/pci/rescan
This does bring up some boot sequence of loading bunch of snd_hda_intel
related modules. However I get this error saying subsystem code
is not matching with a very strange value like 0x138...
something.
Do you think if I just hard set the subsystem code in your patch to my mac one and force loading the module, will that work?
Id need the full error messge line - most of my code error lines follow UNKNOWN subsystem id 0x..... so could be coming from actual kernel
Here is the dmesg:
[ 301.644454] pci 0000:00:1f.3: [8086:a348] type 00 class 0x040380
[ 301.644537] pci 0000:00:1f.3: reg 0x10: [mem 0x81810000-0x81813fff 64bit]
[ 301.644648] pci 0000:00:1f.3: reg 0x20: [mem 0x4000000000-0x40000fffff 64bit]
[ 301.644847] pci 0000:00:1f.3: PME# supported from D3hot D3cold
[ 301.671022] pci 0000:00:1f.3: BAR 4: assigned [mem 0x4000000000-0x40000fffff 64bit]
[ 301.671054] pci 0000:00:1f.3: BAR 0: assigned [mem 0x4000104000-0x4000107fff 64bit]
[ 301.671123] snd_hda_intel 0000:00:1f.3: DSP detected with PCI class/subclass/prog-if info 0x040380
[ 301.685677] snd_hda_intel: Primary patch_cs8409
[ 301.685680] snd_hda_intel: Primary patch_cs8409 NOT FOUND trying APPLE
[ 301.685683] snd_hda_codec_cs8409 hdaudioC0D0: UNKNOWN subsystem id 0x10138409
[ 301.688783] snd_hda_intel: Primary patch_cs8409
[ 301.688786] snd_hda_intel: Primary patch_cs8409 NOT FOUND trying APPLE
[ 301.688789] snd_hda_codec_cs8409 hdaudioC0D0: UNKNOWN subsystem id 0x10138409
[ 301.691430] snd_hda_codec_generic hdaudioC0D0: autoconfig for Generic: line_outs=0 (0x0/0x0/0x0/0x0/0x0) type:line
[ 301.691436] snd_hda_codec_generic hdaudioC0D0: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
[ 301.691440] snd_hda_codec_generic hdaudioC0D0: hp_outs=0 (0x0/0x0/0x0/0x0/0x0)
[ 301.691443] snd_hda_codec_generic hdaudioC0D0: mono: mono_out=0x0
[ 301.691445] snd_hda_codec_generic hdaudioC0D0: inputs:
OK so this is one of my error messages. Unfortunately Ive seen this issue reported before - 0x10138409 is not a subsystem id but the PCI device id of the main sound device - under some conditions something seems to mess with the kernel/chip state so that codec->core.subsystem_id is set to the device id - however what sets codec->core.subsystem_id is somewhere in the main kernel code (likely under the sound directory but could be pci device assignment) - nothing to do with my updates. If you look at the patch_cs8409_apple function in patch_cirrus_apple.h you can see this message near the beginning of the function - also note that the codec variable is passed to this function. It does seem to appear if a full power on/off is not done. Trying to figure out what might cause this needs someone with much more kernel detail knowledge than I have. Id suggest starting at cs_8409_boot_setup_real to redo the boot init on a resume - but you need the resume function for the device - rather than the cs42l42/cs42l83 chip suspend/resume - again dont know much about the kernels PM (power management) functionality. (Best example Ive seen is in patch_realtek.c which sets a codec->patch_ops.suspend = alc269_suspend; and codec->patch_ops.resume = alc269_resume; which I think are the device suspend/resume functions - just try and call cs_8409_boot_setup_real in a new resume function set up for the 8409 codec device). PS you could try setting codec->core.subsystem_id to your subsystem id if you see the device id ( the specific values checked for are listed in patch_cs8409_apple just before the error message) but other things are likely wrong so Id be susprised if it worked.
Yeah I tried to hardcode the subsystem id and reload the modules after waking-up. The end result is still wrong.
I looked briefly on cs42142 code, looks like we have to do something in the resume. After sleep, if I rescan the PCI, the sound card or whatever codec thing will not be discovered just as you mentioned, the subsystem ID turns out to be the device ID or vendor id
of sound card PCI. Interestingly if I did not apply your patch, after deep sleep and rescanning the PCI, the subsystem ID will remain correct.
My guess is that deep sleep mode put that codec chip power down, but we never bring it back... I'll try to see if I can make any progress on it.
BTW, what is the cs_8409_boot_setup_real
you mentioned? Can you put a link to it?
cs_8409_boot_setup_real is one of my functions which sends all the commands to setup the chips from boot as logged from OSX - see file patch_cirrus_real84.h
It works. Thanks for the insight!
Do you think we can patch the sleep this way? or you are still exploring some other method? I am happy to open a PR.
Well thats interesting - sometimes if the state is already partially setup re-doing the setup doesnt work (in general that is - not seen it for this audio). No Im not attempting anything on sleep - so if it works go ahead and setup a PR.
The real drawback is the number of operations - having seen the thousands (literally - the numbers at the end of the commands in the code are a count of the verbs sent from an original OSX log) of HDA verbs sent - even just for start play I noticed some distinct lags even under OSX - one in particular is headphone jack plug in - on older macs speaker off used to be near instantaneous with jack plugin - now theres a good 1/2 second delay between jack plug in and the speakers going off.
One thing I was going to do was to try and reduce hda verbs in the boot setup - if you look eg init_read_all_nodes just reads all the nodes - and under linux nothing is stored so removing shouldnt affect anything - also read_coefs_all just reads data that maybe used under OSX but not under linux.
Ive already removed a lot of duplicate verb sendings for play/stop - Apple seemed to set things up for play but not really start, reset to no play then setup for play again (only guess is something to do with buffering maybe PCI in the 8409 chip) - I skipped a lot of these duplications. It also does a lot more power off/on (assuming to reduce power) which Ive also skipped.
Yeah, one dumb way I can think of is try to remove lines from cs_8409_boot_setup_real
and see if it's still working...
The dell one's resume seems very reasonable lightweight. Do you know the equipvalent way to do that for apple chip?
spec->gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
spec->gpio_data |= cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data);
One of the big differences between the Dell system and Apple is I think the Dell only has the internal mike/jack part of the audio system - handled by the cs42l42 or cs42l83 (Apple) - Apple additionally has the 4 external amp chips which Ive not seen any sign of in the Dell code.
I think this would work for the cs42l83 - there is a pin I decided is the GPIO reset pin - see CS8409_CS42L83_RESET defined in patch_cirrus_apple.h (this is based on the naming used by for the Dell system - CS8409_CS42L42_RESET - but that pin hex value is different - bit 5 for Dell - bit 2 for Apple. Check the functions cs42l83_external_control_GPIO and cs42l83_external_control_GPIO_clear_2, cs42l83_external_control_GPIO_set_2 - I think they do the equivalent of the Dell reset_gpio.
Hi
The sound is not working if I wake my mac from deep sleep mode. But if I set the sleep mode to be s2idle, the sound will remain working after waking up. Can you shed some light on why it works for s2idle? I am trying to make it work with deep sleep mode.