├── .gitignore ├── tests ├── StereoTest32.wav ├── StereoTest32_reduced_m24dB.wav └── README ├── patch_cirrus ├── Makefile ├── cs8409.h ├── patch_cirrus_hda_generic_copy.h └── patch_cs8409.h ├── makefiles ├── Makefile ├── Makefile_cirrus ├── Makefile_common └── Makefile_codecs ├── dkms.conf ├── patch_patch_cirrus_apple.h.diff ├── patches ├── patch_patch_cirrus_apple.h.main.diff ├── patch_patch_cirrus_apple.h.ubuntu.diff ├── patch_patch_cs8409.h.main.diff ├── patch_patch_cs8409.h.ubuntu.diff ├── patch_patch_cs8409.h.main.pre519.diff └── patch_patch_cs8409.h.ubuntu.pre51547.diff ├── dkms.sh ├── Makefile ├── patch_cs8409.c.diff ├── patch_patch_cs8409.c.diff ├── NOTES.md ├── README.md ├── patch_patch_cirrus.c.diff ├── install.cirrus.driver.pre617.sh ├── install.cirrus.driver.sh ├── patch_patch_cs8409.h.diff ├── LICENSE └── patch_cs8409.h.diff /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /tests/StereoTest32.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidjo/snd_hda_macbookpro/HEAD/tests/StereoTest32.wav -------------------------------------------------------------------------------- /tests/StereoTest32_reduced_m24dB.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidjo/snd_hda_macbookpro/HEAD/tests/StereoTest32_reduced_m24dB.wav -------------------------------------------------------------------------------- /patch_cirrus/Makefile: -------------------------------------------------------------------------------- 1 | ifdef PATCH_CIRRUS 2 | snd-hda-codec-cirrus-objs := patch_cirrus.o 3 | obj-$(CONFIG_SND_HDA_CODEC_CIRRUS) += snd-hda-codec-cirrus.o 4 | else 5 | snd-hda-codec-cs8409-objs := patch_cs8409.o patch_cs8409-tables.o 6 | obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o 7 | endif 8 | -------------------------------------------------------------------------------- /makefiles/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | #obj-y += core/ 3 | #obj-$(CONFIG_SND_HDA) += common/ 4 | obj-$(CONFIG_SND_HDA) += codecs/ 5 | # this must be the last entry after codec drivers; 6 | # otherwise the codec drivers won't be hooked before the PCI probe 7 | # when built in kernel 8 | #obj-$(CONFIG_SND_HDA) += controllers/ 9 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | 2 | Test waveforms for speakers 3 | 4 | StereoTest32_reduced_m24dB.wav is reduced volume level for testing via the direct hardware device 5 | 6 | Run: 7 | 8 | aplay StereoTest32.wav 9 | 10 | or 11 | 12 | aplay -D hw:0,0 StereoTest32_reduced_m24dB.wav 13 | 14 | 15 | NOTA BENE - do NOT use -D hw:0,0 with StereoTest32.wav 16 | 17 | 18 | waveform provided by milan475 19 | 20 | -------------------------------------------------------------------------------- /dkms.conf: -------------------------------------------------------------------------------- 1 | PACKAGE_NAME="snd_hda_macbookpro" 2 | PACKAGE_VERSION="0.1" 3 | PRE_BUILD="install.cirrus.driver.sh -k $kernelver" 4 | MAKE="make" 5 | BUILT_MODULE_NAME[0]="snd-hda-codec-cs8409" 6 | BUILT_MODULE_LOCATION[0]="build/hda" 7 | # according to the man page this option is ignored by many distros (including Fedora and Ubuntu) 8 | # but is apparently still required....why?? 9 | DEST_MODULE_LOCATION[0]="/kernel/extra" 10 | AUTOINSTALL="yes" 11 | -------------------------------------------------------------------------------- /makefiles/Makefile_cirrus: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | subdir-ccflags-y += -I$(src)/../../common 3 | 4 | #snd-hda-codec-cs420x-y := cs420x.o 5 | #snd-hda-codec-cs421x-y := cs421x.o 6 | snd-hda-codec-cs8409-y := cs8409.o cs8409-tables.o 7 | 8 | #obj-$(CONFIG_SND_HDA_CODEC_CS420X) += snd-hda-codec-cs420x.o 9 | #obj-$(CONFIG_SND_HDA_CODEC_CS421X) += snd-hda-codec-cs421x.o 10 | obj-$(CONFIG_SND_HDA_CODEC_CS8409) += snd-hda-codec-cs8409.o 11 | -------------------------------------------------------------------------------- /makefiles/Makefile_common: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | #snd-hda-codec-y := bind.o codec.o jack.o auto_parser.o sysfs.o 3 | #snd-hda-codec-y += controller.o 4 | #snd-hda-codec-$(CONFIG_SND_PROC_FS) += proc.o 5 | 6 | #snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hwdep.o 7 | #snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += beep.o 8 | 9 | # for trace-points 10 | #CFLAGS_controller.o := -I$(src) 11 | 12 | # common driver 13 | #obj-$(CONFIG_SND_HDA) := snd-hda-codec.o 14 | -------------------------------------------------------------------------------- /patch_patch_cirrus_apple.h.diff: -------------------------------------------------------------------------------- 1 | diff --git a/patch_cirrus/patch_cirrus_apple.h b/patch_cirrus/patch_cirrus_apple.h 2 | index 398618c..0abda63 100644 3 | --- a/patch_cirrus/patch_cirrus_apple.h 4 | +++ b/patch_cirrus/patch_cirrus_apple.h 5 | @@ -157,7 +157,6 @@ struct sub_codec cs8409_cs42l83_codec = { 6 | .hp_jack_in = 0, 7 | .mic_jack_in = 0, 8 | .linein_jack_in = 0, 9 | - .force_status_change = 1, 10 | .paged = 1, 11 | .suspended = 1, 12 | .no_type_dect = 0, 13 | -------------------------------------------------------------------------------- /patches/patch_patch_cirrus_apple.h.main.diff: -------------------------------------------------------------------------------- 1 | diff --git a/patch_cirrus/patch_cirrus_apple.h b/patch_cirrus/patch_cirrus_apple.h 2 | index fc2b2d0..9a9311e 100644 3 | --- a/patch_cirrus/patch_cirrus_apple.h 4 | +++ b/patch_cirrus/patch_cirrus_apple.h 5 | @@ -155,7 +155,6 @@ struct sub_codec cs8409_cs42l83_codec = { 6 | .hp_jack_in = 0, 7 | .mic_jack_in = 0, 8 | .linein_jack_in = 0, 9 | - .force_status_change = 1, 10 | .paged = 1, 11 | .suspended = 1, 12 | .no_type_dect = 0, 13 | -------------------------------------------------------------------------------- /patches/patch_patch_cirrus_apple.h.ubuntu.diff: -------------------------------------------------------------------------------- 1 | diff --git a/patch_cirrus/patch_cirrus_apple.h b/patch_cirrus/patch_cirrus_apple.h 2 | index fc2b2d0..9a9311e 100644 3 | --- a/patch_cirrus/patch_cirrus_apple.h 4 | +++ b/patch_cirrus/patch_cirrus_apple.h 5 | @@ -155,7 +155,6 @@ struct sub_codec cs8409_cs42l83_codec = { 6 | .hp_jack_in = 0, 7 | .mic_jack_in = 0, 8 | .linein_jack_in = 0, 9 | - .force_status_change = 1, 10 | .paged = 1, 11 | .suspended = 1, 12 | .no_type_dect = 0, 13 | -------------------------------------------------------------------------------- /dkms.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | src_dir='/usr/src/snd_hda_macbookpro-0.1' 4 | dkms_name='snd_hda_macbookpro/0.1' 5 | var_dkms_dir='/var/lib/dkms/snd_hda_macbookpro' 6 | cur_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) 7 | 8 | # specify uninstall with the -r or -u argument 9 | while getopts :ru arg 10 | do 11 | case "${arg}" in 12 | r) dkms_remove=true;; 13 | u) dkms_remove=true;; 14 | esac 15 | done 16 | 17 | if [[ $dkms_remove = true ]]; then 18 | [[ -e $var_dkms_dir ]] && rm -rf $var_dkms_dir && echo "removed $var_dkms_dir" 19 | [[ -e $src_dir ]] && rm -f $src_dir && echo "removed $src_dir" 20 | exit 0 21 | fi 22 | 23 | pushd $cur_dir > /dev/null 24 | 25 | [[ ! -e $src_dir ]] && ln -sfn $cur_dir $src_dir 26 | dkms install -c dkms.conf --force -m $dkms_name 27 | 28 | popd > /dev/null 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # debug build flags 2 | #KBUILD_EXTRA_CFLAGS = "-DCONFIG_SND_DEBUG=1 -DMYSOUNDDEBUGFULL -DAPPLE_PINSENSE_FIXUP -DAPPLE_CODECS -DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function" 3 | # normal build flags 4 | KBUILD_EXTRA_CFLAGS = "-DAPPLE_PINSENSE_FIXUP -DAPPLE_CODECS -DCONFIG_SND_HDA_RECONFIG=1 -Wno-unused-variable -Wno-unused-function" 5 | 6 | 7 | ifdef KERNELRELEASE 8 | KERNELDIR := /lib/modules/$(KERNELRELEASE) 9 | else 10 | KERNELDIR := /lib/modules/$(shell uname -r) 11 | endif 12 | 13 | KERNELBUILD := $(KERNELDIR)/build 14 | 15 | all: 16 | make -C $(KERNELBUILD) CFLAGS_MODULE=$(KBUILD_EXTRA_CFLAGS) M=$(shell pwd)/build/hda modules 17 | 18 | clean: 19 | make -C $(KERNELBUILD) M=$(shell pwd)/build/hda clean 20 | 21 | install: 22 | make INSTALL_MOD_DIR=updates -C $(KERNELBUILD) M=$(shell pwd)/build/hda CONFIG_MODULE_SIG_ALL=n modules_install 23 | depmod -a 24 | -------------------------------------------------------------------------------- /makefiles/Makefile_codecs: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | subdir-ccflags-y += -I$(src)/../common 3 | 4 | #snd-hda-codec-generic-y := generic.o 5 | #snd-hda-codec-cmedia-y := cmedia.o 6 | #snd-hda-codec-cm9825-y := cm9825.o 7 | #snd-hda-codec-analog-y := analog.o 8 | #snd-hda-codec-ca0110-y := ca0110.o 9 | #snd-hda-codec-ca0132-y := ca0132.o 10 | #snd-hda-codec-cmedia-y := cmedia.o 11 | #snd-hda-codec-conexant-y := conexant.o 12 | #snd-hda-codec-idt-y := sigmatel.o 13 | #snd-hda-codec-senarytech-y := senarytech.o 14 | #snd-hda-codec-si3054-y := si3054.o 15 | #snd-hda-codec-via-y := via.o 16 | 17 | obj-y += cirrus/ 18 | #obj-y += hdmi/ 19 | #obj-y += realtek/ 20 | #obj-y += side-codecs/ 21 | 22 | # codec drivers 23 | #obj-$(CONFIG_SND_HDA_GENERIC) += snd-hda-codec-generic.o 24 | #obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o 25 | #obj-$(CONFIG_SND_HDA_CODEC_CM9825) += snd-hda-codec-cm9825.o 26 | #obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o 27 | #obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o 28 | #obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o 29 | #obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o 30 | #obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o 31 | #obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o 32 | #obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o 33 | #obj-$(CONFIG_SND_HDA_CODEC_SI3054) += snd-hda-codec-si3054.o 34 | #obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o 35 | -------------------------------------------------------------------------------- /patch_cs8409.c.diff: -------------------------------------------------------------------------------- 1 | --- a/codecs/cirrus/cs8409.c.orig 2025-09-15 12:53:58.000000000 +0100 2 | +++ b/codecs/cirrus/cs8409.c 2025-11-02 09:40:20.609503547 +0000 3 | @@ -1435,6 +1435,8 @@ 4 | } 5 | } 6 | 7 | +static int cs8409_apple(struct hda_codec *codec); 8 | + 9 | static int cs8409_probe(struct hda_codec *codec, const struct hda_device_id *id) 10 | { 11 | int err; 12 | @@ -1442,8 +1444,19 @@ 13 | if (!cs8409_alloc_spec(codec)) 14 | return -ENOMEM; 15 | 16 | + printk("snd_hda_intel: Primary cs8409\n"); 17 | + 18 | snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups); 19 | 20 | + // this seems the easiest way to separate and jump into the code for handling Apple machines using the 8409 21 | + // note now freeing the just allocated spec - this undos the delayed work as not using mutex yet 22 | + if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET) { 23 | + printk("snd_hda_intel: Primary patch_cs8409 NOT FOUND trying APPLE\n"); 24 | + cs8409_remove(codec); 25 | + err = cs8409_apple(codec); 26 | + return err; 27 | + } 28 | + 29 | codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id, 30 | codec->bus->pci->subsystem_vendor, 31 | codec->bus->pci->subsystem_device); 32 | @@ -1471,6 +1484,12 @@ 33 | .stream_pm = snd_hda_gen_stream_pm, 34 | }; 35 | 36 | + 37 | +// for the moment split the new code into an include file 38 | + 39 | +#include "cirrus_apple.h" 40 | + 41 | + 42 | static const struct hda_device_id snd_hda_id_cs8409[] = { 43 | HDA_CODEC_ID(0x10138409, "CS8409"), 44 | {} /* terminator */ 45 | -------------------------------------------------------------------------------- /patch_patch_cs8409.c.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.c b/patch_cirrus/patch_cs8409.c 2 | index aff2b5a..7e9c07c 100644 3 | --- a/kernel_sources/patch_cs8409.c 4 | +++ b/patch_cirrus/patch_cs8409.c 5 | @@ -1270,6 +1270,8 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac 6 | } 7 | } 8 | 9 | +static int patch_cs8409_apple(struct hda_codec *codec); 10 | + 11 | static int patch_cs8409(struct hda_codec *codec) 12 | { 13 | int err; 14 | @@ -1277,8 +1279,19 @@ static int patch_cs8409(struct hda_codec *codec) 15 | if (!cs8409_alloc_spec(codec)) 16 | return -ENOMEM; 17 | 18 | + printk("snd_hda_intel: Primary patch_cs8409\n"); 19 | + 20 | snd_hda_pick_fixup(codec, cs8409_models, cs8409_fixup_tbl, cs8409_fixups); 21 | 22 | + // this seems the easiest way to separate and jump into the code for handling Apple machines using the 8409 23 | + // note now freeing the just allocated spec - this undos the delayed work as not using mutex yet 24 | + if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET) { 25 | + printk("snd_hda_intel: Primary patch_cs8409 NOT FOUND trying APPLE\n"); 26 | + cs8409_free(codec); 27 | + err = patch_cs8409_apple(codec); 28 | + return err; 29 | + } 30 | + 31 | codec_dbg(codec, "Picked ID=%d, VID=%08x, DEV=%08x\n", codec->fixup_id, 32 | codec->bus->pci->subsystem_vendor, 33 | codec->bus->pci->subsystem_device); 34 | @@ -1295,6 +1308,12 @@ static int patch_cs8409(struct hda_codec *codec) 35 | return 0; 36 | } 37 | 38 | + 39 | +// for the moment split the new code into an include file 40 | + 41 | +#include "patch_cirrus_apple.h" 42 | + 43 | + 44 | static const struct hda_device_id snd_hda_id_cs8409[] = { 45 | HDA_CODEC_ENTRY(0x10138409, "CS8409", patch_cs8409), 46 | {} /* terminator */ 47 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | 2 | NOTE that the headphone plugin/unplug events use unsolicited responses which under linux seem to be executed concurrently 3 | with other commands. 4 | I have implemented a blocking system to ensure the response verb blocks are done serially (which seems to be how OSX does this). 5 | I do not know enough about the internals of the linux kernel module to know if there are better ways of doing this. 6 | As these verb blocks last multiseconds using simple linux kernel mutex locks (as done in other parts of the sound module 7 | for single commands) dont seem to be the right approach but I could be wrong. 8 | There are still issues with concurrency to be handled eg if you plugin and quickly start something playing - the play setup 9 | verbs still need to be delayed while the plugin block finishes. 10 | Currently I just physically wait a few seconds after eg plugging in before starting to play. 11 | Plugging while playing and then unplugging while playing is known to work. 12 | 13 | Input nodes (internal mike, external mike, linein) now setup as per OSX ie using OSX format. 14 | NOT linked to any actual input streams. 15 | SPDIF not implemented. 16 | 17 | Power down/sleep completely unknown and untested. 18 | 19 | 20 | 21 | Comments on what OSX seems to be doing. 22 | 23 | The 8409 seems to be acting as a simple digital transformation system for speaker sound. 24 | The incoming bit stream is converted to a TDM digital stream and sent to the amplifiers which 25 | do the actual digital analogue conversion. 26 | No processing is done by the 8409 - no parameters are set on the hda output nodes except that 27 | the output node pins (0x24, 0x25) are set to output. 28 | (The node chain is 0x02 -> 0x24, 0x03 -> 0x25 with 0x02 1st 2 channels, 0x03 2nd 2 channels). 29 | All I2C programming and TDM setup is done via the vendor node 0x47 using coef index/coef proc writes/reads. 30 | The MAX98706 amp programming is consistent with the MAX98372 documentation. 31 | It appears the amps programming is fixed so eg gain control is not done on the amps either. 32 | 33 | So I think Apple performs all input processing (conversion, volume etc) at higher CoreAudio levels 34 | which ends up as 44.1 kHz, 24 bit 4 channel audio which is output by the 8409 with no additional processing. 35 | 36 | 37 | Issues: 38 | 39 | Because the format is fixed at 44.1 kHz, 24 bit (S24_3LE) 4 channel and the format is set by undocumented vendor node 40 | commands its not clear if other formats can be supported in the 8409 itself. 41 | It appears now that Apples set up can take eg S24_LE format and S32_LE format. 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # snd_hda_macbookpro 2 | 3 | This is a kernel driver for sound on Macs with Cirrus 8409 HDA chips. 4 | Sound output is now reasonably complete and integrated with Linux. 5 | Sound input still needs work. 6 | 7 | 8 | It will play audio through Internal speakers or headphones. 9 | 10 | The primary audio should be set to Analogue Stereo Output in the Settings Audio dialog. 11 | 12 | 13 | Sound recording from internal mike and headset mike is not yet fully interfaced with Linux user side. 14 | 15 | The recorded sound level is very low but this is the sound level as returned in OSX. 16 | Amplification will be required eg using something like PulseEffects. 17 | 18 | 19 | The hardware device sound format is limited to 2/4 channel 44.1 kHz S24_LE S32_LE. 20 | As long as use the default device volume control, other formats, frequencies work. 21 | 22 | 23 | NOTA BENE: The direct hardware device (hw:0,0) and plughw:0,0 device have NO volume control so will be VERY loud! 24 | 25 | 26 | Currently this works with MAX98706, SSM3515 and TAS5764L amplifiers. 27 | It will NOT work with other amplifiers as each amplifier requires specific programming. 28 | 29 | 30 | Power down/sleep completely unknown and untested. 31 | At the moment everything is permanently powered on. 32 | 33 | 34 | The Apple speaker setup is 4 speakers as a left tweeter, left woofer, right tweeter and right woofer 35 | so this is actually a classic HiFi stereo (ie 2 channel) speaker system. 36 | (These names are listed in the layout files under AppleHDA.kext/Contents/Resources). 37 | 38 | The channel order for Linux has been modified to left tweeter, right tweeter and left woofer, right woofer 39 | as this fits in with the Linux way much better. 40 | 41 | The driver also has been modified to duplicate a stereo sound source onto the second stereo channel so all 42 | speakers are driven (this essentially replicates the snd_hda_multi_out_analog_prepare function). 43 | 44 | This will not sound the same as Apple (which is known to be using specific digital filter effects in CoreAudio). 45 | 46 | To create a more Apple-like sound requires creating eg an Alsa pseudo device to channel duplicate a stereo sound 47 | and apply different digital filters to the tweeter and woofer channels. 48 | 49 | 50 | NOTE. My primary testing kernel is now Ubuntu LTS 24.04 6.8. 51 | 52 | 53 | NOTA BENE. As of linux kernel 6.17 the sound kernel source directory has been completely re-organized. 54 | The installation script now works for 6.17 kernel versions (and later when they arrive). 55 | The old installation script is now called install.cirrus.driver.pre617.sh. 56 | The new version of the install.cirrus.driver.sh script will detect your kernel version and exec 57 | the old installation script as needed. 58 | For older kernel version you can just run the old installation script directly 59 | ie install.cirrus.driver.pre617.sh. 60 | Note that for kernel version 6.17 new files and directories have been added to the repo 61 | rather than attempting to update the pre 6.17 versions (as the kernel source changes also 62 | involved name changes and the new files are more consistent with the new kernel names). 63 | 64 | DKMS for 6.17 is untested and highly likely wont work without changes. 65 | 66 | 67 | The following installation setup provided by leifliddy. 68 | 69 | 70 | 71 | Compiling and installing driver: 72 | ------------- 73 | 74 | **fedora package install** 75 | ``` 76 | dnf install gcc kernel-devel make patch wget 77 | ``` 78 | **ubuntu package install** 79 | ``` 80 | apt install gcc linux-headers-generic make patch wget 81 | ``` 82 | **arch package install** 83 | ``` 84 | pacman -S gcc linux-headers make patch wget 85 | ``` 86 | **void package install** 87 | ``` 88 | xbps-install -S gcc make linux-headers patch wget 89 | ``` 90 | 91 | **build driver** 92 | ``` 93 | git clone https://github.com/davidjo/snd_hda_macbookpro.git 94 | cd snd_hda_macbookpro/ 95 | #run the following command as root or with sudo 96 | ./install.cirrus.driver.sh 97 | reboot 98 | ``` 99 | -------------------------------------------------------------------------------- /patch_patch_cirrus.c.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cirrus.c b/patch_cirrus/patch_cirrus.c 2 | index f46204a..678fbca 100644 3 | --- a/kernel_sources/patch_cirrus.c 4 | +++ b/patch_cirrus/patch_cirrus.c 5 | @@ -9,6 +9,7 @@ 6 | #include 7 | #include 8 | #include 9 | +#include 10 | #include 11 | #include 12 | #include "hda_local.h" 13 | @@ -110,7 +111,7 @@ enum { 14 | * 1 DAC => HP(sense) / Speakers, 15 | * 1 ADC <= LineIn(sense) / MicIn / DMicIn, 16 | * 1 SPDIF OUT => SPDIF Trasmitter(sense) 17 | -*/ 18 | + */ 19 | #define CS4210_DAC_NID 0x02 20 | #define CS4210_ADC_NID 0x03 21 | #define CS4210_VENDOR_NID 0x0B 22 | @@ -129,6 +130,7 @@ enum { 23 | static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) 24 | { 25 | struct cs_spec *spec = codec->spec; 26 | + 27 | snd_hda_codec_write(codec, spec->vendor_nid, 0, 28 | AC_VERB_SET_COEF_INDEX, idx); 29 | return snd_hda_codec_read(codec, spec->vendor_nid, 0, 30 | @@ -139,6 +141,7 @@ static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx, 31 | unsigned int coef) 32 | { 33 | struct cs_spec *spec = codec->spec; 34 | + 35 | snd_hda_codec_write(codec, spec->vendor_nid, 0, 36 | AC_VERB_SET_COEF_INDEX, idx); 37 | snd_hda_codec_write(codec, spec->vendor_nid, 0, 38 | @@ -175,6 +178,7 @@ static void cs_automute(struct hda_codec *codec) 39 | static bool is_active_pin(struct hda_codec *codec, hda_nid_t nid) 40 | { 41 | unsigned int val; 42 | + 43 | val = snd_hda_codec_get_pincfg(codec, nid); 44 | return (get_defcfg_connect(val) != AC_JACK_PORT_NONE); 45 | } 46 | @@ -193,7 +197,7 @@ static void init_input_coef(struct hda_codec *codec) 47 | coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off 48 | * No effect if SPDIF_OUT2 is 49 | * selected in IDX_SPDIF_CTL. 50 | - */ 51 | + */ 52 | 53 | cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); 54 | } 55 | @@ -267,13 +271,6 @@ static const struct hda_verb cs_errata_init_verbs[] = { 56 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, 57 | {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, 58 | {0x11, AC_VERB_SET_PROC_STATE, 0x00}, 59 | - 60 | -#if 0 /* Don't to set to D3 as we are in power-up sequence */ 61 | - {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ 62 | - {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ 63 | - /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ 64 | -#endif 65 | - 66 | {} /* terminator */ 67 | }; 68 | 69 | @@ -361,8 +358,10 @@ static int cs_parse_auto_config(struct hda_codec *codec) 70 | /* keep the ADCs powered up when it's dynamically switchable */ 71 | if (spec->gen.dyn_adc_switch) { 72 | unsigned int done = 0; 73 | + 74 | for (i = 0; i < spec->gen.input_mux.num_items; i++) { 75 | int idx = spec->gen.dyn_adc_idx[i]; 76 | + 77 | if (done & (1 << idx)) 78 | continue; 79 | snd_hda_gen_fix_pin_power(codec, 80 | @@ -496,6 +495,7 @@ static void cs420x_fixup_gpio_13(struct hda_codec *codec, 81 | { 82 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { 83 | struct cs_spec *spec = codec->spec; 84 | + 85 | spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ 86 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ 87 | spec->gpio_mask = spec->gpio_dir = 88 | @@ -508,6 +508,7 @@ static void cs420x_fixup_gpio_23(struct hda_codec *codec, 89 | { 90 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { 91 | struct cs_spec *spec = codec->spec; 92 | + 93 | spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */ 94 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ 95 | spec->gpio_mask = spec->gpio_dir = 96 | @@ -652,6 +653,7 @@ static void cs4208_fixup_gpio0(struct hda_codec *codec, 97 | { 98 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { 99 | struct cs_spec *spec = codec->spec; 100 | + 101 | spec->gpio_eapd_hp = 0; 102 | spec->gpio_eapd_speaker = 1; 103 | spec->gpio_mask = spec->gpio_dir = 104 | @@ -806,7 +808,7 @@ static int patch_cs4208(struct hda_codec *codec) 105 | * 1 DAC => HP(sense) / Speakers, 106 | * 1 ADC <= LineIn(sense) / MicIn / DMicIn, 107 | * 1 SPDIF OUT => SPDIF Trasmitter(sense) 108 | -*/ 109 | + */ 110 | 111 | /* CS4210 board names */ 112 | static const struct hda_model_fixup cs421x_models[] = { 113 | @@ -849,6 +851,7 @@ static void cs421x_fixup_sense_b(struct hda_codec *codec, 114 | const struct hda_fixup *fix, int action) 115 | { 116 | struct cs_spec *spec = codec->spec; 117 | + 118 | if (action == HDA_FIXUP_ACT_PRE_PROBE) 119 | spec->sense_b = 1; 120 | } 121 | @@ -874,9 +877,9 @@ static const struct hda_verb cs421x_coef_init_verbs[] = { 122 | {0x0B, AC_VERB_SET_PROC_STATE, 1}, 123 | {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG}, 124 | /* 125 | - Disable Coefficient Index Auto-Increment(DAI)=1, 126 | - PDREF=0 127 | - */ 128 | + * Disable Coefficient Index Auto-Increment(DAI)=1, 129 | + * PDREF=0 130 | + */ 131 | {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 }, 132 | 133 | {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG}, 134 | @@ -963,12 +966,12 @@ static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol, 135 | 136 | coef &= ~0x0003; 137 | coef |= (vol & 0x0003); 138 | - if (original_coef == coef) 139 | - return 0; 140 | - else { 141 | + if (original_coef != coef) { 142 | cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef); 143 | return 1; 144 | } 145 | + 146 | + return 0; 147 | } 148 | 149 | static const struct snd_kcontrol_new cs421x_speaker_boost_ctl = { 150 | @@ -1007,8 +1010,8 @@ static void cs4210_pinmux_init(struct hda_codec *codec) 151 | is_active_pin(codec, CS421X_DMIC_PIN_NID)) { 152 | 153 | /* 154 | - GPIO or SENSE_B forced - disconnect the DMIC pin. 155 | - */ 156 | + * GPIO or SENSE_B forced - disconnect the DMIC pin. 157 | + */ 158 | def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID); 159 | def_conf &= ~AC_DEFCFG_PORT_CONN; 160 | def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT); 161 | @@ -1047,6 +1050,7 @@ static void parse_cs421x_digital(struct hda_codec *codec) 162 | 163 | for (i = 0; i < cfg->dig_outs; i++) { 164 | hda_nid_t nid = cfg->dig_out_pins[i]; 165 | + 166 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { 167 | spec->spdif_detect = 1; 168 | snd_hda_jack_detect_enable_callback(codec, nid, 169 | @@ -1125,9 +1129,9 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) 170 | 171 | #ifdef CONFIG_PM 172 | /* 173 | - Manage PDREF, when transitioning to D3hot 174 | - (DAC,ADC) -> D3, PDREF=1, AFG->D3 175 | -*/ 176 | + * Manage PDREF, when transitioning to D3hot 177 | + * (DAC,ADC) -> D3, PDREF=1, AFG->D3 178 | + */ 179 | static int cs421x_suspend(struct hda_codec *codec) 180 | { 181 | struct cs_spec *spec = codec->spec; 182 | @@ -1178,10 +1182,10 @@ static int patch_cs4210(struct hda_codec *codec) 183 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 184 | 185 | /* 186 | - Update the GPIO/DMIC/SENSE_B pinmux before the configuration 187 | - is auto-parsed. If GPIO or SENSE_B is forced, DMIC input 188 | - is disabled. 189 | - */ 190 | + * Update the GPIO/DMIC/SENSE_B pinmux before the configuration 191 | + * is auto-parsed. If GPIO or SENSE_B is forced, DMIC input 192 | + * is disabled. 193 | + */ 194 | cs4210_pinmux_init(codec); 195 | 196 | err = cs421x_parse_auto_config(codec); 197 | @@ -1219,7 +1223,6 @@ static int patch_cs4213(struct hda_codec *codec) 198 | return err; 199 | } 200 | 201 | - 202 | /* 203 | * patch entries 204 | */ 205 | -------------------------------------------------------------------------------- /install.cirrus.driver.pre617.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NOTA BENE - this script should be run as root 4 | 5 | set -e 6 | 7 | while [ $# -gt 0 ] 8 | do 9 | case $1 in 10 | -i|--install) dkms_action='install';; 11 | -k|--kernel) UNAME=$2; [[ -z $UNAME ]] && echo '-k|--kernel must be followed by a kernel version' && exit 1;; 12 | -r|--remove) dkms_action='remove';; 13 | -u|--uninstall) dkms_action='remove';; 14 | (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;; 15 | (*) break;; 16 | esac 17 | shift 18 | done 19 | 20 | UNAME=${1:-$(uname -r)} 21 | kernel_version=$(echo $UNAME | cut -d '-' -f1) #ie 5.2.7 22 | major_version=$(echo $kernel_version | cut -d '.' -f1) 23 | minor_version=$(echo $kernel_version | cut -d '.' -f2) 24 | major_minor=${major_version}${minor_version} 25 | 26 | revision=$(echo $UNAME | cut -d '.' -f3) 27 | revpart1=$(echo $revision | cut -d '-' -f1) 28 | revpart2=$(echo $revision | cut -d '-' -f2) 29 | revpart3=$(echo $revision | cut -d '-' -f3) 30 | 31 | if [ $major_version -eq 5 -a $minor_version -lt 13 ]; then 32 | sed -i 's/^BUILT_MODULE_NAME\[0\].*$/BUILT_MODULE_NAME[0]="snd-hda-codec-cirrus"/' dkms.conf 33 | PATCH_CIRRUS=true 34 | else 35 | sed -i 's/^BUILT_MODULE_NAME\[0\].*$/BUILT_MODULE_NAME[0]="snd-hda-codec-cs8409"/' dkms.conf 36 | PATCH_CIRRUS=false 37 | fi 38 | 39 | if [[ $dkms_action == 'install' ]]; then 40 | bash dkms.sh 41 | # note that Ubuntu, Debian, Fedora and others (see dkms man page) install to updates/dkms 42 | # and ignore DEST_MODULE_LOCATION 43 | # we DO want updates so that the original module is not overwritten 44 | # (although the original module should be copied to under /var/lib/dkms if needed for other distributions) 45 | update_dir="/lib/modules/${UNAME}/updates" 46 | echo -e "\ncontents of $update_dir/dkms" 47 | ls -lA $update_dir/dkms 48 | exit 49 | elif [[ $dkms_action == 'remove' ]]; then 50 | bash dkms.sh -r 51 | exit 52 | fi 53 | 54 | if [ $major_version == '4' ]; then 55 | echo "Kernel 4 versions no longer supported" 56 | fi 57 | 58 | if [ $major_version -eq 5 -a $minor_version -lt 8 ]; then 59 | echo "Kernel 5 versions less than 5.8 no longer supported" 60 | fi 61 | 62 | isdebian=0 63 | isfedora=0 64 | isarch=0 65 | isvoid=0 66 | 67 | if [ -d /usr/src/linux-headers-${UNAME} ]; then 68 | # Debian Based Distro 69 | isdebian=1 70 | : 71 | elif [ -d /usr/src/kernels/${UNAME} ]; then 72 | # Fedora Based Distro 73 | isfedora=1 74 | : 75 | elif [ -d /usr/lib/modules/${UNAME} ]; then 76 | # Arch Based Distro 77 | isarch=1 78 | : 79 | elif [ -d /usr/src/kernel-headers-${UNAME} ]; then 80 | # Void Linux 81 | isvoid=1 82 | : 83 | else 84 | echo "linux kernel headers not found:" 85 | echo "Debian (eg Ubuntu): /usr/src/linux-headers-${UNAME}" 86 | echo "Fedora: /usr/src/kernels/${UNAME}" 87 | echo "Arch: /usr/lib/modules/${UNAME}" 88 | echo "Void: /usr/src/kernel-headers-${UNAME}" 89 | echo "assuming the linux kernel headers package is not installed" 90 | echo "please install the appropriate linux kernel headers package:" 91 | echo "Debian/Ubuntu: sudo apt install linux-headers-${UNAME}" 92 | echo "Fedora: sudo dnf install kernel-headers" 93 | echo "Arch (also Manjaro): Linux: sudo pacman -S linux-headers" 94 | echo "Void Linux: xbps-install -S linux-headers" 95 | 96 | exit 1 97 | 98 | fi 99 | 100 | # note that the update_dir definition below relies on a symbolic link of /lib to /usr/lib on Arch 101 | cur_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) 102 | build_dir='build' 103 | patch_dir="$cur_dir/patch_cirrus" 104 | hda_dir="$cur_dir/$build_dir/hda" 105 | update_dir="/lib/modules/${UNAME}/updates" 106 | 107 | [[ -d $hda_dir ]] && rm -rf $hda_dir 108 | [[ ! -d $build_dir ]] && mkdir $build_dir 109 | 110 | # fedora doesnt seem to install patch by default so need to explicitly install it 111 | if [ $isfedora -ge 1 ]; then 112 | echo "Ensure the patch package is installed" 113 | [[ ! $(command -v patch) ]] && dnf install -y patch 114 | fi 115 | 116 | # we need to handle Ubuntu based distributions eg Mint here 117 | isubuntu=0 118 | if [ $(grep '^NAME=' /etc/os-release | grep -c Ubuntu) -eq 1 ]; then 119 | isubuntu=1 120 | fi 121 | if [ $(grep '^NAME=' /etc/os-release | grep -c "Linux Mint") -eq 1 ]; then 122 | isubuntu=1 123 | fi 124 | 125 | if [ $isubuntu -ge 1 ]; then 126 | 127 | # NOTE for Ubuntu we need to use the distribution kernel sources as they seem 128 | # to be significantly modified from the mainline kernel sources generally with backports from later kernels 129 | # (so far the actual debian kernels seem to be close to mainline kernels) 130 | 131 | # NOTA BENE this will likely NOT work for Ubuntu hwe kernels which are even more highly 132 | # modified with extensive backports from later kernel versions 133 | # (and in any case there is no linux-source-... package for hwe kernels) 134 | 135 | if [ ! -e /usr/src/linux-source-$kernel_version.tar.bz2 ]; then 136 | 137 | echo "Ubuntu linux kernel source not found in /usr/src: /usr/src/linux-source-$kernel_version.tar.bz2" 138 | echo "assuming the linux kernel source package is not installed" 139 | echo "please install the linux kernel source package:" 140 | echo "sudo apt install linux-source-$kernel_version" 141 | echo "NOTE - This does not work for HWE kernels" 142 | 143 | exit 1 144 | 145 | fi 146 | 147 | tar --strip-components=3 -xvf /usr/src/linux-source-$kernel_version.tar.bz2 --directory=build/ linux-source-$kernel_version/sound/pci/hda 148 | 149 | else 150 | # here we assume the distribution kernel source is essentially the mainline kernel source 151 | 152 | set +e 153 | 154 | # attempt to download linux-x.x.x.tar.xz kernel 155 | wget -c https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/linux-$kernel_version.tar.xz -P $build_dir 156 | 157 | if [[ $? -ne 0 ]]; then 158 | echo "Failed to download linux-$kernel_version.tar.xz" 159 | echo "Trying to download base kernel version linux-$major_version.$minor_version.tar.xz" 160 | echo "This may lead to build failures as too old" 161 | echo "If this is an Ubuntu-based distribution this almost certainly will fail to build" 162 | echo "" 163 | # if first attempt fails, attempt to download linux-x.x.tar.xz kernel 164 | kernel_version=$major_version.$minor_version 165 | wget -c https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/linux-$kernel_version.tar.xz -P $build_dir 166 | 167 | [[ $? -ne 0 ]] && echo "kernel could not be downloaded...exiting" && exit 168 | fi 169 | 170 | set -e 171 | 172 | tar --strip-components=3 -xvf $build_dir/linux-$kernel_version.tar.xz --directory=build/ linux-$kernel_version/sound/pci/hda 173 | 174 | fi 175 | 176 | mv $hda_dir/Makefile $hda_dir/Makefile.orig 177 | cp $patch_dir/Makefile $patch_dir/patch_cirrus_* $hda_dir 178 | pushd $hda_dir > /dev/null 179 | # define the ubuntu/mainline versions that work at the moment 180 | # for ubuntu allow a range of revisions that work 181 | current_major=5 182 | current_minor=19 183 | current_minor_ubuntu=15 184 | current_rev_ubuntu=47 185 | latest_rev_ubuntu=71 186 | 187 | iscurrent=0 188 | if [ $isubuntu -ge 1 ]; then 189 | if [ $major_version -gt $current_major ]; then 190 | iscurrent=2 191 | elif [ $major_version -eq $current_major -a $minor_version -gt $current_minor_ubuntu ]; then 192 | iscurrent=2 193 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -gt $latest_rev_ubuntu ]; then 194 | iscurrent=2 195 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -gt $current_rev_ubuntu ]; then 196 | iscurrent=1 197 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -eq $current_rev_ubuntu ]; then 198 | iscurrent=1 199 | else 200 | iscurrent=-1 201 | fi 202 | else 203 | if [ $major_version -gt $current_major ]; then 204 | iscurrent=2 205 | elif [ $major_version -eq $current_major -a $minor_version -gt $current_minor ]; then 206 | iscurrent=2 207 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor ]; then 208 | iscurrent=1 209 | else 210 | iscurrent=-1 211 | fi 212 | fi 213 | 214 | if [ $iscurrent -gt 1 ]; then 215 | echo "Kernel version later than implemented version - there may be build problems" 216 | fi 217 | 218 | if [ $major_version -eq 5 -a $minor_version -lt 13 ]; then 219 | patch -b -p2 <../../patch_patch_cirrus.c.diff 220 | else 221 | if [ $isubuntu -ge 1 ]; then 222 | 223 | patch -b -p2 <../../patch_patch_cs8409.c.diff 224 | 225 | if [ $iscurrent -ge 0 ]; then 226 | patch -b -p2 <../../patch_patch_cs8409.h.diff 227 | else 228 | patch -b -p2 <../../patches/patch_patch_cs8409.h.ubuntu.pre51547.diff 229 | fi 230 | 231 | if [ $iscurrent -ge 0 ]; then 232 | patch -b -p2 <../../patch_patch_cirrus_apple.h.diff 233 | fi 234 | 235 | else 236 | patch -b -p2 <../../patch_patch_cs8409.c.diff 237 | 238 | if [ $iscurrent -ge 0 ]; then 239 | patch -b -p2 <../../patch_patch_cs8409.h.diff 240 | else 241 | patch -b -p2 <../../patches/patch_patch_cs8409.h.main.pre519.diff 242 | fi 243 | 244 | cp $patch_dir/Makefile $patch_dir/patch_cirrus_* $hda_dir/ 245 | 246 | if [ $iscurrent -ge 0 ]; then 247 | patch -b -p2 <../../patch_patch_cirrus_apple.h.diff 248 | fi 249 | 250 | fi 251 | fi 252 | 253 | popd > /dev/null 254 | 255 | [[ ! $dkms_action == 'install' ]] && [[ ! -d $update_dir ]] && mkdir $update_dir 256 | 257 | if [ $PATCH_CIRRUS = true ]; then 258 | make PATCH_CIRRUS=1 259 | make install PATCH_CIRRUS=1 260 | 261 | else 262 | make KERNELRELEASE=$UNAME 263 | make install KERNELRELEASE=$UNAME 264 | 265 | fi 266 | 267 | echo -e "\ncontents of $update_dir" 268 | ls -lA $update_dir 269 | -------------------------------------------------------------------------------- /install.cirrus.driver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NOTA BENE - this script should be run as root 4 | 5 | set -e 6 | 7 | while [ $# -gt 0 ] 8 | do 9 | case $1 in 10 | -i|--install) dkms_action='install';; 11 | -k|--kernel) UNAME=$2; [[ -z $UNAME ]] && echo '-k|--kernel must be followed by a kernel version' && exit 1;; 12 | -r|--remove) dkms_action='remove';; 13 | -u|--uninstall) dkms_action='remove';; 14 | (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;; 15 | (*) break;; 16 | esac 17 | shift 18 | done 19 | 20 | UNAME=${1:-$(uname -r)} 21 | kernel_version=$(echo $UNAME | cut -d '-' -f1) #ie 5.2.7 22 | major_version=$(echo $kernel_version | cut -d '.' -f1) 23 | minor_version=$(echo $kernel_version | cut -d '.' -f2) 24 | major_minor=${major_version}${minor_version} 25 | 26 | revision=$(echo $UNAME | cut -d '.' -f3) 27 | revpart1=$(echo $revision | cut -d '-' -f1) 28 | revpart2=$(echo $revision | cut -d '-' -f2) 29 | revpart3=$(echo $revision | cut -d '-' -f3) 30 | 31 | if [ $major_version -lt 6 -o \( $major_version -eq 6 -a $minor_version -lt 17 \) ]; then 32 | 33 | exec ./install.cirrus.driver.pre617.sh "${@}" 34 | 35 | fi 36 | 37 | 38 | if [[ $dkms_action != '' ]]; then 39 | echo "WARNING: dkms is untested for 6.17 and likely wont work!!!" 40 | exit 1 41 | fi 42 | 43 | sed -i 's/^BUILT_MODULE_NAME\[0\].*$/BUILT_MODULE_NAME[0]="snd-hda-codec-cs8409"/' dkms.conf 44 | PATCH_CIRRUS=false 45 | 46 | if [[ $dkms_action == 'install' ]]; then 47 | bash dkms.sh 48 | # note that Ubuntu, Debian, Fedora and others (see dkms man page) install to updates/dkms 49 | # and ignore DEST_MODULE_LOCATION 50 | # we DO want updates so that the original module is not overwritten 51 | # (although the original module should be copied to under /var/lib/dkms if needed for other distributions) 52 | update_dir="/lib/modules/${UNAME}/updates" 53 | echo -e "\ncontents of $update_dir/dkms" 54 | ls -lA $update_dir/dkms 55 | exit 56 | elif [[ $dkms_action == 'remove' ]]; then 57 | bash dkms.sh -r 58 | exit 59 | fi 60 | 61 | isdebian=0 62 | isfedora=0 63 | isarch=0 64 | isvoid=0 65 | 66 | if [ -d /usr/src/linux-headers-${UNAME} ]; then 67 | # Debian Based Distro 68 | isdebian=1 69 | : 70 | elif [ -d /usr/src/kernels/${UNAME} ]; then 71 | # Fedora Based Distro 72 | isfedora=1 73 | : 74 | elif [ -d /usr/lib/modules/${UNAME} ]; then 75 | # Arch Based Distro 76 | isarch=1 77 | : 78 | elif [ -d /usr/src/kernel-headers-${UNAME} ]; then 79 | # Void Linux 80 | isvoid=1 81 | : 82 | else 83 | echo "linux kernel headers not found:" 84 | echo "Debian (eg Ubuntu): /usr/src/linux-headers-${UNAME}" 85 | echo "Fedora: /usr/src/kernels/${UNAME}" 86 | echo "Arch: /usr/lib/modules/${UNAME}" 87 | echo "Void: /usr/src/kernel-headers-${UNAME}" 88 | echo "assuming the linux kernel headers package is not installed" 89 | echo "please install the appropriate linux kernel headers package:" 90 | echo "Debian/Ubuntu: sudo apt install linux-headers-${UNAME}" 91 | echo "Fedora: sudo dnf install kernel-headers" 92 | echo "Arch (also Manjaro): Linux: sudo pacman -S linux-headers" 93 | echo "Void Linux: xbps-install -S linux-headers" 94 | 95 | exit 1 96 | 97 | fi 98 | 99 | # note that the update_dir definition below relies on a symbolic link of /lib to /usr/lib on Arch 100 | cur_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) 101 | build_dir='build' 102 | patch_dir="$cur_dir/patch_cirrus" 103 | makefiles_dir="$cur_dir/makefiles" 104 | hda_dir="$cur_dir/$build_dir/hda" 105 | update_dir="/lib/modules/${UNAME}/updates" 106 | 107 | [[ -d $hda_dir ]] && rm -rf $hda_dir 108 | [[ ! -d $build_dir ]] && mkdir $build_dir 109 | 110 | # fedora doesnt seem to install patch by default so need to explicitly install it 111 | if [ $isfedora -ge 1 ]; then 112 | echo "Ensure the patch package is installed" 113 | [[ ! $(command -v patch) ]] && dnf install -y patch 114 | fi 115 | 116 | # we need to handle Ubuntu based distributions eg Mint here 117 | isubuntu=0 118 | if [ $(grep '^NAME=' /etc/os-release | grep -c Ubuntu) -eq 1 ]; then 119 | isubuntu=1 120 | fi 121 | if [ $(grep '^NAME=' /etc/os-release | grep -c "Linux Mint") -eq 1 ]; then 122 | isubuntu=1 123 | fi 124 | 125 | if [ $isubuntu -ge 1 ]; then 126 | 127 | # NOTE for Ubuntu we need to use the distribution kernel sources as they seem 128 | # to be significantly modified from the mainline kernel sources generally with backports from later kernels 129 | # (so far the actual debian kernels seem to be close to mainline kernels) 130 | 131 | # NOTA BENE this will likely NOT work for Ubuntu hwe kernels which are even more highly 132 | # modified with extensive backports from later kernel versions 133 | # (and in any case there is no linux-source-... package for hwe kernels) 134 | 135 | if [ ! -e /usr/src/linux-source-$kernel_version.tar.bz2 ]; then 136 | 137 | echo "Ubuntu linux kernel source not found in /usr/src: /usr/src/linux-source-$kernel_version.tar.bz2" 138 | echo "assuming the linux kernel source package is not installed" 139 | echo "please install the linux kernel source package:" 140 | echo "sudo apt install linux-source-$kernel_version" 141 | echo "NOTE - This does not work for HWE kernels" 142 | 143 | exit 1 144 | 145 | fi 146 | 147 | tar --strip-components=2 -xvf /usr/src/linux-source-$kernel_version.tar.bz2 --directory=build/ linux-source-$kernel_version/sound/hda 148 | 149 | else 150 | # here we assume the distribution kernel source is essentially the mainline kernel source 151 | 152 | set +e 153 | 154 | # attempt to download linux-x.x.x.tar.xz kernel 155 | wget -c https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/linux-$kernel_version.tar.xz -P $build_dir 156 | 157 | if [[ $? -ne 0 ]]; then 158 | echo "Failed to download linux-$kernel_version.tar.xz" 159 | echo "Trying to download base kernel version linux-$major_version.$minor_version.tar.xz" 160 | echo "This may lead to build failures as too old" 161 | echo "If this is an Ubuntu-based distribution this almost certainly will fail to build" 162 | echo "" 163 | # if first attempt fails, attempt to download linux-x.x.tar.xz kernel 164 | kernel_version=$major_version.$minor_version 165 | wget -c https://cdn.kernel.org/pub/linux/kernel/v$major_version.x/linux-$kernel_version.tar.xz -P $build_dir 166 | 167 | [[ $? -ne 0 ]] && echo "kernel could not be downloaded...exiting" && exit 168 | fi 169 | 170 | set -e 171 | 172 | tar --strip-components=2 -xvf $build_dir/linux-$kernel_version.tar.xz --directory=build/ linux-$kernel_version/sound/hda 173 | 174 | fi 175 | 176 | 177 | mv $hda_dir/Makefile $hda_dir/Makefile.orig 178 | mv $hda_dir/common/Makefile $hda_dir/common//Makefile.orig 179 | mv $hda_dir/codecs/Makefile $hda_dir/codecs//Makefile.orig 180 | mv $hda_dir/codecs/cirrus/Makefile $hda_dir/codecs/cirrus//Makefile.orig 181 | 182 | cp $makefiles_dir/Makefile $hda_dir 183 | cp $makefiles_dir/Makefile_common $hda_dir/common/Makefile 184 | cp $makefiles_dir/Makefile_codecs $hda_dir/codecs/Makefile 185 | cp $makefiles_dir/Makefile_cirrus $hda_dir/codecs/cirrus/Makefile 186 | 187 | # going with explicit file names now 188 | 189 | cp $patch_dir/cirrus_apple.h $hda_dir/codecs/cirrus 190 | cp $patch_dir/patch_cirrus_boot84.h $hda_dir/codecs/cirrus 191 | cp $patch_dir/patch_cirrus_new84.h $hda_dir/codecs/cirrus 192 | cp $patch_dir/patch_cirrus_real84.h $hda_dir/codecs/cirrus 193 | cp $patch_dir/patch_cirrus_hda_generic_copy.h $hda_dir/codecs/cirrus 194 | cp $patch_dir/patch_cirrus_real84_i2c.h $hda_dir/codecs/cirrus 195 | 196 | 197 | pushd $hda_dir > /dev/null 198 | # define the ubuntu/mainline versions that work at the moment 199 | # for ubuntu allow a range of revisions that work 200 | current_major=6 201 | current_minor=17 202 | current_minor_ubuntu=6 203 | current_rev_ubuntu=6 204 | latest_rev_ubuntu=6 205 | 206 | iscurrent=0 207 | if [ $isubuntu -ge 1 ]; then 208 | if [ $major_version -gt $current_major ]; then 209 | iscurrent=2 210 | elif [ $major_version -eq $current_major -a $minor_version -gt $current_minor_ubuntu ]; then 211 | iscurrent=2 212 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -gt $latest_rev_ubuntu ]; then 213 | iscurrent=2 214 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -gt $current_rev_ubuntu ]; then 215 | iscurrent=1 216 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor_ubuntu -a $revpart2 -eq $current_rev_ubuntu ]; then 217 | iscurrent=1 218 | else 219 | iscurrent=-1 220 | fi 221 | else 222 | if [ $major_version -gt $current_major ]; then 223 | iscurrent=2 224 | elif [ $major_version -eq $current_major -a $minor_version -gt $current_minor ]; then 225 | iscurrent=2 226 | elif [ $major_version -eq $current_major -a $minor_version -eq $current_minor ]; then 227 | iscurrent=1 228 | else 229 | iscurrent=-1 230 | fi 231 | fi 232 | 233 | if [ $iscurrent -gt 1 ]; then 234 | echo "Kernel version later than implemented version - there may be build problems" 235 | fi 236 | 237 | if [ $major_version -eq 6 -a $minor_version -ge 17 ]; then 238 | if [ $isubuntu -ge 1 ]; then 239 | 240 | patch -b -p1 <../../patch_cs8409.c.diff 241 | 242 | if [ $iscurrent -ge 0 ]; then 243 | patch -b -p1 <../../patch_cs8409.h.diff 244 | else 245 | echo "Error: older version not implmented yet" 246 | exit 1 247 | fi 248 | 249 | else 250 | patch -b -p1 <../../patch_cs8409.c.diff 251 | 252 | if [ $iscurrent -ge 0 ]; then 253 | patch -b -p1 <../../patch_cs8409.h.diff 254 | else 255 | echo "Error: older version not implmented yet" 256 | exit 1 257 | fi 258 | 259 | # this just redos the above copies - why was it in?? 260 | #cp $patch_dir/Makefile $patch_dir/patch_cirrus_* $hda_dir/ 261 | 262 | fi 263 | fi 264 | 265 | popd > /dev/null 266 | 267 | [[ ! $dkms_action == 'install' ]] && [[ ! -d $update_dir ]] && mkdir $update_dir 268 | 269 | make KERNELRELEASE=$UNAME 270 | make install KERNELRELEASE=$UNAME 271 | 272 | 273 | echo -e "\ncontents of $update_dir" 274 | ls -lA $update_dir 275 | -------------------------------------------------------------------------------- /patch_cirrus/cs8409.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* 3 | * HD audio codec driver for Cirrus Logic CS8409 HDA bridge chip 4 | * 5 | * Copyright (C) 2021 Cirrus Logic, Inc. and 6 | * Cirrus Logic International Semiconductor Ltd. 7 | */ 8 | 9 | #ifndef __CS8409_PATCH_H 10 | #define __CS8409_PATCH_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "hda_local.h" 18 | #include "hda_auto_parser.h" 19 | #include "hda_jack.h" 20 | #include "../generic.h" 21 | 22 | /* CS8409 Specific Definitions */ 23 | 24 | enum cs8409_pins { 25 | CS8409_PIN_ROOT, 26 | CS8409_PIN_AFG, 27 | CS8409_PIN_ASP1_OUT_A, 28 | CS8409_PIN_ASP1_OUT_B, 29 | CS8409_PIN_ASP1_OUT_C, 30 | CS8409_PIN_ASP1_OUT_D, 31 | CS8409_PIN_ASP1_OUT_E, 32 | CS8409_PIN_ASP1_OUT_F, 33 | CS8409_PIN_ASP1_OUT_G, 34 | CS8409_PIN_ASP1_OUT_H, 35 | CS8409_PIN_ASP2_OUT_A, 36 | CS8409_PIN_ASP2_OUT_B, 37 | CS8409_PIN_ASP2_OUT_C, 38 | CS8409_PIN_ASP2_OUT_D, 39 | CS8409_PIN_ASP2_OUT_E, 40 | CS8409_PIN_ASP2_OUT_F, 41 | CS8409_PIN_ASP2_OUT_G, 42 | CS8409_PIN_ASP2_OUT_H, 43 | CS8409_PIN_ASP1_IN_A, 44 | CS8409_PIN_ASP1_IN_B, 45 | CS8409_PIN_ASP1_IN_C, 46 | CS8409_PIN_ASP1_IN_D, 47 | CS8409_PIN_ASP1_IN_E, 48 | CS8409_PIN_ASP1_IN_F, 49 | CS8409_PIN_ASP1_IN_G, 50 | CS8409_PIN_ASP1_IN_H, 51 | CS8409_PIN_ASP2_IN_A, 52 | CS8409_PIN_ASP2_IN_B, 53 | CS8409_PIN_ASP2_IN_C, 54 | CS8409_PIN_ASP2_IN_D, 55 | CS8409_PIN_ASP2_IN_E, 56 | CS8409_PIN_ASP2_IN_F, 57 | CS8409_PIN_ASP2_IN_G, 58 | CS8409_PIN_ASP2_IN_H, 59 | CS8409_PIN_DMIC1, 60 | CS8409_PIN_DMIC2, 61 | CS8409_PIN_ASP1_TRANSMITTER_A, 62 | CS8409_PIN_ASP1_TRANSMITTER_B, 63 | CS8409_PIN_ASP1_TRANSMITTER_C, 64 | CS8409_PIN_ASP1_TRANSMITTER_D, 65 | CS8409_PIN_ASP1_TRANSMITTER_E, 66 | CS8409_PIN_ASP1_TRANSMITTER_F, 67 | CS8409_PIN_ASP1_TRANSMITTER_G, 68 | CS8409_PIN_ASP1_TRANSMITTER_H, 69 | CS8409_PIN_ASP2_TRANSMITTER_A, 70 | CS8409_PIN_ASP2_TRANSMITTER_B, 71 | CS8409_PIN_ASP2_TRANSMITTER_C, 72 | CS8409_PIN_ASP2_TRANSMITTER_D, 73 | CS8409_PIN_ASP2_TRANSMITTER_E, 74 | CS8409_PIN_ASP2_TRANSMITTER_F, 75 | CS8409_PIN_ASP2_TRANSMITTER_G, 76 | CS8409_PIN_ASP2_TRANSMITTER_H, 77 | CS8409_PIN_ASP1_RECEIVER_A, 78 | CS8409_PIN_ASP1_RECEIVER_B, 79 | CS8409_PIN_ASP1_RECEIVER_C, 80 | CS8409_PIN_ASP1_RECEIVER_D, 81 | CS8409_PIN_ASP1_RECEIVER_E, 82 | CS8409_PIN_ASP1_RECEIVER_F, 83 | CS8409_PIN_ASP1_RECEIVER_G, 84 | CS8409_PIN_ASP1_RECEIVER_H, 85 | CS8409_PIN_ASP2_RECEIVER_A, 86 | CS8409_PIN_ASP2_RECEIVER_B, 87 | CS8409_PIN_ASP2_RECEIVER_C, 88 | CS8409_PIN_ASP2_RECEIVER_D, 89 | CS8409_PIN_ASP2_RECEIVER_E, 90 | CS8409_PIN_ASP2_RECEIVER_F, 91 | CS8409_PIN_ASP2_RECEIVER_G, 92 | CS8409_PIN_ASP2_RECEIVER_H, 93 | CS8409_PIN_DMIC1_IN, 94 | CS8409_PIN_DMIC2_IN, 95 | CS8409_PIN_BEEP_GEN, 96 | CS8409_PIN_VENDOR_WIDGET 97 | }; 98 | 99 | enum cs8409_coefficient_index_registers { 100 | CS8409_DEV_CFG1, 101 | CS8409_DEV_CFG2, 102 | CS8409_DEV_CFG3, 103 | CS8409_ASP1_CLK_CTRL1, 104 | CS8409_ASP1_CLK_CTRL2, 105 | CS8409_ASP1_CLK_CTRL3, 106 | CS8409_ASP2_CLK_CTRL1, 107 | CS8409_ASP2_CLK_CTRL2, 108 | CS8409_ASP2_CLK_CTRL3, 109 | CS8409_DMIC_CFG, 110 | CS8409_BEEP_CFG, 111 | ASP1_RX_NULL_INS_RMV, 112 | ASP1_Rx_RATE1, 113 | ASP1_Rx_RATE2, 114 | ASP1_Tx_NULL_INS_RMV, 115 | ASP1_Tx_RATE1, 116 | ASP1_Tx_RATE2, 117 | ASP2_Rx_NULL_INS_RMV, 118 | ASP2_Rx_RATE1, 119 | ASP2_Rx_RATE2, 120 | ASP2_Tx_NULL_INS_RMV, 121 | ASP2_Tx_RATE1, 122 | ASP2_Tx_RATE2, 123 | ASP1_SYNC_CTRL, 124 | ASP2_SYNC_CTRL, 125 | ASP1_A_TX_CTRL1, 126 | ASP1_A_TX_CTRL2, 127 | ASP1_B_TX_CTRL1, 128 | ASP1_B_TX_CTRL2, 129 | ASP1_C_TX_CTRL1, 130 | ASP1_C_TX_CTRL2, 131 | ASP1_D_TX_CTRL1, 132 | ASP1_D_TX_CTRL2, 133 | ASP1_E_TX_CTRL1, 134 | ASP1_E_TX_CTRL2, 135 | ASP1_F_TX_CTRL1, 136 | ASP1_F_TX_CTRL2, 137 | ASP1_G_TX_CTRL1, 138 | ASP1_G_TX_CTRL2, 139 | ASP1_H_TX_CTRL1, 140 | ASP1_H_TX_CTRL2, 141 | ASP2_A_TX_CTRL1, 142 | ASP2_A_TX_CTRL2, 143 | ASP2_B_TX_CTRL1, 144 | ASP2_B_TX_CTRL2, 145 | ASP2_C_TX_CTRL1, 146 | ASP2_C_TX_CTRL2, 147 | ASP2_D_TX_CTRL1, 148 | ASP2_D_TX_CTRL2, 149 | ASP2_E_TX_CTRL1, 150 | ASP2_E_TX_CTRL2, 151 | ASP2_F_TX_CTRL1, 152 | ASP2_F_TX_CTRL2, 153 | ASP2_G_TX_CTRL1, 154 | ASP2_G_TX_CTRL2, 155 | ASP2_H_TX_CTRL1, 156 | ASP2_H_TX_CTRL2, 157 | ASP1_A_RX_CTRL1, 158 | ASP1_A_RX_CTRL2, 159 | ASP1_B_RX_CTRL1, 160 | ASP1_B_RX_CTRL2, 161 | ASP1_C_RX_CTRL1, 162 | ASP1_C_RX_CTRL2, 163 | ASP1_D_RX_CTRL1, 164 | ASP1_D_RX_CTRL2, 165 | ASP1_E_RX_CTRL1, 166 | ASP1_E_RX_CTRL2, 167 | ASP1_F_RX_CTRL1, 168 | ASP1_F_RX_CTRL2, 169 | ASP1_G_RX_CTRL1, 170 | ASP1_G_RX_CTRL2, 171 | ASP1_H_RX_CTRL1, 172 | ASP1_H_RX_CTRL2, 173 | ASP2_A_RX_CTRL1, 174 | ASP2_A_RX_CTRL2, 175 | ASP2_B_RX_CTRL1, 176 | ASP2_B_RX_CTRL2, 177 | ASP2_C_RX_CTRL1, 178 | ASP2_C_RX_CTRL2, 179 | ASP2_D_RX_CTRL1, 180 | ASP2_D_RX_CTRL2, 181 | ASP2_E_RX_CTRL1, 182 | ASP2_E_RX_CTRL2, 183 | ASP2_F_RX_CTRL1, 184 | ASP2_F_RX_CTRL2, 185 | ASP2_G_RX_CTRL1, 186 | ASP2_G_RX_CTRL2, 187 | ASP2_H_RX_CTRL1, 188 | ASP2_H_RX_CTRL2, 189 | CS8409_I2C_ADDR, 190 | CS8409_I2C_DATA, 191 | CS8409_I2C_CTRL, 192 | CS8409_I2C_STS, 193 | CS8409_I2C_QWRITE, 194 | CS8409_I2C_QREAD, 195 | CS8409_SPI_CTRL, 196 | CS8409_SPI_TX_DATA, 197 | CS8409_SPI_RX_DATA, 198 | CS8409_SPI_STS, 199 | CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 200 | CS8409_PFE_COEF_W2, 201 | CS8409_PFE_CTRL1, 202 | CS8409_PFE_CTRL2, 203 | CS8409_PRE_SCALE_ATTN1, 204 | CS8409_PRE_SCALE_ATTN2, 205 | CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 206 | CS8409_PFE_COEF_MON2, 207 | CS8409_ASP1_INTRN_STS, 208 | CS8409_ASP2_INTRN_STS, 209 | CS8409_ASP1_RX_SCLK_COUNT, 210 | CS8409_ASP1_TX_SCLK_COUNT, 211 | CS8409_ASP2_RX_SCLK_COUNT, 212 | CS8409_ASP2_TX_SCLK_COUNT, 213 | CS8409_ASP_UNS_RESP_MASK, 214 | CS8409_LOOPBACK_CTRL = 0x80, 215 | CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 216 | }; 217 | 218 | /* CS42L42 Specific Definitions */ 219 | 220 | #define CS8409_MAX_CODECS 8 221 | #define CS42L42_VOLUMES (4U) 222 | #define CS42L42_HP_VOL_REAL_MIN (-63) 223 | #define CS42L42_HP_VOL_REAL_MAX (0) 224 | #define CS42L42_AMIC_VOL_REAL_MIN (-97) 225 | #define CS42L42_AMIC_VOL_REAL_MAX (12) 226 | #define CS42L42_REG_AMIC_VOL_MASK (0x00FF) 227 | #define CS42L42_HSTYPE_MASK (0x03) 228 | #define CS42L42_I2C_TIMEOUT_US (20000) 229 | #define CS42L42_I2C_SLEEP_US (2000) 230 | #define CS42L42_PDN_TIMEOUT_US (250000) 231 | #define CS42L42_PDN_SLEEP_US (2000) 232 | #define CS42L42_ANA_MUTE_AB (0x0C) 233 | #define CS42L42_FULL_SCALE_VOL_MASK (2) 234 | #define CS42L42_FULL_SCALE_VOL_0DB (0) 235 | #define CS42L42_FULL_SCALE_VOL_MINUS6DB (1) 236 | 237 | /* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */ 238 | 239 | #define CS42L42_I2C_ADDR (0x48 << 1) 240 | #define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */ 241 | #define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */ 242 | #define CS8409_CYBORG_SPEAKER_PDN GENMASK(2, 2) /* CS8409_GPIO2 */ 243 | #define CS8409_WARLOCK_SPEAKER_PDN GENMASK(1, 1) /* CS8409_GPIO1 */ 244 | #define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A 245 | #define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A 246 | #define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A 247 | #define CS8409_CS42L42_DMIC_PIN_NID CS8409_PIN_DMIC1_IN 248 | #define CS8409_CS42L42_DMIC_ADC_PIN_NID CS8409_PIN_DMIC1 249 | 250 | /* Dolphin */ 251 | 252 | #define DOLPHIN_C0_I2C_ADDR (0x48 << 1) 253 | #define DOLPHIN_C1_I2C_ADDR (0x49 << 1) 254 | #define DOLPHIN_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A 255 | #define DOLPHIN_LO_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_B 256 | #define DOLPHIN_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A 257 | 258 | #define DOLPHIN_C0_INT GENMASK(4, 4) 259 | #define DOLPHIN_C1_INT GENMASK(0, 0) 260 | #define DOLPHIN_C0_RESET GENMASK(5, 5) 261 | #define DOLPHIN_C1_RESET GENMASK(1, 1) 262 | #define DOLPHIN_WAKE (DOLPHIN_C0_INT | DOLPHIN_C1_INT) 263 | 264 | enum { 265 | CS8409_BULLSEYE, 266 | CS8409_WARLOCK, 267 | CS8409_WARLOCK_MLK, 268 | CS8409_WARLOCK_MLK_DUAL_MIC, 269 | CS8409_CYBORG, 270 | CS8409_FIXUPS, 271 | CS8409_DOLPHIN, 272 | CS8409_DOLPHIN_FIXUPS, 273 | CS8409_ODIN, 274 | }; 275 | 276 | enum { 277 | CS8409_CODEC0, 278 | CS8409_CODEC1 279 | }; 280 | 281 | enum { 282 | CS42L42_VOL_ADC, 283 | CS42L42_VOL_DAC, 284 | }; 285 | 286 | #define CS42L42_ADC_VOL_OFFSET (CS42L42_VOL_ADC) 287 | #define CS42L42_DAC_CH0_VOL_OFFSET (CS42L42_VOL_DAC) 288 | #define CS42L42_DAC_CH1_VOL_OFFSET (CS42L42_VOL_DAC + 1) 289 | 290 | struct cs8409_i2c_param { 291 | unsigned int addr; 292 | unsigned int value; 293 | unsigned int delay; 294 | }; 295 | 296 | struct cs8409_cir_param { 297 | unsigned int nid; 298 | unsigned int cir; 299 | unsigned int coeff; 300 | }; 301 | 302 | struct sub_codec { 303 | struct hda_codec *codec; 304 | unsigned int addr; 305 | unsigned int reset_gpio; 306 | unsigned int irq_mask; 307 | const struct cs8409_i2c_param *init_seq; 308 | unsigned int init_seq_num; 309 | 310 | unsigned int hp_jack_in:1; 311 | unsigned int mic_jack_in:1; 312 | unsigned int suspended:1; 313 | unsigned int paged:1; 314 | unsigned int last_page; 315 | unsigned int hsbias_hiz; 316 | unsigned int full_scale_vol:1; 317 | unsigned int no_type_dect:1; 318 | 319 | s8 vol[CS42L42_VOLUMES]; 320 | }; 321 | 322 | struct cs8409_spec { 323 | struct hda_gen_spec gen; 324 | struct hda_codec *codec; 325 | 326 | struct sub_codec *scodecs[CS8409_MAX_CODECS]; 327 | unsigned int num_scodecs; 328 | 329 | unsigned int gpio_mask; 330 | unsigned int gpio_dir; 331 | unsigned int gpio_data; 332 | 333 | int speaker_pdn_gpio; 334 | 335 | struct mutex i2c_mux; 336 | unsigned int i2c_clck_enabled; 337 | unsigned int dev_addr; 338 | struct delayed_work i2c_clk_work; 339 | 340 | unsigned int playback_started:1; 341 | unsigned int capture_started:1; 342 | unsigned int init_done:1; 343 | unsigned int build_ctrl_done:1; 344 | 345 | /* verb exec op override */ 346 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 347 | unsigned int *res); 348 | /* unsol_event op override */ 349 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); 350 | }; 351 | 352 | extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer; 353 | extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer; 354 | 355 | int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo); 356 | int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl); 357 | int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl); 358 | 359 | extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback; 360 | extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture; 361 | extern const struct hda_quirk cs8409_fixup_tbl[]; 362 | extern const struct hda_model_fixup cs8409_models[]; 363 | extern const struct hda_fixup cs8409_fixups[]; 364 | extern const struct hda_verb cs8409_cs42l42_init_verbs[]; 365 | extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[]; 366 | extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[]; 367 | extern struct sub_codec cs8409_cs42l42_codec; 368 | 369 | extern const struct hda_verb dolphin_init_verbs[]; 370 | extern const struct cs8409_cir_param dolphin_hw_cfg[]; 371 | extern struct sub_codec dolphin_cs42l42_0; 372 | extern struct sub_codec dolphin_cs42l42_1; 373 | 374 | void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action); 375 | void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action); 376 | 377 | #endif 378 | -------------------------------------------------------------------------------- /patch_cirrus/patch_cirrus_hda_generic_copy.h: -------------------------------------------------------------------------------- 1 | 2 | /* playback mute control with the software mute bit check */ 3 | static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol, 4 | struct snd_ctl_elem_value *ucontrol) 5 | { 6 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 7 | struct hda_gen_spec *spec = codec->spec; 8 | 9 | if (spec->auto_mute_via_amp) { 10 | hda_nid_t nid = get_amp_nid(kcontrol); 11 | bool enabled = !((spec->mute_bits >> nid) & 1); 12 | ucontrol->value.integer.value[0] &= enabled; 13 | ucontrol->value.integer.value[1] &= enabled; 14 | } 15 | } 16 | 17 | 18 | static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, 19 | struct snd_ctl_elem_value *ucontrol) 20 | { 21 | sync_auto_mute_bits(kcontrol, ucontrol); 22 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 23 | } 24 | 25 | 26 | /* 27 | * Bound mute controls 28 | */ 29 | #define AMP_VAL_IDX_SHIFT 19 30 | #define AMP_VAL_IDX_MASK (0x0f<<19) 31 | 32 | static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, 33 | struct snd_ctl_elem_value *ucontrol) 34 | { 35 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 36 | unsigned long pval; 37 | int err; 38 | 39 | mutex_lock(&codec->control_mutex); 40 | pval = kcontrol->private_value; 41 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ 42 | err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 43 | kcontrol->private_value = pval; 44 | mutex_unlock(&codec->control_mutex); 45 | return err; 46 | } 47 | 48 | static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, 49 | struct snd_ctl_elem_value *ucontrol) 50 | { 51 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 52 | unsigned long pval; 53 | int i, indices, err = 0, change = 0; 54 | 55 | sync_auto_mute_bits(kcontrol, ucontrol); 56 | 57 | mutex_lock(&codec->control_mutex); 58 | pval = kcontrol->private_value; 59 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; 60 | for (i = 0; i < indices; i++) { 61 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | 62 | (i << AMP_VAL_IDX_SHIFT); 63 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 64 | if (err < 0) 65 | break; 66 | change |= err; 67 | } 68 | kcontrol->private_value = pval; 69 | mutex_unlock(&codec->control_mutex); 70 | return err < 0 ? err : change; 71 | } 72 | 73 | 74 | enum { 75 | HDA_CTL_WIDGET_VOL, 76 | HDA_CTL_WIDGET_MUTE, 77 | HDA_CTL_BIND_MUTE, 78 | }; 79 | 80 | 81 | static const struct snd_kcontrol_new control_templates[] = { 82 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), 83 | /* only the put callback is replaced for handling the special mute */ 84 | { 85 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 86 | .subdevice = HDA_SUBDEV_AMP_FLAG, 87 | .info = snd_hda_mixer_amp_switch_info, 88 | .get = snd_hda_mixer_amp_switch_get, 89 | .put = hda_gen_mixer_mute_put, /* replaced */ 90 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), 91 | }, 92 | { 93 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 94 | .info = snd_hda_mixer_amp_switch_info, 95 | .get = hda_gen_bind_mute_get, 96 | .put = hda_gen_bind_mute_put, /* replaced */ 97 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), 98 | }, 99 | }; 100 | 101 | 102 | /* add the powersave loopback-list entry */ 103 | static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx) 104 | { 105 | struct hda_amp_list *list; 106 | 107 | list = snd_array_new(&spec->loopback_list); 108 | if (!list) 109 | return -ENOMEM; 110 | list->nid = mix; 111 | list->dir = HDA_INPUT; 112 | list->idx = idx; 113 | spec->loopback.amplist = spec->loopback_list.list; 114 | return 0; 115 | } 116 | 117 | 118 | static int is_input_pin(struct hda_codec *codec, hda_nid_t nid) 119 | { 120 | unsigned int pincap = snd_hda_query_pin_caps(codec, nid); 121 | return (pincap & AC_PINCAP_IN) != 0; 122 | } 123 | 124 | 125 | 126 | //static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) 127 | //{ 128 | // struct hda_gen_spec *spec = codec->spec; 129 | // struct snd_kcontrol_new *knew; 130 | // char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 131 | // unsigned int defcfg; 132 | // 133 | // if (pin == spec->hp_mic_pin) 134 | // return 0; /* already done in create_out_jack_mode() */ 135 | // 136 | // /* no jack mode for fixed pins */ 137 | // defcfg = snd_hda_codec_get_pincfg(codec, pin); 138 | // if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT) 139 | // return 0; 140 | // 141 | // /* no multiple vref caps? */ 142 | // if (get_in_jack_num_items(codec, pin) <= 1) 143 | // return 0; 144 | // 145 | // get_jack_mode_name(codec, pin, name, sizeof(name)); 146 | // knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum); 147 | // if (!knew) 148 | // return -ENOMEM; 149 | // knew->private_value = pin; 150 | // return 0; 151 | //} 152 | 153 | 154 | static void print_nid_path(struct hda_codec *codec, 155 | const char *pfx, struct nid_path *path) 156 | { 157 | char buf[40]; 158 | char *pos = buf; 159 | int i; 160 | 161 | *pos = 0; 162 | for (i = 0; i < path->depth; i++) 163 | pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x", 164 | pos != buf ? ":" : "", 165 | path->path[i]); 166 | 167 | codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf); 168 | } 169 | 170 | 171 | /* check whether the given two widgets can be connected */ 172 | static bool is_reachable_path(struct hda_codec *codec, 173 | hda_nid_t from_nid, hda_nid_t to_nid) 174 | { 175 | if (!from_nid || !to_nid) 176 | return false; 177 | return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0; 178 | } 179 | 180 | 181 | /* fill the label for each input at first */ 182 | static int fill_input_pin_labels(struct hda_codec *codec) 183 | { 184 | struct hda_gen_spec *spec = codec->spec; 185 | const struct auto_pin_cfg *cfg = &spec->autocfg; 186 | int i; 187 | 188 | for (i = 0; i < cfg->num_inputs; i++) { 189 | hda_nid_t pin = cfg->inputs[i].pin; 190 | const char *label; 191 | int j, idx; 192 | 193 | if (!is_input_pin(codec, pin)) 194 | continue; 195 | 196 | label = hda_get_autocfg_input_label(codec, cfg, i); 197 | idx = 0; 198 | for (j = i - 1; j >= 0; j--) { 199 | if (spec->input_labels[j] && 200 | !strcmp(spec->input_labels[j], label)) { 201 | idx = spec->input_label_idxs[j] + 1; 202 | break; 203 | } 204 | } 205 | 206 | spec->input_labels[i] = label; 207 | spec->input_label_idxs[i] = idx; 208 | } 209 | 210 | return 0; 211 | } 212 | 213 | /* Parse the codec tree and retrieve ADCs */ 214 | static int fill_adc_nids(struct hda_codec *codec) 215 | { 216 | struct hda_gen_spec *spec = codec->spec; 217 | hda_nid_t nid; 218 | hda_nid_t *adc_nids = spec->adc_nids; 219 | int max_nums = ARRAY_SIZE(spec->adc_nids); 220 | int nums = 0; 221 | 222 | for_each_hda_codec_node(nid, codec) { 223 | unsigned int caps = get_wcaps(codec, nid); 224 | int type = get_wcaps_type(caps); 225 | 226 | if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL)) 227 | continue; 228 | adc_nids[nums] = nid; 229 | if (++nums >= max_nums) 230 | break; 231 | } 232 | spec->num_adc_nids = nums; 233 | 234 | codec_dbg(codec, "fill_adc_nids num nids %d\n",nums); 235 | 236 | /* copy the detected ADCs to all_adcs[] */ 237 | spec->num_all_adcs = nums; 238 | memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t)); 239 | 240 | return nums; 241 | } 242 | 243 | 244 | #define update_pin_ctl(codec, pin, val) \ 245 | snd_hda_codec_write_cache(codec, pin, 0, \ 246 | AC_VERB_SET_PIN_WIDGET_CONTROL, val) 247 | 248 | /* set the pinctl target value and write it if requested */ 249 | static void set_pin_target(struct hda_codec *codec, hda_nid_t pin, 250 | unsigned int val, bool do_write) 251 | { 252 | if (!pin) 253 | return; 254 | val = snd_hda_correct_pin_ctl(codec, pin, val); 255 | snd_hda_codec_set_pin_target(codec, pin, val); 256 | if (do_write) 257 | update_pin_ctl(codec, pin, val); 258 | } 259 | 260 | 261 | 262 | /* nid, dir and idx */ 263 | #define AMP_VAL_COMPARE_MASK (0xffff | (1U << 18) | (0x0f << 19)) 264 | 265 | /* check whether the given ctl is already assigned in any path elements */ 266 | static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type) 267 | { 268 | struct hda_gen_spec *spec = codec->spec; 269 | const struct nid_path *path; 270 | int i; 271 | 272 | val &= AMP_VAL_COMPARE_MASK; 273 | snd_array_for_each(&spec->paths, i, path) { 274 | if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val) 275 | return true; 276 | } 277 | return false; 278 | } 279 | 280 | /* check whether a control with the given (nid, dir, idx) was assigned */ 281 | static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid, 282 | int dir, int idx, int type) 283 | { 284 | unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir); 285 | return is_ctl_used(codec, val, type); 286 | } 287 | 288 | 289 | /* return true if either a volume or a mute amp is found for the given 290 | * aamix path; the amp has to be either in the mixer node or its direct leaf 291 | */ 292 | static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid, 293 | hda_nid_t pin, unsigned int *mix_val, 294 | unsigned int *mute_val) 295 | { 296 | int idx, num_conns; 297 | const hda_nid_t *list; 298 | hda_nid_t nid; 299 | 300 | idx = snd_hda_get_conn_index(codec, mix_nid, pin, true); 301 | if (idx < 0) 302 | return false; 303 | 304 | *mix_val = *mute_val = 0; 305 | if (nid_has_volume(codec, mix_nid, HDA_INPUT)) 306 | *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); 307 | if (nid_has_mute(codec, mix_nid, HDA_INPUT)) 308 | *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); 309 | if (*mix_val && *mute_val) 310 | return true; 311 | 312 | /* check leaf node */ 313 | num_conns = snd_hda_get_conn_list(codec, mix_nid, &list); 314 | if (num_conns < idx) 315 | return false; 316 | nid = list[idx]; 317 | if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) && 318 | !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL)) 319 | *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 320 | if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) && 321 | !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL)) 322 | *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 323 | 324 | return *mix_val || *mute_val; 325 | } 326 | 327 | 328 | 329 | 330 | /* add dynamic controls from template */ 331 | static struct snd_kcontrol_new * 332 | add_control(struct hda_gen_spec *spec, int type, const char *name, 333 | int cidx, unsigned long val) 334 | { 335 | struct snd_kcontrol_new *knew; 336 | 337 | knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]); 338 | if (!knew) 339 | return NULL; 340 | knew->index = cidx; 341 | if (get_amp_nid_(val)) 342 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; 343 | knew->private_value = val; 344 | return knew; 345 | } 346 | 347 | 348 | static int add_control_with_pfx(struct hda_gen_spec *spec, int type, 349 | const char *pfx, const char *dir, 350 | const char *sfx, int cidx, unsigned long val) 351 | { 352 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 353 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); 354 | if (!add_control(spec, type, name, cidx, val)) 355 | return -ENOMEM; 356 | return 0; 357 | } 358 | 359 | 360 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ 361 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) 362 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ 363 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) 364 | #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ 365 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) 366 | #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ 367 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) 368 | 369 | 370 | /* create input playback/capture controls for the given pin */ 371 | static int new_analog_input(struct hda_codec *codec, int input_idx, 372 | hda_nid_t pin, const char *ctlname, int ctlidx, 373 | hda_nid_t mix_nid) 374 | { 375 | struct hda_gen_spec *spec = codec->spec; 376 | struct nid_path *path; 377 | unsigned int mix_val, mute_val; 378 | int err, idx; 379 | 380 | if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val)) 381 | return 0; 382 | 383 | path = snd_hda_add_new_path(codec, pin, mix_nid, 0); 384 | if (!path) 385 | return -EINVAL; 386 | print_nid_path(codec, "loopback", path); 387 | spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); 388 | 389 | idx = path->idx[path->depth - 1]; 390 | if (mix_val) { 391 | err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val); 392 | if (err < 0) 393 | return err; 394 | path->ctls[NID_PATH_VOL_CTL] = mix_val; 395 | } 396 | 397 | if (mute_val) { 398 | err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val); 399 | if (err < 0) 400 | return err; 401 | path->ctls[NID_PATH_MUTE_CTL] = mute_val; 402 | } 403 | 404 | path->active = true; 405 | path->stream_enabled = true; /* no DAC/ADC involved */ 406 | err = add_loopback_list(spec, mix_nid, idx); 407 | if (err < 0) 408 | return err; 409 | 410 | if (spec->mixer_nid != spec->mixer_merge_nid && 411 | !spec->loopback_merge_path) { 412 | path = snd_hda_add_new_path(codec, spec->mixer_nid, 413 | spec->mixer_merge_nid, 0); 414 | if (path) { 415 | print_nid_path(codec, "loopback-merge", path); 416 | path->active = true; 417 | path->pin_fixed = true; /* static route */ 418 | path->stream_enabled = true; /* no DAC/ADC involved */ 419 | spec->loopback_merge_path = 420 | snd_hda_get_path_idx(codec, path); 421 | } 422 | } 423 | 424 | return 0; 425 | } 426 | 427 | -------------------------------------------------------------------------------- /patch_cirrus/patch_cs8409.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* 3 | * HD audio interface patch for Cirrus Logic CS8409 HDA bridge chip 4 | * 5 | * Copyright (C) 2021 Cirrus Logic, Inc. and 6 | * Cirrus Logic International Semiconductor Ltd. 7 | */ 8 | 9 | #ifndef __CS8409_PATCH_H 10 | #define __CS8409_PATCH_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "hda_local.h" 18 | #include "hda_auto_parser.h" 19 | #include "hda_jack.h" 20 | #include "hda_generic.h" 21 | 22 | //#ifdef APPLE_CODECS 23 | //#include 24 | //#include 25 | //#include 26 | //#endif 27 | 28 | /* CS8409 Specific Definitions */ 29 | 30 | enum cs8409_pins { 31 | CS8409_PIN_ROOT, // nid 0x00 32 | CS8409_PIN_AFG, // nid 0x01 33 | CS8409_PIN_ASP1_OUT_A, // nid 0x02 34 | CS8409_PIN_ASP1_OUT_B, // nid 0x03 35 | CS8409_PIN_ASP1_OUT_C, // nid 0x04 36 | CS8409_PIN_ASP1_OUT_D, // nid 0x05 37 | CS8409_PIN_ASP1_OUT_E, // nid 0x06 38 | CS8409_PIN_ASP1_OUT_F, // nid 0x07 39 | CS8409_PIN_ASP1_OUT_G, // nid 0x08 40 | CS8409_PIN_ASP1_OUT_H, // nid 0x09 41 | CS8409_PIN_ASP2_OUT_A, // nid 0x0a 42 | CS8409_PIN_ASP2_OUT_B, // nid 0x0b 43 | CS8409_PIN_ASP2_OUT_C, // nid 0x0c 44 | CS8409_PIN_ASP2_OUT_D, // nid 0x0d 45 | CS8409_PIN_ASP2_OUT_E, // nid 0x0e 46 | CS8409_PIN_ASP2_OUT_F, // nid 0x0f 47 | CS8409_PIN_ASP2_OUT_G, // nid 0x10 48 | CS8409_PIN_ASP2_OUT_H, // nid 0x11 49 | CS8409_PIN_ASP1_IN_A, // nid 0x12 50 | CS8409_PIN_ASP1_IN_B, // nid 0x13 51 | CS8409_PIN_ASP1_IN_C, // nid 0x14 52 | CS8409_PIN_ASP1_IN_D, // nid 0x15 53 | CS8409_PIN_ASP1_IN_E, // nid 0x16 54 | CS8409_PIN_ASP1_IN_F, // nid 0x17 55 | CS8409_PIN_ASP1_IN_G, // nid 0x18 56 | CS8409_PIN_ASP1_IN_H, // nid 0x19 57 | CS8409_PIN_ASP2_IN_A, // nid 0x1a 58 | CS8409_PIN_ASP2_IN_B, // nid 0x1b 59 | CS8409_PIN_ASP2_IN_C, // nid 0x1c 60 | CS8409_PIN_ASP2_IN_D, // nid 0x1d 61 | CS8409_PIN_ASP2_IN_E, // nid 0x1e 62 | CS8409_PIN_ASP2_IN_F, // nid 0x1f 63 | CS8409_PIN_ASP2_IN_G, // nid 0x20 64 | CS8409_PIN_ASP2_IN_H, // nid 0x21 65 | CS8409_PIN_DMIC1, // nid 0x22 66 | CS8409_PIN_DMIC2, // nid 0x23 67 | CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 68 | CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 69 | CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 70 | CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 71 | CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 72 | CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 73 | CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 74 | CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 75 | CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 76 | CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 77 | CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 78 | CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 79 | CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 80 | CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 81 | CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 82 | CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 83 | CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 84 | CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 85 | CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 86 | CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 87 | CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 88 | CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 89 | CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 90 | CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 91 | CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 92 | CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 93 | CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 94 | CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 95 | CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 96 | CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 97 | CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 98 | CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 99 | CS8409_PIN_DMIC1_IN, // nid 0x44 100 | CS8409_PIN_DMIC2_IN, // nid 0x45 101 | CS8409_PIN_BEEP_GEN, // nid 0x46 102 | CS8409_PIN_VENDOR_WIDGET // nid 0x47 103 | }; 104 | 105 | enum cs8409_coefficient_index_registers { 106 | CS8409_DEV_CFG1, // reg 0x00 107 | CS8409_DEV_CFG2, // reg 0x01 108 | CS8409_DEV_CFG3, // reg 0x02 109 | CS8409_ASP1_CLK_CTRL1, // reg 0x03 110 | CS8409_ASP1_CLK_CTRL2, // reg 0x04 111 | CS8409_ASP1_CLK_CTRL3, // reg 0x05 112 | CS8409_ASP2_CLK_CTRL1, // reg 0x06 113 | CS8409_ASP2_CLK_CTRL2, // reg 0x07 114 | CS8409_ASP2_CLK_CTRL3, // reg 0x08 115 | CS8409_DMIC_CFG, // reg 0x09 116 | CS8409_BEEP_CFG, // reg 0x0a 117 | ASP1_RX_NULL_INS_RMV, // reg 0x0b 118 | ASP1_Rx_RATE1, // reg 0x0c 119 | ASP1_Rx_RATE2, // reg 0x0d 120 | ASP1_Tx_NULL_INS_RMV, // reg 0x0e 121 | ASP1_Tx_RATE1, // reg 0x0f 122 | ASP1_Tx_RATE2, // reg 0x10 123 | ASP2_Rx_NULL_INS_RMV, // reg 0x11 124 | ASP2_Rx_RATE1, // reg 0x12 125 | ASP2_Rx_RATE2, // reg 0x13 126 | ASP2_Tx_NULL_INS_RMV, // reg 0x14 127 | ASP2_Tx_RATE1, // reg 0x15 128 | ASP2_Tx_RATE2, // reg 0x16 129 | ASP1_SYNC_CTRL, // reg 0x17 130 | ASP2_SYNC_CTRL, // reg 0x18 131 | ASP1_A_TX_CTRL1, // reg 0x19 132 | ASP1_A_TX_CTRL2, // reg 0x1a 133 | ASP1_B_TX_CTRL1, // reg 0x1b 134 | ASP1_B_TX_CTRL2, // reg 0x1c 135 | ASP1_C_TX_CTRL1, // reg 0x1d 136 | ASP1_C_TX_CTRL2, // reg 0x1e 137 | ASP1_D_TX_CTRL1, // reg 0x1f 138 | ASP1_D_TX_CTRL2, // reg 0x20 139 | ASP1_E_TX_CTRL1, // reg 0x21 140 | ASP1_E_TX_CTRL2, // reg 0x22 141 | ASP1_F_TX_CTRL1, // reg 0x23 142 | ASP1_F_TX_CTRL2, // reg 0x24 143 | ASP1_G_TX_CTRL1, // reg 0x25 144 | ASP1_G_TX_CTRL2, // reg 0x26 145 | ASP1_H_TX_CTRL1, // reg 0x27 146 | ASP1_H_TX_CTRL2, // reg 0x28 147 | ASP2_A_TX_CTRL1, // reg 0x29 148 | ASP2_A_TX_CTRL2, // reg 0x2a 149 | ASP2_B_TX_CTRL1, // reg 0x2b 150 | ASP2_B_TX_CTRL2, // reg 0x2c 151 | ASP2_C_TX_CTRL1, // reg 0x2d 152 | ASP2_C_TX_CTRL2, // reg 0x2e 153 | ASP2_D_TX_CTRL1, // reg 0x2f 154 | ASP2_D_TX_CTRL2, // reg 0x30 155 | ASP2_E_TX_CTRL1, // reg 0x31 156 | ASP2_E_TX_CTRL2, // reg 0x32 157 | ASP2_F_TX_CTRL1, // reg 0x33 158 | ASP2_F_TX_CTRL2, // reg 0x34 159 | ASP2_G_TX_CTRL1, // reg 0x35 160 | ASP2_G_TX_CTRL2, // reg 0x36 161 | ASP2_H_TX_CTRL1, // reg 0x37 162 | ASP2_H_TX_CTRL2, // reg 0x38 163 | ASP1_A_RX_CTRL1, // reg 0x39 164 | ASP1_A_RX_CTRL2, // reg 0x3a 165 | ASP1_B_RX_CTRL1, // reg 0x3b 166 | ASP1_B_RX_CTRL2, // reg 0x3c 167 | ASP1_C_RX_CTRL1, // reg 0x3d 168 | ASP1_C_RX_CTRL2, // reg 0x3e 169 | ASP1_D_RX_CTRL1, // reg 0x3f 170 | ASP1_D_RX_CTRL2, // reg 0x40 171 | ASP1_E_RX_CTRL1, // reg 0x41 172 | ASP1_E_RX_CTRL2, // reg 0x42 173 | ASP1_F_RX_CTRL1, // reg 0x43 174 | ASP1_F_RX_CTRL2, // reg 0x44 175 | ASP1_G_RX_CTRL1, // reg 0x45 176 | ASP1_G_RX_CTRL2, // reg 0x46 177 | ASP1_H_RX_CTRL1, // reg 0x47 178 | ASP1_H_RX_CTRL2, // reg 0x48 179 | ASP2_A_RX_CTRL1, // reg 0x49 180 | ASP2_A_RX_CTRL2, // reg 0x4a 181 | ASP2_B_RX_CTRL1, // reg 0x4b 182 | ASP2_B_RX_CTRL2, // reg 0x4c 183 | ASP2_C_RX_CTRL1, // reg 0x4d 184 | ASP2_C_RX_CTRL2, // reg 0x4e 185 | ASP2_D_RX_CTRL1, // reg 0x4f 186 | ASP2_D_RX_CTRL2, // reg 0x50 187 | ASP2_E_RX_CTRL1, // reg 0x51 188 | ASP2_E_RX_CTRL2, // reg 0x52 189 | ASP2_F_RX_CTRL1, // reg 0x53 190 | ASP2_F_RX_CTRL2, // reg 0x54 191 | ASP2_G_RX_CTRL1, // reg 0x55 192 | ASP2_G_RX_CTRL2, // reg 0x56 193 | ASP2_H_RX_CTRL1, // reg 0x57 194 | ASP2_H_RX_CTRL2, // reg 0x58 195 | CS8409_I2C_ADDR, // reg 0x59 196 | CS8409_I2C_DATA, // reg 0x5a 197 | CS8409_I2C_CTRL, // reg 0x5b 198 | CS8409_I2C_STS, // reg 0x5c 199 | CS8409_I2C_QWRITE, // reg 0x5d 200 | CS8409_I2C_QREAD, // reg 0x5e 201 | CS8409_SPI_CTRL, // reg 0x5f 202 | CS8409_SPI_TX_DATA, // reg 0x60 203 | CS8409_SPI_RX_DATA, // reg 0x61 204 | CS8409_SPI_STS, // reg 0x62 205 | CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 206 | CS8409_PFE_COEF_W2, // reg 0x64 207 | CS8409_PFE_CTRL1, // reg 0x65 208 | CS8409_PFE_CTRL2, // reg 0x66 209 | CS8409_PRE_SCALE_ATTN1, // reg 0x67 210 | CS8409_PRE_SCALE_ATTN2, // reg 0x68 211 | CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 212 | CS8409_PFE_COEF_MON2, // reg 0x6a 213 | CS8409_ASP1_INTRN_STS, // reg 0x6b 214 | CS8409_ASP2_INTRN_STS, // reg 0x6c 215 | CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 216 | CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 217 | CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 218 | CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 219 | CS8409_ASP_UNS_RESP_MASK, // reg 0x71 220 | CS8409_LOOPBACK_CTRL = 0x80, 221 | CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 222 | }; 223 | 224 | /* CS42L42 Specific Definitions */ 225 | 226 | #define CS8409_MAX_CODECS 8 227 | #define CS42L42_VOLUMES (4U) 228 | #define CS42L42_HP_VOL_REAL_MIN (-63) 229 | #define CS42L42_HP_VOL_REAL_MAX (0) 230 | #define CS42L42_AMIC_VOL_REAL_MIN (-97) 231 | #define CS42L42_AMIC_VOL_REAL_MAX (12) 232 | #define CS42L42_REG_AMIC_VOL_MASK (0x00FF) 233 | #define CS42L42_HSTYPE_MASK (0x03) 234 | #define CS42L42_I2C_TIMEOUT_US (20000) 235 | #define CS42L42_I2C_SLEEP_US (2000) 236 | #define CS42L42_PDN_TIMEOUT_US (250000) 237 | #define CS42L42_PDN_SLEEP_US (2000) 238 | #define CS42L42_FULL_SCALE_VOL_MASK (2) 239 | #define CS42L42_FULL_SCALE_VOL_0DB (1) 240 | #define CS42L42_FULL_SCALE_VOL_MINUS6DB (0) 241 | 242 | /* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */ 243 | 244 | #define CS42L42_I2C_ADDR (0x48 << 1) 245 | #define CS8409_CS42L42_RESET GENMASK(5, 5) /* CS8409_GPIO5 */ 246 | #define CS8409_CS42L42_INT GENMASK(4, 4) /* CS8409_GPIO4 */ 247 | #define CS8409_CYBORG_SPEAKER_PDN GENMASK(2, 2) /* CS8409_GPIO2 */ 248 | #define CS8409_CS42L42_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A 249 | #define CS8409_CS42L42_SPK_PIN_NID CS8409_PIN_ASP2_TRANSMITTER_A 250 | #define CS8409_CS42L42_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A 251 | #define CS8409_CS42L42_DMIC_PIN_NID CS8409_PIN_DMIC1_IN 252 | #define CS8409_CS42L42_DMIC_ADC_PIN_NID CS8409_PIN_DMIC1 253 | 254 | /* Dolphin */ 255 | 256 | #define DOLPHIN_C0_I2C_ADDR (0x48 << 1) 257 | #define DOLPHIN_C1_I2C_ADDR (0x49 << 1) 258 | #define DOLPHIN_HP_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_A 259 | #define DOLPHIN_LO_PIN_NID CS8409_PIN_ASP1_TRANSMITTER_B 260 | #define DOLPHIN_AMIC_PIN_NID CS8409_PIN_ASP1_RECEIVER_A 261 | 262 | #define DOLPHIN_C0_INT GENMASK(4, 4) 263 | #define DOLPHIN_C1_INT GENMASK(0, 0) 264 | #define DOLPHIN_C0_RESET GENMASK(5, 5) 265 | #define DOLPHIN_C1_RESET GENMASK(1, 1) 266 | #define DOLPHIN_WAKE (DOLPHIN_C0_INT | DOLPHIN_C1_INT) 267 | 268 | enum { 269 | CS8409_BULLSEYE, 270 | CS8409_WARLOCK, 271 | CS8409_WARLOCK_MLK, 272 | CS8409_WARLOCK_MLK_DUAL_MIC, 273 | CS8409_CYBORG, 274 | CS8409_FIXUPS, 275 | CS8409_DOLPHIN, 276 | CS8409_DOLPHIN_FIXUPS, 277 | CS8409_ODIN, 278 | }; 279 | 280 | enum { 281 | CS8409_CODEC0, 282 | CS8409_CODEC1 283 | }; 284 | 285 | enum { 286 | CS42L42_VOL_ADC, 287 | CS42L42_VOL_DAC, 288 | }; 289 | 290 | #define CS42L42_ADC_VOL_OFFSET (CS42L42_VOL_ADC) 291 | #define CS42L42_DAC_CH0_VOL_OFFSET (CS42L42_VOL_DAC) 292 | #define CS42L42_DAC_CH1_VOL_OFFSET (CS42L42_VOL_DAC + 1) 293 | 294 | struct cs8409_i2c_param { 295 | unsigned int addr; 296 | unsigned int value; 297 | }; 298 | 299 | struct cs8409_cir_param { 300 | unsigned int nid; 301 | unsigned int cir; 302 | unsigned int coeff; 303 | }; 304 | 305 | 306 | #ifdef APPLE_CODECS 307 | struct unsol_item { 308 | struct list_head list; 309 | unsigned int idx; 310 | unsigned int res; 311 | }; 312 | struct hda_cvt_setup_apple { 313 | hda_nid_t nid; 314 | u8 stream_tag; 315 | u8 channel_id; 316 | u16 format_id; 317 | unsigned char active; /* cvt is currently used */ 318 | unsigned char dirty; /* setups should be cleared */ 319 | }; 320 | #endif 321 | 322 | struct sub_codec { 323 | struct hda_codec *codec; 324 | unsigned int addr; 325 | unsigned int reset_gpio; 326 | unsigned int irq_mask; 327 | const struct cs8409_i2c_param *init_seq; 328 | unsigned int init_seq_num; 329 | 330 | unsigned int hp_jack_in:1; 331 | unsigned int mic_jack_in:1; 332 | #ifdef APPLE_CODECS 333 | unsigned int linein_jack_in:1; 334 | #endif 335 | unsigned int suspended:1; 336 | unsigned int paged:1; 337 | unsigned int last_page; 338 | unsigned int hsbias_hiz; 339 | unsigned int full_scale_vol:1; 340 | unsigned int no_type_dect:1; 341 | 342 | s8 vol[CS42L42_VOLUMES]; 343 | }; 344 | 345 | struct cs8409_spec { 346 | struct hda_gen_spec gen; 347 | struct hda_codec *codec; 348 | 349 | struct sub_codec *scodecs[CS8409_MAX_CODECS]; 350 | unsigned int num_scodecs; 351 | 352 | unsigned int gpio_mask; 353 | unsigned int gpio_dir; 354 | unsigned int gpio_data; 355 | 356 | int speaker_pdn_gpio; 357 | 358 | struct mutex i2c_mux; 359 | unsigned int i2c_clck_enabled; 360 | unsigned int dev_addr; 361 | struct delayed_work i2c_clk_work; 362 | 363 | unsigned int playback_started:1; 364 | unsigned int capture_started:1; 365 | unsigned int init_done:1; 366 | unsigned int build_ctrl_done:1; 367 | 368 | #ifdef APPLE_CODECS 369 | 370 | // additional data for Apple 8409 system 371 | 372 | unsigned int spdif_detect:1; 373 | unsigned int spdif_present:1; 374 | unsigned int sense_b:1; 375 | hda_nid_t vendor_nid; 376 | 377 | /* digital beep */ 378 | hda_nid_t beep_nid; 379 | 380 | /* for MBP SPDIF control */ 381 | int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 382 | struct snd_ctl_elem_value *ucontrol); 383 | 384 | // so it appears we have "concurrency" in the linux HDA code 385 | // in that if unsolicited responses occur which perform extensive verbs 386 | // the hda verbs are intermixed with eg extensive start playback verbs 387 | // on OSX we appear to have blocks of verbs during which unsolicited responses 388 | // are logged but the unsolicited verbs occur after the verb block 389 | // this flag is used to flag such verb blocks and the list will store the 390 | // responses 391 | // we use a pre-allocated list - if we have more than 10 outstanding unsols 392 | // we will drop 393 | // not clear if mutexes would be the way to go 394 | int block_unsol; 395 | struct list_head unsol_list; 396 | struct unsol_item unsol_items_prealloc[10]; 397 | int unsol_items_prealloc_used[10]; 398 | 399 | // add in specific nids for the intmike and linein as they seem to swap 400 | // between macbook pros (14,3) and imacs (18,3) 401 | int intmike_nid; 402 | int linein_nid; 403 | int intmike_adc_nid; 404 | int linein_amp_nid; 405 | 406 | // the following flag bits also need swapping 407 | int reg9_intmike_dmic_mo; 408 | int reg9_linein_dmic_mo; 409 | int reg82_intmike_dmic_scl; 410 | int reg82_linein_dmic_scl; 411 | 412 | 413 | // add explicit stream format store entries as per hda_codec using a local definition 414 | // of hda_cvt_setup (which is local to hda_codec.c) 415 | // also use explicit nid versions 416 | // (except that means either need explicit functions for each nid or have to lookup 417 | // nid each time want to use in a generic function with nid argument) 418 | struct hda_cvt_setup_apple nid_0x02; 419 | struct hda_cvt_setup_apple nid_0x03; 420 | struct hda_cvt_setup_apple nid_0x0a; 421 | struct hda_cvt_setup_apple nid_0x22; 422 | struct hda_cvt_setup_apple nid_0x23; 423 | struct hda_cvt_setup_apple nid_0x1a; 424 | 425 | 426 | // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 427 | // the HDA spec by using a separate headphone chip 428 | int jack_present; 429 | 430 | // save the type of headphone connected 431 | int headset_type; 432 | 433 | // if headphone has mike or not 434 | int have_mike; 435 | 436 | // if headphone has buttons or not 437 | int have_buttons; 438 | 439 | // current stream channel count 440 | int stream_channels; 441 | 442 | // set when playing for plug/unplug events while playing 443 | int playing; 444 | 445 | // set when capturing for plug/unplug events while capturing 446 | int capturing; 447 | 448 | // changing coding - OSX sets up the format on plugin 449 | // then does some minimal setup when start play 450 | // initial coding delayed any format setup till actually play 451 | // this works for no mike but not for mike - we need to initialize 452 | // the mike on plugin 453 | // this flag will be set when we have done the format setup 454 | // so know if need to do it on play or not 455 | // now need 2 flags - one for play and one for capture 456 | int headset_play_format_setup_needed; 457 | int headset_capture_format_setup_needed; 458 | 459 | int headset_presetup_done; 460 | 461 | 462 | int use_data; 463 | 464 | 465 | // this is new item for dealing with headset plugins 466 | // so can distinguish which phase we are in if have multiple interrupts 467 | // not really used now have analyzed interrupts properly 468 | int headset_phase; 469 | 470 | // another dirty hack item to manage the different headset enable codes 471 | int headset_enable; 472 | 473 | int play_init; 474 | int capture_init; 475 | 476 | int play_init_count; 477 | int capture_init_count; 478 | 479 | 480 | // new item to limit times we redo unmute/play 481 | struct timespec64 last_play_time; 482 | // record the first play time - we have a problem there 483 | // some initial plays that I dont understand - so skip any setup 484 | // till sometime after the first play 485 | struct timespec64 first_play_time; 486 | 487 | 488 | #endif 489 | 490 | 491 | /* verb exec op override */ 492 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 493 | unsigned int *res); 494 | }; 495 | 496 | extern const struct snd_kcontrol_new cs42l42_dac_volume_mixer; 497 | extern const struct snd_kcontrol_new cs42l42_adc_volume_mixer; 498 | 499 | int cs42l42_volume_info(struct snd_kcontrol *kctrl, struct snd_ctl_elem_info *uinfo); 500 | int cs42l42_volume_get(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl); 501 | int cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_value *uctrl); 502 | 503 | extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_playback; 504 | extern const struct hda_pcm_stream cs42l42_48k_pcm_analog_capture; 505 | extern const struct snd_pci_quirk cs8409_fixup_tbl[]; 506 | extern const struct hda_model_fixup cs8409_models[]; 507 | extern const struct hda_fixup cs8409_fixups[]; 508 | extern const struct hda_verb cs8409_cs42l42_init_verbs[]; 509 | extern const struct hda_pintbl cs8409_cs42l42_pincfgs[]; 510 | extern const struct cs8409_cir_param cs8409_cs42l42_hw_cfg[]; 511 | extern const struct cs8409_cir_param cs8409_cs42l42_bullseye_atn[]; 512 | extern struct sub_codec cs8409_cs42l42_codec; 513 | 514 | extern const struct hda_verb dolphin_init_verbs[]; 515 | extern const struct hda_pintbl dolphin_pincfgs[]; 516 | extern const struct cs8409_cir_param dolphin_hw_cfg[]; 517 | extern struct sub_codec dolphin_cs42l42_0; 518 | extern struct sub_codec dolphin_cs42l42_1; 519 | 520 | void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action); 521 | void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int action); 522 | 523 | #endif 524 | -------------------------------------------------------------------------------- /patches/patch_patch_cs8409.h.main.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.h b/patch_cirrus/patch_cs8409.h 2 | index d0b725c..d8b5232 100644 3 | --- a/kernel_sources/patch_cs8409.h 4 | +++ b/patch_cirrus/patch_cs8409.h 5 | @@ -19,200 +19,206 @@ 6 | #include "hda_jack.h" 7 | #include "hda_generic.h" 8 | 9 | +//#ifdef APPLE_CODECS 10 | +//#include 11 | +//#include 12 | +//#include 13 | +//#endif 14 | + 15 | /* CS8409 Specific Definitions */ 16 | 17 | enum cs8409_pins { 18 | - CS8409_PIN_ROOT, 19 | - CS8409_PIN_AFG, 20 | - CS8409_PIN_ASP1_OUT_A, 21 | - CS8409_PIN_ASP1_OUT_B, 22 | - CS8409_PIN_ASP1_OUT_C, 23 | - CS8409_PIN_ASP1_OUT_D, 24 | - CS8409_PIN_ASP1_OUT_E, 25 | - CS8409_PIN_ASP1_OUT_F, 26 | - CS8409_PIN_ASP1_OUT_G, 27 | - CS8409_PIN_ASP1_OUT_H, 28 | - CS8409_PIN_ASP2_OUT_A, 29 | - CS8409_PIN_ASP2_OUT_B, 30 | - CS8409_PIN_ASP2_OUT_C, 31 | - CS8409_PIN_ASP2_OUT_D, 32 | - CS8409_PIN_ASP2_OUT_E, 33 | - CS8409_PIN_ASP2_OUT_F, 34 | - CS8409_PIN_ASP2_OUT_G, 35 | - CS8409_PIN_ASP2_OUT_H, 36 | - CS8409_PIN_ASP1_IN_A, 37 | - CS8409_PIN_ASP1_IN_B, 38 | - CS8409_PIN_ASP1_IN_C, 39 | - CS8409_PIN_ASP1_IN_D, 40 | - CS8409_PIN_ASP1_IN_E, 41 | - CS8409_PIN_ASP1_IN_F, 42 | - CS8409_PIN_ASP1_IN_G, 43 | - CS8409_PIN_ASP1_IN_H, 44 | - CS8409_PIN_ASP2_IN_A, 45 | - CS8409_PIN_ASP2_IN_B, 46 | - CS8409_PIN_ASP2_IN_C, 47 | - CS8409_PIN_ASP2_IN_D, 48 | - CS8409_PIN_ASP2_IN_E, 49 | - CS8409_PIN_ASP2_IN_F, 50 | - CS8409_PIN_ASP2_IN_G, 51 | - CS8409_PIN_ASP2_IN_H, 52 | - CS8409_PIN_DMIC1, 53 | - CS8409_PIN_DMIC2, 54 | - CS8409_PIN_ASP1_TRANSMITTER_A, 55 | - CS8409_PIN_ASP1_TRANSMITTER_B, 56 | - CS8409_PIN_ASP1_TRANSMITTER_C, 57 | - CS8409_PIN_ASP1_TRANSMITTER_D, 58 | - CS8409_PIN_ASP1_TRANSMITTER_E, 59 | - CS8409_PIN_ASP1_TRANSMITTER_F, 60 | - CS8409_PIN_ASP1_TRANSMITTER_G, 61 | - CS8409_PIN_ASP1_TRANSMITTER_H, 62 | - CS8409_PIN_ASP2_TRANSMITTER_A, 63 | - CS8409_PIN_ASP2_TRANSMITTER_B, 64 | - CS8409_PIN_ASP2_TRANSMITTER_C, 65 | - CS8409_PIN_ASP2_TRANSMITTER_D, 66 | - CS8409_PIN_ASP2_TRANSMITTER_E, 67 | - CS8409_PIN_ASP2_TRANSMITTER_F, 68 | - CS8409_PIN_ASP2_TRANSMITTER_G, 69 | - CS8409_PIN_ASP2_TRANSMITTER_H, 70 | - CS8409_PIN_ASP1_RECEIVER_A, 71 | - CS8409_PIN_ASP1_RECEIVER_B, 72 | - CS8409_PIN_ASP1_RECEIVER_C, 73 | - CS8409_PIN_ASP1_RECEIVER_D, 74 | - CS8409_PIN_ASP1_RECEIVER_E, 75 | - CS8409_PIN_ASP1_RECEIVER_F, 76 | - CS8409_PIN_ASP1_RECEIVER_G, 77 | - CS8409_PIN_ASP1_RECEIVER_H, 78 | - CS8409_PIN_ASP2_RECEIVER_A, 79 | - CS8409_PIN_ASP2_RECEIVER_B, 80 | - CS8409_PIN_ASP2_RECEIVER_C, 81 | - CS8409_PIN_ASP2_RECEIVER_D, 82 | - CS8409_PIN_ASP2_RECEIVER_E, 83 | - CS8409_PIN_ASP2_RECEIVER_F, 84 | - CS8409_PIN_ASP2_RECEIVER_G, 85 | - CS8409_PIN_ASP2_RECEIVER_H, 86 | - CS8409_PIN_DMIC1_IN, 87 | - CS8409_PIN_DMIC2_IN, 88 | - CS8409_PIN_BEEP_GEN, 89 | - CS8409_PIN_VENDOR_WIDGET 90 | + CS8409_PIN_ROOT, // nid 0x00 91 | + CS8409_PIN_AFG, // nid 0x01 92 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 93 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 94 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 95 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_E, // nid 0x06 97 | + CS8409_PIN_ASP1_OUT_F, // nid 0x07 98 | + CS8409_PIN_ASP1_OUT_G, // nid 0x08 99 | + CS8409_PIN_ASP1_OUT_H, // nid 0x09 100 | + CS8409_PIN_ASP2_OUT_A, // nid 0x0a 101 | + CS8409_PIN_ASP2_OUT_B, // nid 0x0b 102 | + CS8409_PIN_ASP2_OUT_C, // nid 0x0c 103 | + CS8409_PIN_ASP2_OUT_D, // nid 0x0d 104 | + CS8409_PIN_ASP2_OUT_E, // nid 0x0e 105 | + CS8409_PIN_ASP2_OUT_F, // nid 0x0f 106 | + CS8409_PIN_ASP2_OUT_G, // nid 0x10 107 | + CS8409_PIN_ASP2_OUT_H, // nid 0x11 108 | + CS8409_PIN_ASP1_IN_A, // nid 0x12 109 | + CS8409_PIN_ASP1_IN_B, // nid 0x13 110 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 111 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_E, // nid 0x16 113 | + CS8409_PIN_ASP1_IN_F, // nid 0x17 114 | + CS8409_PIN_ASP1_IN_G, // nid 0x18 115 | + CS8409_PIN_ASP1_IN_H, // nid 0x19 116 | + CS8409_PIN_ASP2_IN_A, // nid 0x1a 117 | + CS8409_PIN_ASP2_IN_B, // nid 0x1b 118 | + CS8409_PIN_ASP2_IN_C, // nid 0x1c 119 | + CS8409_PIN_ASP2_IN_D, // nid 0x1d 120 | + CS8409_PIN_ASP2_IN_E, // nid 0x1e 121 | + CS8409_PIN_ASP2_IN_F, // nid 0x1f 122 | + CS8409_PIN_ASP2_IN_G, // nid 0x20 123 | + CS8409_PIN_ASP2_IN_H, // nid 0x21 124 | + CS8409_PIN_DMIC1, // nid 0x22 125 | + CS8409_PIN_DMIC2, // nid 0x23 126 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 127 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 129 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 130 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 131 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 132 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 133 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 134 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 135 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 136 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 137 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 138 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 139 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 140 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 141 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 142 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 144 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 145 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 146 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 147 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 148 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 149 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 150 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 151 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 152 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 153 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 154 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 155 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 156 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 157 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 158 | + CS8409_PIN_DMIC1_IN, // nid 0x44 159 | + CS8409_PIN_DMIC2_IN, // nid 0x45 160 | + CS8409_PIN_BEEP_GEN, // nid 0x46 161 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 162 | }; 163 | 164 | enum cs8409_coefficient_index_registers { 165 | - CS8409_DEV_CFG1, 166 | - CS8409_DEV_CFG2, 167 | - CS8409_DEV_CFG3, 168 | - CS8409_ASP1_CLK_CTRL1, 169 | - CS8409_ASP1_CLK_CTRL2, 170 | - CS8409_ASP1_CLK_CTRL3, 171 | - CS8409_ASP2_CLK_CTRL1, 172 | - CS8409_ASP2_CLK_CTRL2, 173 | - CS8409_ASP2_CLK_CTRL3, 174 | - CS8409_DMIC_CFG, 175 | - CS8409_BEEP_CFG, 176 | - ASP1_RX_NULL_INS_RMV, 177 | - ASP1_Rx_RATE1, 178 | - ASP1_Rx_RATE2, 179 | - ASP1_Tx_NULL_INS_RMV, 180 | - ASP1_Tx_RATE1, 181 | - ASP1_Tx_RATE2, 182 | - ASP2_Rx_NULL_INS_RMV, 183 | - ASP2_Rx_RATE1, 184 | - ASP2_Rx_RATE2, 185 | - ASP2_Tx_NULL_INS_RMV, 186 | - ASP2_Tx_RATE1, 187 | - ASP2_Tx_RATE2, 188 | - ASP1_SYNC_CTRL, 189 | - ASP2_SYNC_CTRL, 190 | - ASP1_A_TX_CTRL1, 191 | - ASP1_A_TX_CTRL2, 192 | - ASP1_B_TX_CTRL1, 193 | - ASP1_B_TX_CTRL2, 194 | - ASP1_C_TX_CTRL1, 195 | - ASP1_C_TX_CTRL2, 196 | - ASP1_D_TX_CTRL1, 197 | - ASP1_D_TX_CTRL2, 198 | - ASP1_E_TX_CTRL1, 199 | - ASP1_E_TX_CTRL2, 200 | - ASP1_F_TX_CTRL1, 201 | - ASP1_F_TX_CTRL2, 202 | - ASP1_G_TX_CTRL1, 203 | - ASP1_G_TX_CTRL2, 204 | - ASP1_H_TX_CTRL1, 205 | - ASP1_H_TX_CTRL2, 206 | - ASP2_A_TX_CTRL1, 207 | - ASP2_A_TX_CTRL2, 208 | - ASP2_B_TX_CTRL1, 209 | - ASP2_B_TX_CTRL2, 210 | - ASP2_C_TX_CTRL1, 211 | - ASP2_C_TX_CTRL2, 212 | - ASP2_D_TX_CTRL1, 213 | - ASP2_D_TX_CTRL2, 214 | - ASP2_E_TX_CTRL1, 215 | - ASP2_E_TX_CTRL2, 216 | - ASP2_F_TX_CTRL1, 217 | - ASP2_F_TX_CTRL2, 218 | - ASP2_G_TX_CTRL1, 219 | - ASP2_G_TX_CTRL2, 220 | - ASP2_H_TX_CTRL1, 221 | - ASP2_H_TX_CTRL2, 222 | - ASP1_A_RX_CTRL1, 223 | - ASP1_A_RX_CTRL2, 224 | - ASP1_B_RX_CTRL1, 225 | - ASP1_B_RX_CTRL2, 226 | - ASP1_C_RX_CTRL1, 227 | - ASP1_C_RX_CTRL2, 228 | - ASP1_D_RX_CTRL1, 229 | - ASP1_D_RX_CTRL2, 230 | - ASP1_E_RX_CTRL1, 231 | - ASP1_E_RX_CTRL2, 232 | - ASP1_F_RX_CTRL1, 233 | - ASP1_F_RX_CTRL2, 234 | - ASP1_G_RX_CTRL1, 235 | - ASP1_G_RX_CTRL2, 236 | - ASP1_H_RX_CTRL1, 237 | - ASP1_H_RX_CTRL2, 238 | - ASP2_A_RX_CTRL1, 239 | - ASP2_A_RX_CTRL2, 240 | - ASP2_B_RX_CTRL1, 241 | - ASP2_B_RX_CTRL2, 242 | - ASP2_C_RX_CTRL1, 243 | - ASP2_C_RX_CTRL2, 244 | - ASP2_D_RX_CTRL1, 245 | - ASP2_D_RX_CTRL2, 246 | - ASP2_E_RX_CTRL1, 247 | - ASP2_E_RX_CTRL2, 248 | - ASP2_F_RX_CTRL1, 249 | - ASP2_F_RX_CTRL2, 250 | - ASP2_G_RX_CTRL1, 251 | - ASP2_G_RX_CTRL2, 252 | - ASP2_H_RX_CTRL1, 253 | - ASP2_H_RX_CTRL2, 254 | - CS8409_I2C_ADDR, 255 | - CS8409_I2C_DATA, 256 | - CS8409_I2C_CTRL, 257 | - CS8409_I2C_STS, 258 | - CS8409_I2C_QWRITE, 259 | - CS8409_I2C_QREAD, 260 | - CS8409_SPI_CTRL, 261 | - CS8409_SPI_TX_DATA, 262 | - CS8409_SPI_RX_DATA, 263 | - CS8409_SPI_STS, 264 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 265 | - CS8409_PFE_COEF_W2, 266 | - CS8409_PFE_CTRL1, 267 | - CS8409_PFE_CTRL2, 268 | - CS8409_PRE_SCALE_ATTN1, 269 | - CS8409_PRE_SCALE_ATTN2, 270 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 271 | - CS8409_PFE_COEF_MON2, 272 | - CS8409_ASP1_INTRN_STS, 273 | - CS8409_ASP2_INTRN_STS, 274 | - CS8409_ASP1_RX_SCLK_COUNT, 275 | - CS8409_ASP1_TX_SCLK_COUNT, 276 | - CS8409_ASP2_RX_SCLK_COUNT, 277 | - CS8409_ASP2_TX_SCLK_COUNT, 278 | - CS8409_ASP_UNS_RESP_MASK, 279 | + CS8409_DEV_CFG1, // reg 0x00 280 | + CS8409_DEV_CFG2, // reg 0x01 281 | + CS8409_DEV_CFG3, // reg 0x02 282 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 283 | + CS8409_ASP1_CLK_CTRL2, // reg 0x04 284 | + CS8409_ASP1_CLK_CTRL3, // reg 0x05 285 | + CS8409_ASP2_CLK_CTRL1, // reg 0x06 286 | + CS8409_ASP2_CLK_CTRL2, // reg 0x07 287 | + CS8409_ASP2_CLK_CTRL3, // reg 0x08 288 | + CS8409_DMIC_CFG, // reg 0x09 289 | + CS8409_BEEP_CFG, // reg 0x0a 290 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 291 | + ASP1_Rx_RATE1, // reg 0x0c 292 | + ASP1_Rx_RATE2, // reg 0x0d 293 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 294 | + ASP1_Tx_RATE1, // reg 0x0f 295 | + ASP1_Tx_RATE2, // reg 0x10 296 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 297 | + ASP2_Rx_RATE1, // reg 0x12 298 | + ASP2_Rx_RATE2, // reg 0x13 299 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 300 | + ASP2_Tx_RATE1, // reg 0x15 301 | + ASP2_Tx_RATE2, // reg 0x16 302 | + ASP1_SYNC_CTRL, // reg 0x17 303 | + ASP2_SYNC_CTRL, // reg 0x18 304 | + ASP1_A_TX_CTRL1, // reg 0x19 305 | + ASP1_A_TX_CTRL2, // reg 0x1a 306 | + ASP1_B_TX_CTRL1, // reg 0x1b 307 | + ASP1_B_TX_CTRL2, // reg 0x1c 308 | + ASP1_C_TX_CTRL1, // reg 0x1d 309 | + ASP1_C_TX_CTRL2, // reg 0x1e 310 | + ASP1_D_TX_CTRL1, // reg 0x1f 311 | + ASP1_D_TX_CTRL2, // reg 0x20 312 | + ASP1_E_TX_CTRL1, // reg 0x21 313 | + ASP1_E_TX_CTRL2, // reg 0x22 314 | + ASP1_F_TX_CTRL1, // reg 0x23 315 | + ASP1_F_TX_CTRL2, // reg 0x24 316 | + ASP1_G_TX_CTRL1, // reg 0x25 317 | + ASP1_G_TX_CTRL2, // reg 0x26 318 | + ASP1_H_TX_CTRL1, // reg 0x27 319 | + ASP1_H_TX_CTRL2, // reg 0x28 320 | + ASP2_A_TX_CTRL1, // reg 0x29 321 | + ASP2_A_TX_CTRL2, // reg 0x2a 322 | + ASP2_B_TX_CTRL1, // reg 0x2b 323 | + ASP2_B_TX_CTRL2, // reg 0x2c 324 | + ASP2_C_TX_CTRL1, // reg 0x2d 325 | + ASP2_C_TX_CTRL2, // reg 0x2e 326 | + ASP2_D_TX_CTRL1, // reg 0x2f 327 | + ASP2_D_TX_CTRL2, // reg 0x30 328 | + ASP2_E_TX_CTRL1, // reg 0x31 329 | + ASP2_E_TX_CTRL2, // reg 0x32 330 | + ASP2_F_TX_CTRL1, // reg 0x33 331 | + ASP2_F_TX_CTRL2, // reg 0x34 332 | + ASP2_G_TX_CTRL1, // reg 0x35 333 | + ASP2_G_TX_CTRL2, // reg 0x36 334 | + ASP2_H_TX_CTRL1, // reg 0x37 335 | + ASP2_H_TX_CTRL2, // reg 0x38 336 | + ASP1_A_RX_CTRL1, // reg 0x39 337 | + ASP1_A_RX_CTRL2, // reg 0x3a 338 | + ASP1_B_RX_CTRL1, // reg 0x3b 339 | + ASP1_B_RX_CTRL2, // reg 0x3c 340 | + ASP1_C_RX_CTRL1, // reg 0x3d 341 | + ASP1_C_RX_CTRL2, // reg 0x3e 342 | + ASP1_D_RX_CTRL1, // reg 0x3f 343 | + ASP1_D_RX_CTRL2, // reg 0x40 344 | + ASP1_E_RX_CTRL1, // reg 0x41 345 | + ASP1_E_RX_CTRL2, // reg 0x42 346 | + ASP1_F_RX_CTRL1, // reg 0x43 347 | + ASP1_F_RX_CTRL2, // reg 0x44 348 | + ASP1_G_RX_CTRL1, // reg 0x45 349 | + ASP1_G_RX_CTRL2, // reg 0x46 350 | + ASP1_H_RX_CTRL1, // reg 0x47 351 | + ASP1_H_RX_CTRL2, // reg 0x48 352 | + ASP2_A_RX_CTRL1, // reg 0x49 353 | + ASP2_A_RX_CTRL2, // reg 0x4a 354 | + ASP2_B_RX_CTRL1, // reg 0x4b 355 | + ASP2_B_RX_CTRL2, // reg 0x4c 356 | + ASP2_C_RX_CTRL1, // reg 0x4d 357 | + ASP2_C_RX_CTRL2, // reg 0x4e 358 | + ASP2_D_RX_CTRL1, // reg 0x4f 359 | + ASP2_D_RX_CTRL2, // reg 0x50 360 | + ASP2_E_RX_CTRL1, // reg 0x51 361 | + ASP2_E_RX_CTRL2, // reg 0x52 362 | + ASP2_F_RX_CTRL1, // reg 0x53 363 | + ASP2_F_RX_CTRL2, // reg 0x54 364 | + ASP2_G_RX_CTRL1, // reg 0x55 365 | + ASP2_G_RX_CTRL2, // reg 0x56 366 | + ASP2_H_RX_CTRL1, // reg 0x57 367 | + ASP2_H_RX_CTRL2, // reg 0x58 368 | + CS8409_I2C_ADDR, // reg 0x59 369 | + CS8409_I2C_DATA, // reg 0x5a 370 | + CS8409_I2C_CTRL, // reg 0x5b 371 | + CS8409_I2C_STS, // reg 0x5c 372 | + CS8409_I2C_QWRITE, // reg 0x5d 373 | + CS8409_I2C_QREAD, // reg 0x5e 374 | + CS8409_SPI_CTRL, // reg 0x5f 375 | + CS8409_SPI_TX_DATA, // reg 0x60 376 | + CS8409_SPI_RX_DATA, // reg 0x61 377 | + CS8409_SPI_STS, // reg 0x62 378 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 379 | + CS8409_PFE_COEF_W2, // reg 0x64 380 | + CS8409_PFE_CTRL1, // reg 0x65 381 | + CS8409_PFE_CTRL2, // reg 0x66 382 | + CS8409_PRE_SCALE_ATTN1, // reg 0x67 383 | + CS8409_PRE_SCALE_ATTN2, // reg 0x68 384 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 385 | + CS8409_PFE_COEF_MON2, // reg 0x6a 386 | + CS8409_ASP1_INTRN_STS, // reg 0x6b 387 | + CS8409_ASP2_INTRN_STS, // reg 0x6c 388 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 389 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 390 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 391 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 392 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x71 393 | CS8409_LOOPBACK_CTRL = 0x80, 394 | - CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 395 | + CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 396 | }; 397 | 398 | /* CS42L42 Specific Definitions */ 399 | @@ -296,6 +302,23 @@ 400 | unsigned int coeff; 401 | }; 402 | 403 | + 404 | +#ifdef APPLE_CODECS 405 | +struct unsol_item { 406 | + struct list_head list; 407 | + unsigned int idx; 408 | + unsigned int res; 409 | +}; 410 | +struct hda_cvt_setup_apple { 411 | + hda_nid_t nid; 412 | + u8 stream_tag; 413 | + u8 channel_id; 414 | + u16 format_id; 415 | + unsigned char active; /* cvt is currently used */ 416 | + unsigned char dirty; /* setups should be cleared */ 417 | +}; 418 | +#endif 419 | + 420 | struct sub_codec { 421 | struct hda_codec *codec; 422 | unsigned int addr; 423 | @@ -306,6 +329,9 @@ 424 | 425 | unsigned int hp_jack_in:1; 426 | unsigned int mic_jack_in:1; 427 | +#ifdef APPLE_CODECS 428 | + unsigned int linein_jack_in:1; 429 | +#endif 430 | unsigned int suspended:1; 431 | unsigned int paged:1; 432 | unsigned int last_page; 433 | @@ -339,6 +365,126 @@ 434 | unsigned int init_done:1; 435 | unsigned int build_ctrl_done:1; 436 | 437 | +#ifdef APPLE_CODECS 438 | + 439 | + // additional data for Apple 8409 system 440 | + 441 | + unsigned int spdif_detect:1; 442 | + unsigned int spdif_present:1; 443 | + unsigned int sense_b:1; 444 | + hda_nid_t vendor_nid; 445 | + 446 | + /* digital beep */ 447 | + hda_nid_t beep_nid; 448 | + 449 | + /* for MBP SPDIF control */ 450 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 451 | + struct snd_ctl_elem_value *ucontrol); 452 | + 453 | + // so it appears we have "concurrency" in the linux HDA code 454 | + // in that if unsolicited responses occur which perform extensive verbs 455 | + // the hda verbs are intermixed with eg extensive start playback verbs 456 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 457 | + // are logged but the unsolicited verbs occur after the verb block 458 | + // this flag is used to flag such verb blocks and the list will store the 459 | + // responses 460 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 461 | + // we will drop 462 | + // not clear if mutexes would be the way to go 463 | + int block_unsol; 464 | + struct list_head unsol_list; 465 | + struct unsol_item unsol_items_prealloc[10]; 466 | + int unsol_items_prealloc_used[10]; 467 | + 468 | + // add in specific nids for the intmike and linein as they seem to swap 469 | + // between macbook pros (14,3) and imacs (18,3) 470 | + int intmike_nid; 471 | + int linein_nid; 472 | + int intmike_adc_nid; 473 | + int linein_amp_nid; 474 | + 475 | + // the following flag bits also need swapping 476 | + int reg9_intmike_dmic_mo; 477 | + int reg9_linein_dmic_mo; 478 | + int reg82_intmike_dmic_scl; 479 | + int reg82_linein_dmic_scl; 480 | + 481 | + 482 | + // add explicit stream format store entries as per hda_codec using a local definition 483 | + // of hda_cvt_setup (which is local to hda_codec.c) 484 | + // also use explicit nid versions 485 | + // (except that means either need explicit functions for each nid or have to lookup 486 | + // nid each time want to use in a generic function with nid argument) 487 | + struct hda_cvt_setup_apple nid_0x02; 488 | + struct hda_cvt_setup_apple nid_0x03; 489 | + struct hda_cvt_setup_apple nid_0x0a; 490 | + struct hda_cvt_setup_apple nid_0x22; 491 | + struct hda_cvt_setup_apple nid_0x23; 492 | + struct hda_cvt_setup_apple nid_0x1a; 493 | + 494 | + 495 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 496 | + // the HDA spec by using a separate headphone chip 497 | + int jack_present; 498 | + 499 | + // save the type of headphone connected 500 | + int headset_type; 501 | + 502 | + // if headphone has mike or not 503 | + int have_mike; 504 | + 505 | + // if headphone has buttons or not 506 | + int have_buttons; 507 | + 508 | + // current stream channel count 509 | + int stream_channels; 510 | + 511 | + // set when playing for plug/unplug events while playing 512 | + int playing; 513 | + 514 | + // set when capturing for plug/unplug events while capturing 515 | + int capturing; 516 | + 517 | + // changing coding - OSX sets up the format on plugin 518 | + // then does some minimal setup when start play 519 | + // initial coding delayed any format setup till actually play 520 | + // this works for no mike but not for mike - we need to initialize 521 | + // the mike on plugin 522 | + // this flag will be set when we have done the format setup 523 | + // so know if need to do it on play or not 524 | + // now need 2 flags - one for play and one for capture 525 | + int headset_play_format_setup_needed; 526 | + int headset_capture_format_setup_needed; 527 | + 528 | + int headset_presetup_done; 529 | + 530 | + 531 | + int use_data; 532 | + 533 | + 534 | + // this is new item for dealing with headset plugins 535 | + // so can distinguish which phase we are in if have multiple interrupts 536 | + // not really used now have analyzed interrupts properly 537 | + int headset_phase; 538 | + 539 | + // another dirty hack item to manage the different headset enable codes 540 | + int headset_enable; 541 | + 542 | + int play_init; 543 | + int capture_init; 544 | + 545 | + 546 | + // new item to limit times we redo unmute/play 547 | + struct timespec64 last_play_time; 548 | + // record the first play time - we have a problem there 549 | + // some initial plays that I dont understand - so skip any setup 550 | + // till sometime after the first play 551 | + struct timespec64 first_play_time; 552 | + 553 | + 554 | +#endif 555 | + 556 | + 557 | /* verb exec op override */ 558 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 559 | unsigned int *res); 560 | -------------------------------------------------------------------------------- /patches/patch_patch_cs8409.h.ubuntu.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.h b/patch_cirrus/patch_cs8409.h 2 | index d0b725c..d8b5232 100644 3 | --- a/kernel_sources/patch_cs8409.h 4 | +++ b/patch_cirrus/patch_cs8409.h 5 | @@ -19,200 +19,206 @@ 6 | #include "hda_jack.h" 7 | #include "hda_generic.h" 8 | 9 | +//#ifdef APPLE_CODECS 10 | +//#include 11 | +//#include 12 | +//#include 13 | +//#endif 14 | + 15 | /* CS8409 Specific Definitions */ 16 | 17 | enum cs8409_pins { 18 | - CS8409_PIN_ROOT, 19 | - CS8409_PIN_AFG, 20 | - CS8409_PIN_ASP1_OUT_A, 21 | - CS8409_PIN_ASP1_OUT_B, 22 | - CS8409_PIN_ASP1_OUT_C, 23 | - CS8409_PIN_ASP1_OUT_D, 24 | - CS8409_PIN_ASP1_OUT_E, 25 | - CS8409_PIN_ASP1_OUT_F, 26 | - CS8409_PIN_ASP1_OUT_G, 27 | - CS8409_PIN_ASP1_OUT_H, 28 | - CS8409_PIN_ASP2_OUT_A, 29 | - CS8409_PIN_ASP2_OUT_B, 30 | - CS8409_PIN_ASP2_OUT_C, 31 | - CS8409_PIN_ASP2_OUT_D, 32 | - CS8409_PIN_ASP2_OUT_E, 33 | - CS8409_PIN_ASP2_OUT_F, 34 | - CS8409_PIN_ASP2_OUT_G, 35 | - CS8409_PIN_ASP2_OUT_H, 36 | - CS8409_PIN_ASP1_IN_A, 37 | - CS8409_PIN_ASP1_IN_B, 38 | - CS8409_PIN_ASP1_IN_C, 39 | - CS8409_PIN_ASP1_IN_D, 40 | - CS8409_PIN_ASP1_IN_E, 41 | - CS8409_PIN_ASP1_IN_F, 42 | - CS8409_PIN_ASP1_IN_G, 43 | - CS8409_PIN_ASP1_IN_H, 44 | - CS8409_PIN_ASP2_IN_A, 45 | - CS8409_PIN_ASP2_IN_B, 46 | - CS8409_PIN_ASP2_IN_C, 47 | - CS8409_PIN_ASP2_IN_D, 48 | - CS8409_PIN_ASP2_IN_E, 49 | - CS8409_PIN_ASP2_IN_F, 50 | - CS8409_PIN_ASP2_IN_G, 51 | - CS8409_PIN_ASP2_IN_H, 52 | - CS8409_PIN_DMIC1, 53 | - CS8409_PIN_DMIC2, 54 | - CS8409_PIN_ASP1_TRANSMITTER_A, 55 | - CS8409_PIN_ASP1_TRANSMITTER_B, 56 | - CS8409_PIN_ASP1_TRANSMITTER_C, 57 | - CS8409_PIN_ASP1_TRANSMITTER_D, 58 | - CS8409_PIN_ASP1_TRANSMITTER_E, 59 | - CS8409_PIN_ASP1_TRANSMITTER_F, 60 | - CS8409_PIN_ASP1_TRANSMITTER_G, 61 | - CS8409_PIN_ASP1_TRANSMITTER_H, 62 | - CS8409_PIN_ASP2_TRANSMITTER_A, 63 | - CS8409_PIN_ASP2_TRANSMITTER_B, 64 | - CS8409_PIN_ASP2_TRANSMITTER_C, 65 | - CS8409_PIN_ASP2_TRANSMITTER_D, 66 | - CS8409_PIN_ASP2_TRANSMITTER_E, 67 | - CS8409_PIN_ASP2_TRANSMITTER_F, 68 | - CS8409_PIN_ASP2_TRANSMITTER_G, 69 | - CS8409_PIN_ASP2_TRANSMITTER_H, 70 | - CS8409_PIN_ASP1_RECEIVER_A, 71 | - CS8409_PIN_ASP1_RECEIVER_B, 72 | - CS8409_PIN_ASP1_RECEIVER_C, 73 | - CS8409_PIN_ASP1_RECEIVER_D, 74 | - CS8409_PIN_ASP1_RECEIVER_E, 75 | - CS8409_PIN_ASP1_RECEIVER_F, 76 | - CS8409_PIN_ASP1_RECEIVER_G, 77 | - CS8409_PIN_ASP1_RECEIVER_H, 78 | - CS8409_PIN_ASP2_RECEIVER_A, 79 | - CS8409_PIN_ASP2_RECEIVER_B, 80 | - CS8409_PIN_ASP2_RECEIVER_C, 81 | - CS8409_PIN_ASP2_RECEIVER_D, 82 | - CS8409_PIN_ASP2_RECEIVER_E, 83 | - CS8409_PIN_ASP2_RECEIVER_F, 84 | - CS8409_PIN_ASP2_RECEIVER_G, 85 | - CS8409_PIN_ASP2_RECEIVER_H, 86 | - CS8409_PIN_DMIC1_IN, 87 | - CS8409_PIN_DMIC2_IN, 88 | - CS8409_PIN_BEEP_GEN, 89 | - CS8409_PIN_VENDOR_WIDGET 90 | + CS8409_PIN_ROOT, // nid 0x00 91 | + CS8409_PIN_AFG, // nid 0x01 92 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 93 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 94 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 95 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_E, // nid 0x06 97 | + CS8409_PIN_ASP1_OUT_F, // nid 0x07 98 | + CS8409_PIN_ASP1_OUT_G, // nid 0x08 99 | + CS8409_PIN_ASP1_OUT_H, // nid 0x09 100 | + CS8409_PIN_ASP2_OUT_A, // nid 0x0a 101 | + CS8409_PIN_ASP2_OUT_B, // nid 0x0b 102 | + CS8409_PIN_ASP2_OUT_C, // nid 0x0c 103 | + CS8409_PIN_ASP2_OUT_D, // nid 0x0d 104 | + CS8409_PIN_ASP2_OUT_E, // nid 0x0e 105 | + CS8409_PIN_ASP2_OUT_F, // nid 0x0f 106 | + CS8409_PIN_ASP2_OUT_G, // nid 0x10 107 | + CS8409_PIN_ASP2_OUT_H, // nid 0x11 108 | + CS8409_PIN_ASP1_IN_A, // nid 0x12 109 | + CS8409_PIN_ASP1_IN_B, // nid 0x13 110 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 111 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_E, // nid 0x16 113 | + CS8409_PIN_ASP1_IN_F, // nid 0x17 114 | + CS8409_PIN_ASP1_IN_G, // nid 0x18 115 | + CS8409_PIN_ASP1_IN_H, // nid 0x19 116 | + CS8409_PIN_ASP2_IN_A, // nid 0x1a 117 | + CS8409_PIN_ASP2_IN_B, // nid 0x1b 118 | + CS8409_PIN_ASP2_IN_C, // nid 0x1c 119 | + CS8409_PIN_ASP2_IN_D, // nid 0x1d 120 | + CS8409_PIN_ASP2_IN_E, // nid 0x1e 121 | + CS8409_PIN_ASP2_IN_F, // nid 0x1f 122 | + CS8409_PIN_ASP2_IN_G, // nid 0x20 123 | + CS8409_PIN_ASP2_IN_H, // nid 0x21 124 | + CS8409_PIN_DMIC1, // nid 0x22 125 | + CS8409_PIN_DMIC2, // nid 0x23 126 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 127 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 129 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 130 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 131 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 132 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 133 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 134 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 135 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 136 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 137 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 138 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 139 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 140 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 141 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 142 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 144 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 145 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 146 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 147 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 148 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 149 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 150 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 151 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 152 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 153 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 154 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 155 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 156 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 157 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 158 | + CS8409_PIN_DMIC1_IN, // nid 0x44 159 | + CS8409_PIN_DMIC2_IN, // nid 0x45 160 | + CS8409_PIN_BEEP_GEN, // nid 0x46 161 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 162 | }; 163 | 164 | enum cs8409_coefficient_index_registers { 165 | - CS8409_DEV_CFG1, 166 | - CS8409_DEV_CFG2, 167 | - CS8409_DEV_CFG3, 168 | - CS8409_ASP1_CLK_CTRL1, 169 | - CS8409_ASP1_CLK_CTRL2, 170 | - CS8409_ASP1_CLK_CTRL3, 171 | - CS8409_ASP2_CLK_CTRL1, 172 | - CS8409_ASP2_CLK_CTRL2, 173 | - CS8409_ASP2_CLK_CTRL3, 174 | - CS8409_DMIC_CFG, 175 | - CS8409_BEEP_CFG, 176 | - ASP1_RX_NULL_INS_RMV, 177 | - ASP1_Rx_RATE1, 178 | - ASP1_Rx_RATE2, 179 | - ASP1_Tx_NULL_INS_RMV, 180 | - ASP1_Tx_RATE1, 181 | - ASP1_Tx_RATE2, 182 | - ASP2_Rx_NULL_INS_RMV, 183 | - ASP2_Rx_RATE1, 184 | - ASP2_Rx_RATE2, 185 | - ASP2_Tx_NULL_INS_RMV, 186 | - ASP2_Tx_RATE1, 187 | - ASP2_Tx_RATE2, 188 | - ASP1_SYNC_CTRL, 189 | - ASP2_SYNC_CTRL, 190 | - ASP1_A_TX_CTRL1, 191 | - ASP1_A_TX_CTRL2, 192 | - ASP1_B_TX_CTRL1, 193 | - ASP1_B_TX_CTRL2, 194 | - ASP1_C_TX_CTRL1, 195 | - ASP1_C_TX_CTRL2, 196 | - ASP1_D_TX_CTRL1, 197 | - ASP1_D_TX_CTRL2, 198 | - ASP1_E_TX_CTRL1, 199 | - ASP1_E_TX_CTRL2, 200 | - ASP1_F_TX_CTRL1, 201 | - ASP1_F_TX_CTRL2, 202 | - ASP1_G_TX_CTRL1, 203 | - ASP1_G_TX_CTRL2, 204 | - ASP1_H_TX_CTRL1, 205 | - ASP1_H_TX_CTRL2, 206 | - ASP2_A_TX_CTRL1, 207 | - ASP2_A_TX_CTRL2, 208 | - ASP2_B_TX_CTRL1, 209 | - ASP2_B_TX_CTRL2, 210 | - ASP2_C_TX_CTRL1, 211 | - ASP2_C_TX_CTRL2, 212 | - ASP2_D_TX_CTRL1, 213 | - ASP2_D_TX_CTRL2, 214 | - ASP2_E_TX_CTRL1, 215 | - ASP2_E_TX_CTRL2, 216 | - ASP2_F_TX_CTRL1, 217 | - ASP2_F_TX_CTRL2, 218 | - ASP2_G_TX_CTRL1, 219 | - ASP2_G_TX_CTRL2, 220 | - ASP2_H_TX_CTRL1, 221 | - ASP2_H_TX_CTRL2, 222 | - ASP1_A_RX_CTRL1, 223 | - ASP1_A_RX_CTRL2, 224 | - ASP1_B_RX_CTRL1, 225 | - ASP1_B_RX_CTRL2, 226 | - ASP1_C_RX_CTRL1, 227 | - ASP1_C_RX_CTRL2, 228 | - ASP1_D_RX_CTRL1, 229 | - ASP1_D_RX_CTRL2, 230 | - ASP1_E_RX_CTRL1, 231 | - ASP1_E_RX_CTRL2, 232 | - ASP1_F_RX_CTRL1, 233 | - ASP1_F_RX_CTRL2, 234 | - ASP1_G_RX_CTRL1, 235 | - ASP1_G_RX_CTRL2, 236 | - ASP1_H_RX_CTRL1, 237 | - ASP1_H_RX_CTRL2, 238 | - ASP2_A_RX_CTRL1, 239 | - ASP2_A_RX_CTRL2, 240 | - ASP2_B_RX_CTRL1, 241 | - ASP2_B_RX_CTRL2, 242 | - ASP2_C_RX_CTRL1, 243 | - ASP2_C_RX_CTRL2, 244 | - ASP2_D_RX_CTRL1, 245 | - ASP2_D_RX_CTRL2, 246 | - ASP2_E_RX_CTRL1, 247 | - ASP2_E_RX_CTRL2, 248 | - ASP2_F_RX_CTRL1, 249 | - ASP2_F_RX_CTRL2, 250 | - ASP2_G_RX_CTRL1, 251 | - ASP2_G_RX_CTRL2, 252 | - ASP2_H_RX_CTRL1, 253 | - ASP2_H_RX_CTRL2, 254 | - CS8409_I2C_ADDR, 255 | - CS8409_I2C_DATA, 256 | - CS8409_I2C_CTRL, 257 | - CS8409_I2C_STS, 258 | - CS8409_I2C_QWRITE, 259 | - CS8409_I2C_QREAD, 260 | - CS8409_SPI_CTRL, 261 | - CS8409_SPI_TX_DATA, 262 | - CS8409_SPI_RX_DATA, 263 | - CS8409_SPI_STS, 264 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 265 | - CS8409_PFE_COEF_W2, 266 | - CS8409_PFE_CTRL1, 267 | - CS8409_PFE_CTRL2, 268 | - CS8409_PRE_SCALE_ATTN1, 269 | - CS8409_PRE_SCALE_ATTN2, 270 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 271 | - CS8409_PFE_COEF_MON2, 272 | - CS8409_ASP1_INTRN_STS, 273 | - CS8409_ASP2_INTRN_STS, 274 | - CS8409_ASP1_RX_SCLK_COUNT, 275 | - CS8409_ASP1_TX_SCLK_COUNT, 276 | - CS8409_ASP2_RX_SCLK_COUNT, 277 | - CS8409_ASP2_TX_SCLK_COUNT, 278 | - CS8409_ASP_UNS_RESP_MASK, 279 | + CS8409_DEV_CFG1, // reg 0x00 280 | + CS8409_DEV_CFG2, // reg 0x01 281 | + CS8409_DEV_CFG3, // reg 0x02 282 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 283 | + CS8409_ASP1_CLK_CTRL2, // reg 0x04 284 | + CS8409_ASP1_CLK_CTRL3, // reg 0x05 285 | + CS8409_ASP2_CLK_CTRL1, // reg 0x06 286 | + CS8409_ASP2_CLK_CTRL2, // reg 0x07 287 | + CS8409_ASP2_CLK_CTRL3, // reg 0x08 288 | + CS8409_DMIC_CFG, // reg 0x09 289 | + CS8409_BEEP_CFG, // reg 0x0a 290 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 291 | + ASP1_Rx_RATE1, // reg 0x0c 292 | + ASP1_Rx_RATE2, // reg 0x0d 293 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 294 | + ASP1_Tx_RATE1, // reg 0x0f 295 | + ASP1_Tx_RATE2, // reg 0x10 296 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 297 | + ASP2_Rx_RATE1, // reg 0x12 298 | + ASP2_Rx_RATE2, // reg 0x13 299 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 300 | + ASP2_Tx_RATE1, // reg 0x15 301 | + ASP2_Tx_RATE2, // reg 0x16 302 | + ASP1_SYNC_CTRL, // reg 0x17 303 | + ASP2_SYNC_CTRL, // reg 0x18 304 | + ASP1_A_TX_CTRL1, // reg 0x19 305 | + ASP1_A_TX_CTRL2, // reg 0x1a 306 | + ASP1_B_TX_CTRL1, // reg 0x1b 307 | + ASP1_B_TX_CTRL2, // reg 0x1c 308 | + ASP1_C_TX_CTRL1, // reg 0x1d 309 | + ASP1_C_TX_CTRL2, // reg 0x1e 310 | + ASP1_D_TX_CTRL1, // reg 0x1f 311 | + ASP1_D_TX_CTRL2, // reg 0x20 312 | + ASP1_E_TX_CTRL1, // reg 0x21 313 | + ASP1_E_TX_CTRL2, // reg 0x22 314 | + ASP1_F_TX_CTRL1, // reg 0x23 315 | + ASP1_F_TX_CTRL2, // reg 0x24 316 | + ASP1_G_TX_CTRL1, // reg 0x25 317 | + ASP1_G_TX_CTRL2, // reg 0x26 318 | + ASP1_H_TX_CTRL1, // reg 0x27 319 | + ASP1_H_TX_CTRL2, // reg 0x28 320 | + ASP2_A_TX_CTRL1, // reg 0x29 321 | + ASP2_A_TX_CTRL2, // reg 0x2a 322 | + ASP2_B_TX_CTRL1, // reg 0x2b 323 | + ASP2_B_TX_CTRL2, // reg 0x2c 324 | + ASP2_C_TX_CTRL1, // reg 0x2d 325 | + ASP2_C_TX_CTRL2, // reg 0x2e 326 | + ASP2_D_TX_CTRL1, // reg 0x2f 327 | + ASP2_D_TX_CTRL2, // reg 0x30 328 | + ASP2_E_TX_CTRL1, // reg 0x31 329 | + ASP2_E_TX_CTRL2, // reg 0x32 330 | + ASP2_F_TX_CTRL1, // reg 0x33 331 | + ASP2_F_TX_CTRL2, // reg 0x34 332 | + ASP2_G_TX_CTRL1, // reg 0x35 333 | + ASP2_G_TX_CTRL2, // reg 0x36 334 | + ASP2_H_TX_CTRL1, // reg 0x37 335 | + ASP2_H_TX_CTRL2, // reg 0x38 336 | + ASP1_A_RX_CTRL1, // reg 0x39 337 | + ASP1_A_RX_CTRL2, // reg 0x3a 338 | + ASP1_B_RX_CTRL1, // reg 0x3b 339 | + ASP1_B_RX_CTRL2, // reg 0x3c 340 | + ASP1_C_RX_CTRL1, // reg 0x3d 341 | + ASP1_C_RX_CTRL2, // reg 0x3e 342 | + ASP1_D_RX_CTRL1, // reg 0x3f 343 | + ASP1_D_RX_CTRL2, // reg 0x40 344 | + ASP1_E_RX_CTRL1, // reg 0x41 345 | + ASP1_E_RX_CTRL2, // reg 0x42 346 | + ASP1_F_RX_CTRL1, // reg 0x43 347 | + ASP1_F_RX_CTRL2, // reg 0x44 348 | + ASP1_G_RX_CTRL1, // reg 0x45 349 | + ASP1_G_RX_CTRL2, // reg 0x46 350 | + ASP1_H_RX_CTRL1, // reg 0x47 351 | + ASP1_H_RX_CTRL2, // reg 0x48 352 | + ASP2_A_RX_CTRL1, // reg 0x49 353 | + ASP2_A_RX_CTRL2, // reg 0x4a 354 | + ASP2_B_RX_CTRL1, // reg 0x4b 355 | + ASP2_B_RX_CTRL2, // reg 0x4c 356 | + ASP2_C_RX_CTRL1, // reg 0x4d 357 | + ASP2_C_RX_CTRL2, // reg 0x4e 358 | + ASP2_D_RX_CTRL1, // reg 0x4f 359 | + ASP2_D_RX_CTRL2, // reg 0x50 360 | + ASP2_E_RX_CTRL1, // reg 0x51 361 | + ASP2_E_RX_CTRL2, // reg 0x52 362 | + ASP2_F_RX_CTRL1, // reg 0x53 363 | + ASP2_F_RX_CTRL2, // reg 0x54 364 | + ASP2_G_RX_CTRL1, // reg 0x55 365 | + ASP2_G_RX_CTRL2, // reg 0x56 366 | + ASP2_H_RX_CTRL1, // reg 0x57 367 | + ASP2_H_RX_CTRL2, // reg 0x58 368 | + CS8409_I2C_ADDR, // reg 0x59 369 | + CS8409_I2C_DATA, // reg 0x5a 370 | + CS8409_I2C_CTRL, // reg 0x5b 371 | + CS8409_I2C_STS, // reg 0x5c 372 | + CS8409_I2C_QWRITE, // reg 0x5d 373 | + CS8409_I2C_QREAD, // reg 0x5e 374 | + CS8409_SPI_CTRL, // reg 0x5f 375 | + CS8409_SPI_TX_DATA, // reg 0x60 376 | + CS8409_SPI_RX_DATA, // reg 0x61 377 | + CS8409_SPI_STS, // reg 0x62 378 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 379 | + CS8409_PFE_COEF_W2, // reg 0x64 380 | + CS8409_PFE_CTRL1, // reg 0x65 381 | + CS8409_PFE_CTRL2, // reg 0x66 382 | + CS8409_PRE_SCALE_ATTN1, // reg 0x67 383 | + CS8409_PRE_SCALE_ATTN2, // reg 0x68 384 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 385 | + CS8409_PFE_COEF_MON2, // reg 0x6a 386 | + CS8409_ASP1_INTRN_STS, // reg 0x6b 387 | + CS8409_ASP2_INTRN_STS, // reg 0x6c 388 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 389 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 390 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 391 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 392 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x71 393 | CS8409_LOOPBACK_CTRL = 0x80, 394 | - CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 395 | + CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 396 | }; 397 | 398 | /* CS42L42 Specific Definitions */ 399 | @@ -296,6 +302,23 @@ 400 | unsigned int coeff; 401 | }; 402 | 403 | + 404 | +#ifdef APPLE_CODECS 405 | +struct unsol_item { 406 | + struct list_head list; 407 | + unsigned int idx; 408 | + unsigned int res; 409 | +}; 410 | +struct hda_cvt_setup_apple { 411 | + hda_nid_t nid; 412 | + u8 stream_tag; 413 | + u8 channel_id; 414 | + u16 format_id; 415 | + unsigned char active; /* cvt is currently used */ 416 | + unsigned char dirty; /* setups should be cleared */ 417 | +}; 418 | +#endif 419 | + 420 | struct sub_codec { 421 | struct hda_codec *codec; 422 | unsigned int addr; 423 | @@ -306,6 +329,9 @@ 424 | 425 | unsigned int hp_jack_in:1; 426 | unsigned int mic_jack_in:1; 427 | +#ifdef APPLE_CODECS 428 | + unsigned int linein_jack_in:1; 429 | +#endif 430 | unsigned int suspended:1; 431 | unsigned int paged:1; 432 | unsigned int last_page; 433 | @@ -339,6 +365,126 @@ 434 | unsigned int init_done:1; 435 | unsigned int build_ctrl_done:1; 436 | 437 | +#ifdef APPLE_CODECS 438 | + 439 | + // additional data for Apple 8409 system 440 | + 441 | + unsigned int spdif_detect:1; 442 | + unsigned int spdif_present:1; 443 | + unsigned int sense_b:1; 444 | + hda_nid_t vendor_nid; 445 | + 446 | + /* digital beep */ 447 | + hda_nid_t beep_nid; 448 | + 449 | + /* for MBP SPDIF control */ 450 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 451 | + struct snd_ctl_elem_value *ucontrol); 452 | + 453 | + // so it appears we have "concurrency" in the linux HDA code 454 | + // in that if unsolicited responses occur which perform extensive verbs 455 | + // the hda verbs are intermixed with eg extensive start playback verbs 456 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 457 | + // are logged but the unsolicited verbs occur after the verb block 458 | + // this flag is used to flag such verb blocks and the list will store the 459 | + // responses 460 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 461 | + // we will drop 462 | + // not clear if mutexes would be the way to go 463 | + int block_unsol; 464 | + struct list_head unsol_list; 465 | + struct unsol_item unsol_items_prealloc[10]; 466 | + int unsol_items_prealloc_used[10]; 467 | + 468 | + // add in specific nids for the intmike and linein as they seem to swap 469 | + // between macbook pros (14,3) and imacs (18,3) 470 | + int intmike_nid; 471 | + int linein_nid; 472 | + int intmike_adc_nid; 473 | + int linein_amp_nid; 474 | + 475 | + // the following flag bits also need swapping 476 | + int reg9_intmike_dmic_mo; 477 | + int reg9_linein_dmic_mo; 478 | + int reg82_intmike_dmic_scl; 479 | + int reg82_linein_dmic_scl; 480 | + 481 | + 482 | + // add explicit stream format store entries as per hda_codec using a local definition 483 | + // of hda_cvt_setup (which is local to hda_codec.c) 484 | + // also use explicit nid versions 485 | + // (except that means either need explicit functions for each nid or have to lookup 486 | + // nid each time want to use in a generic function with nid argument) 487 | + struct hda_cvt_setup_apple nid_0x02; 488 | + struct hda_cvt_setup_apple nid_0x03; 489 | + struct hda_cvt_setup_apple nid_0x0a; 490 | + struct hda_cvt_setup_apple nid_0x22; 491 | + struct hda_cvt_setup_apple nid_0x23; 492 | + struct hda_cvt_setup_apple nid_0x1a; 493 | + 494 | + 495 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 496 | + // the HDA spec by using a separate headphone chip 497 | + int jack_present; 498 | + 499 | + // save the type of headphone connected 500 | + int headset_type; 501 | + 502 | + // if headphone has mike or not 503 | + int have_mike; 504 | + 505 | + // if headphone has buttons or not 506 | + int have_buttons; 507 | + 508 | + // current stream channel count 509 | + int stream_channels; 510 | + 511 | + // set when playing for plug/unplug events while playing 512 | + int playing; 513 | + 514 | + // set when capturing for plug/unplug events while capturing 515 | + int capturing; 516 | + 517 | + // changing coding - OSX sets up the format on plugin 518 | + // then does some minimal setup when start play 519 | + // initial coding delayed any format setup till actually play 520 | + // this works for no mike but not for mike - we need to initialize 521 | + // the mike on plugin 522 | + // this flag will be set when we have done the format setup 523 | + // so know if need to do it on play or not 524 | + // now need 2 flags - one for play and one for capture 525 | + int headset_play_format_setup_needed; 526 | + int headset_capture_format_setup_needed; 527 | + 528 | + int headset_presetup_done; 529 | + 530 | + 531 | + int use_data; 532 | + 533 | + 534 | + // this is new item for dealing with headset plugins 535 | + // so can distinguish which phase we are in if have multiple interrupts 536 | + // not really used now have analyzed interrupts properly 537 | + int headset_phase; 538 | + 539 | + // another dirty hack item to manage the different headset enable codes 540 | + int headset_enable; 541 | + 542 | + int play_init; 543 | + int capture_init; 544 | + 545 | + 546 | + // new item to limit times we redo unmute/play 547 | + struct timespec64 last_play_time; 548 | + // record the first play time - we have a problem there 549 | + // some initial plays that I dont understand - so skip any setup 550 | + // till sometime after the first play 551 | + struct timespec64 first_play_time; 552 | + 553 | + 554 | +#endif 555 | + 556 | + 557 | /* verb exec op override */ 558 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 559 | unsigned int *res); 560 | -------------------------------------------------------------------------------- /patch_patch_cs8409.h.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.h b/patch_cirrus/patch_cs8409.h 2 | index d0b725c..d8b5232 100644 3 | --- a/kernel_sources/patch_cs8409.h 4 | +++ b/patch_cirrus/patch_cs8409.h 5 | @@ -19,200 +19,206 @@ 6 | #include "hda_jack.h" 7 | #include "hda_generic.h" 8 | 9 | +//#ifdef APPLE_CODECS 10 | +//#include 11 | +//#include 12 | +//#include 13 | +//#endif 14 | + 15 | /* CS8409 Specific Definitions */ 16 | 17 | enum cs8409_pins { 18 | - CS8409_PIN_ROOT, 19 | - CS8409_PIN_AFG, 20 | - CS8409_PIN_ASP1_OUT_A, 21 | - CS8409_PIN_ASP1_OUT_B, 22 | - CS8409_PIN_ASP1_OUT_C, 23 | - CS8409_PIN_ASP1_OUT_D, 24 | - CS8409_PIN_ASP1_OUT_E, 25 | - CS8409_PIN_ASP1_OUT_F, 26 | - CS8409_PIN_ASP1_OUT_G, 27 | - CS8409_PIN_ASP1_OUT_H, 28 | - CS8409_PIN_ASP2_OUT_A, 29 | - CS8409_PIN_ASP2_OUT_B, 30 | - CS8409_PIN_ASP2_OUT_C, 31 | - CS8409_PIN_ASP2_OUT_D, 32 | - CS8409_PIN_ASP2_OUT_E, 33 | - CS8409_PIN_ASP2_OUT_F, 34 | - CS8409_PIN_ASP2_OUT_G, 35 | - CS8409_PIN_ASP2_OUT_H, 36 | - CS8409_PIN_ASP1_IN_A, 37 | - CS8409_PIN_ASP1_IN_B, 38 | - CS8409_PIN_ASP1_IN_C, 39 | - CS8409_PIN_ASP1_IN_D, 40 | - CS8409_PIN_ASP1_IN_E, 41 | - CS8409_PIN_ASP1_IN_F, 42 | - CS8409_PIN_ASP1_IN_G, 43 | - CS8409_PIN_ASP1_IN_H, 44 | - CS8409_PIN_ASP2_IN_A, 45 | - CS8409_PIN_ASP2_IN_B, 46 | - CS8409_PIN_ASP2_IN_C, 47 | - CS8409_PIN_ASP2_IN_D, 48 | - CS8409_PIN_ASP2_IN_E, 49 | - CS8409_PIN_ASP2_IN_F, 50 | - CS8409_PIN_ASP2_IN_G, 51 | - CS8409_PIN_ASP2_IN_H, 52 | - CS8409_PIN_DMIC1, 53 | - CS8409_PIN_DMIC2, 54 | - CS8409_PIN_ASP1_TRANSMITTER_A, 55 | - CS8409_PIN_ASP1_TRANSMITTER_B, 56 | - CS8409_PIN_ASP1_TRANSMITTER_C, 57 | - CS8409_PIN_ASP1_TRANSMITTER_D, 58 | - CS8409_PIN_ASP1_TRANSMITTER_E, 59 | - CS8409_PIN_ASP1_TRANSMITTER_F, 60 | - CS8409_PIN_ASP1_TRANSMITTER_G, 61 | - CS8409_PIN_ASP1_TRANSMITTER_H, 62 | - CS8409_PIN_ASP2_TRANSMITTER_A, 63 | - CS8409_PIN_ASP2_TRANSMITTER_B, 64 | - CS8409_PIN_ASP2_TRANSMITTER_C, 65 | - CS8409_PIN_ASP2_TRANSMITTER_D, 66 | - CS8409_PIN_ASP2_TRANSMITTER_E, 67 | - CS8409_PIN_ASP2_TRANSMITTER_F, 68 | - CS8409_PIN_ASP2_TRANSMITTER_G, 69 | - CS8409_PIN_ASP2_TRANSMITTER_H, 70 | - CS8409_PIN_ASP1_RECEIVER_A, 71 | - CS8409_PIN_ASP1_RECEIVER_B, 72 | - CS8409_PIN_ASP1_RECEIVER_C, 73 | - CS8409_PIN_ASP1_RECEIVER_D, 74 | - CS8409_PIN_ASP1_RECEIVER_E, 75 | - CS8409_PIN_ASP1_RECEIVER_F, 76 | - CS8409_PIN_ASP1_RECEIVER_G, 77 | - CS8409_PIN_ASP1_RECEIVER_H, 78 | - CS8409_PIN_ASP2_RECEIVER_A, 79 | - CS8409_PIN_ASP2_RECEIVER_B, 80 | - CS8409_PIN_ASP2_RECEIVER_C, 81 | - CS8409_PIN_ASP2_RECEIVER_D, 82 | - CS8409_PIN_ASP2_RECEIVER_E, 83 | - CS8409_PIN_ASP2_RECEIVER_F, 84 | - CS8409_PIN_ASP2_RECEIVER_G, 85 | - CS8409_PIN_ASP2_RECEIVER_H, 86 | - CS8409_PIN_DMIC1_IN, 87 | - CS8409_PIN_DMIC2_IN, 88 | - CS8409_PIN_BEEP_GEN, 89 | - CS8409_PIN_VENDOR_WIDGET 90 | + CS8409_PIN_ROOT, // nid 0x00 91 | + CS8409_PIN_AFG, // nid 0x01 92 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 93 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 94 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 95 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_E, // nid 0x06 97 | + CS8409_PIN_ASP1_OUT_F, // nid 0x07 98 | + CS8409_PIN_ASP1_OUT_G, // nid 0x08 99 | + CS8409_PIN_ASP1_OUT_H, // nid 0x09 100 | + CS8409_PIN_ASP2_OUT_A, // nid 0x0a 101 | + CS8409_PIN_ASP2_OUT_B, // nid 0x0b 102 | + CS8409_PIN_ASP2_OUT_C, // nid 0x0c 103 | + CS8409_PIN_ASP2_OUT_D, // nid 0x0d 104 | + CS8409_PIN_ASP2_OUT_E, // nid 0x0e 105 | + CS8409_PIN_ASP2_OUT_F, // nid 0x0f 106 | + CS8409_PIN_ASP2_OUT_G, // nid 0x10 107 | + CS8409_PIN_ASP2_OUT_H, // nid 0x11 108 | + CS8409_PIN_ASP1_IN_A, // nid 0x12 109 | + CS8409_PIN_ASP1_IN_B, // nid 0x13 110 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 111 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_E, // nid 0x16 113 | + CS8409_PIN_ASP1_IN_F, // nid 0x17 114 | + CS8409_PIN_ASP1_IN_G, // nid 0x18 115 | + CS8409_PIN_ASP1_IN_H, // nid 0x19 116 | + CS8409_PIN_ASP2_IN_A, // nid 0x1a 117 | + CS8409_PIN_ASP2_IN_B, // nid 0x1b 118 | + CS8409_PIN_ASP2_IN_C, // nid 0x1c 119 | + CS8409_PIN_ASP2_IN_D, // nid 0x1d 120 | + CS8409_PIN_ASP2_IN_E, // nid 0x1e 121 | + CS8409_PIN_ASP2_IN_F, // nid 0x1f 122 | + CS8409_PIN_ASP2_IN_G, // nid 0x20 123 | + CS8409_PIN_ASP2_IN_H, // nid 0x21 124 | + CS8409_PIN_DMIC1, // nid 0x22 125 | + CS8409_PIN_DMIC2, // nid 0x23 126 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 127 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 129 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 130 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 131 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 132 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 133 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 134 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 135 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 136 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 137 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 138 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 139 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 140 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 141 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 142 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 144 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 145 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 146 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 147 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 148 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 149 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 150 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 151 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 152 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 153 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 154 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 155 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 156 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 157 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 158 | + CS8409_PIN_DMIC1_IN, // nid 0x44 159 | + CS8409_PIN_DMIC2_IN, // nid 0x45 160 | + CS8409_PIN_BEEP_GEN, // nid 0x46 161 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 162 | }; 163 | 164 | enum cs8409_coefficient_index_registers { 165 | - CS8409_DEV_CFG1, 166 | - CS8409_DEV_CFG2, 167 | - CS8409_DEV_CFG3, 168 | - CS8409_ASP1_CLK_CTRL1, 169 | - CS8409_ASP1_CLK_CTRL2, 170 | - CS8409_ASP1_CLK_CTRL3, 171 | - CS8409_ASP2_CLK_CTRL1, 172 | - CS8409_ASP2_CLK_CTRL2, 173 | - CS8409_ASP2_CLK_CTRL3, 174 | - CS8409_DMIC_CFG, 175 | - CS8409_BEEP_CFG, 176 | - ASP1_RX_NULL_INS_RMV, 177 | - ASP1_Rx_RATE1, 178 | - ASP1_Rx_RATE2, 179 | - ASP1_Tx_NULL_INS_RMV, 180 | - ASP1_Tx_RATE1, 181 | - ASP1_Tx_RATE2, 182 | - ASP2_Rx_NULL_INS_RMV, 183 | - ASP2_Rx_RATE1, 184 | - ASP2_Rx_RATE2, 185 | - ASP2_Tx_NULL_INS_RMV, 186 | - ASP2_Tx_RATE1, 187 | - ASP2_Tx_RATE2, 188 | - ASP1_SYNC_CTRL, 189 | - ASP2_SYNC_CTRL, 190 | - ASP1_A_TX_CTRL1, 191 | - ASP1_A_TX_CTRL2, 192 | - ASP1_B_TX_CTRL1, 193 | - ASP1_B_TX_CTRL2, 194 | - ASP1_C_TX_CTRL1, 195 | - ASP1_C_TX_CTRL2, 196 | - ASP1_D_TX_CTRL1, 197 | - ASP1_D_TX_CTRL2, 198 | - ASP1_E_TX_CTRL1, 199 | - ASP1_E_TX_CTRL2, 200 | - ASP1_F_TX_CTRL1, 201 | - ASP1_F_TX_CTRL2, 202 | - ASP1_G_TX_CTRL1, 203 | - ASP1_G_TX_CTRL2, 204 | - ASP1_H_TX_CTRL1, 205 | - ASP1_H_TX_CTRL2, 206 | - ASP2_A_TX_CTRL1, 207 | - ASP2_A_TX_CTRL2, 208 | - ASP2_B_TX_CTRL1, 209 | - ASP2_B_TX_CTRL2, 210 | - ASP2_C_TX_CTRL1, 211 | - ASP2_C_TX_CTRL2, 212 | - ASP2_D_TX_CTRL1, 213 | - ASP2_D_TX_CTRL2, 214 | - ASP2_E_TX_CTRL1, 215 | - ASP2_E_TX_CTRL2, 216 | - ASP2_F_TX_CTRL1, 217 | - ASP2_F_TX_CTRL2, 218 | - ASP2_G_TX_CTRL1, 219 | - ASP2_G_TX_CTRL2, 220 | - ASP2_H_TX_CTRL1, 221 | - ASP2_H_TX_CTRL2, 222 | - ASP1_A_RX_CTRL1, 223 | - ASP1_A_RX_CTRL2, 224 | - ASP1_B_RX_CTRL1, 225 | - ASP1_B_RX_CTRL2, 226 | - ASP1_C_RX_CTRL1, 227 | - ASP1_C_RX_CTRL2, 228 | - ASP1_D_RX_CTRL1, 229 | - ASP1_D_RX_CTRL2, 230 | - ASP1_E_RX_CTRL1, 231 | - ASP1_E_RX_CTRL2, 232 | - ASP1_F_RX_CTRL1, 233 | - ASP1_F_RX_CTRL2, 234 | - ASP1_G_RX_CTRL1, 235 | - ASP1_G_RX_CTRL2, 236 | - ASP1_H_RX_CTRL1, 237 | - ASP1_H_RX_CTRL2, 238 | - ASP2_A_RX_CTRL1, 239 | - ASP2_A_RX_CTRL2, 240 | - ASP2_B_RX_CTRL1, 241 | - ASP2_B_RX_CTRL2, 242 | - ASP2_C_RX_CTRL1, 243 | - ASP2_C_RX_CTRL2, 244 | - ASP2_D_RX_CTRL1, 245 | - ASP2_D_RX_CTRL2, 246 | - ASP2_E_RX_CTRL1, 247 | - ASP2_E_RX_CTRL2, 248 | - ASP2_F_RX_CTRL1, 249 | - ASP2_F_RX_CTRL2, 250 | - ASP2_G_RX_CTRL1, 251 | - ASP2_G_RX_CTRL2, 252 | - ASP2_H_RX_CTRL1, 253 | - ASP2_H_RX_CTRL2, 254 | - CS8409_I2C_ADDR, 255 | - CS8409_I2C_DATA, 256 | - CS8409_I2C_CTRL, 257 | - CS8409_I2C_STS, 258 | - CS8409_I2C_QWRITE, 259 | - CS8409_I2C_QREAD, 260 | - CS8409_SPI_CTRL, 261 | - CS8409_SPI_TX_DATA, 262 | - CS8409_SPI_RX_DATA, 263 | - CS8409_SPI_STS, 264 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 265 | - CS8409_PFE_COEF_W2, 266 | - CS8409_PFE_CTRL1, 267 | - CS8409_PFE_CTRL2, 268 | - CS8409_PRE_SCALE_ATTN1, 269 | - CS8409_PRE_SCALE_ATTN2, 270 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 271 | - CS8409_PFE_COEF_MON2, 272 | - CS8409_ASP1_INTRN_STS, 273 | - CS8409_ASP2_INTRN_STS, 274 | - CS8409_ASP1_RX_SCLK_COUNT, 275 | - CS8409_ASP1_TX_SCLK_COUNT, 276 | - CS8409_ASP2_RX_SCLK_COUNT, 277 | - CS8409_ASP2_TX_SCLK_COUNT, 278 | - CS8409_ASP_UNS_RESP_MASK, 279 | + CS8409_DEV_CFG1, // reg 0x00 280 | + CS8409_DEV_CFG2, // reg 0x01 281 | + CS8409_DEV_CFG3, // reg 0x02 282 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 283 | + CS8409_ASP1_CLK_CTRL2, // reg 0x04 284 | + CS8409_ASP1_CLK_CTRL3, // reg 0x05 285 | + CS8409_ASP2_CLK_CTRL1, // reg 0x06 286 | + CS8409_ASP2_CLK_CTRL2, // reg 0x07 287 | + CS8409_ASP2_CLK_CTRL3, // reg 0x08 288 | + CS8409_DMIC_CFG, // reg 0x09 289 | + CS8409_BEEP_CFG, // reg 0x0a 290 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 291 | + ASP1_Rx_RATE1, // reg 0x0c 292 | + ASP1_Rx_RATE2, // reg 0x0d 293 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 294 | + ASP1_Tx_RATE1, // reg 0x0f 295 | + ASP1_Tx_RATE2, // reg 0x10 296 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 297 | + ASP2_Rx_RATE1, // reg 0x12 298 | + ASP2_Rx_RATE2, // reg 0x13 299 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 300 | + ASP2_Tx_RATE1, // reg 0x15 301 | + ASP2_Tx_RATE2, // reg 0x16 302 | + ASP1_SYNC_CTRL, // reg 0x17 303 | + ASP2_SYNC_CTRL, // reg 0x18 304 | + ASP1_A_TX_CTRL1, // reg 0x19 305 | + ASP1_A_TX_CTRL2, // reg 0x1a 306 | + ASP1_B_TX_CTRL1, // reg 0x1b 307 | + ASP1_B_TX_CTRL2, // reg 0x1c 308 | + ASP1_C_TX_CTRL1, // reg 0x1d 309 | + ASP1_C_TX_CTRL2, // reg 0x1e 310 | + ASP1_D_TX_CTRL1, // reg 0x1f 311 | + ASP1_D_TX_CTRL2, // reg 0x20 312 | + ASP1_E_TX_CTRL1, // reg 0x21 313 | + ASP1_E_TX_CTRL2, // reg 0x22 314 | + ASP1_F_TX_CTRL1, // reg 0x23 315 | + ASP1_F_TX_CTRL2, // reg 0x24 316 | + ASP1_G_TX_CTRL1, // reg 0x25 317 | + ASP1_G_TX_CTRL2, // reg 0x26 318 | + ASP1_H_TX_CTRL1, // reg 0x27 319 | + ASP1_H_TX_CTRL2, // reg 0x28 320 | + ASP2_A_TX_CTRL1, // reg 0x29 321 | + ASP2_A_TX_CTRL2, // reg 0x2a 322 | + ASP2_B_TX_CTRL1, // reg 0x2b 323 | + ASP2_B_TX_CTRL2, // reg 0x2c 324 | + ASP2_C_TX_CTRL1, // reg 0x2d 325 | + ASP2_C_TX_CTRL2, // reg 0x2e 326 | + ASP2_D_TX_CTRL1, // reg 0x2f 327 | + ASP2_D_TX_CTRL2, // reg 0x30 328 | + ASP2_E_TX_CTRL1, // reg 0x31 329 | + ASP2_E_TX_CTRL2, // reg 0x32 330 | + ASP2_F_TX_CTRL1, // reg 0x33 331 | + ASP2_F_TX_CTRL2, // reg 0x34 332 | + ASP2_G_TX_CTRL1, // reg 0x35 333 | + ASP2_G_TX_CTRL2, // reg 0x36 334 | + ASP2_H_TX_CTRL1, // reg 0x37 335 | + ASP2_H_TX_CTRL2, // reg 0x38 336 | + ASP1_A_RX_CTRL1, // reg 0x39 337 | + ASP1_A_RX_CTRL2, // reg 0x3a 338 | + ASP1_B_RX_CTRL1, // reg 0x3b 339 | + ASP1_B_RX_CTRL2, // reg 0x3c 340 | + ASP1_C_RX_CTRL1, // reg 0x3d 341 | + ASP1_C_RX_CTRL2, // reg 0x3e 342 | + ASP1_D_RX_CTRL1, // reg 0x3f 343 | + ASP1_D_RX_CTRL2, // reg 0x40 344 | + ASP1_E_RX_CTRL1, // reg 0x41 345 | + ASP1_E_RX_CTRL2, // reg 0x42 346 | + ASP1_F_RX_CTRL1, // reg 0x43 347 | + ASP1_F_RX_CTRL2, // reg 0x44 348 | + ASP1_G_RX_CTRL1, // reg 0x45 349 | + ASP1_G_RX_CTRL2, // reg 0x46 350 | + ASP1_H_RX_CTRL1, // reg 0x47 351 | + ASP1_H_RX_CTRL2, // reg 0x48 352 | + ASP2_A_RX_CTRL1, // reg 0x49 353 | + ASP2_A_RX_CTRL2, // reg 0x4a 354 | + ASP2_B_RX_CTRL1, // reg 0x4b 355 | + ASP2_B_RX_CTRL2, // reg 0x4c 356 | + ASP2_C_RX_CTRL1, // reg 0x4d 357 | + ASP2_C_RX_CTRL2, // reg 0x4e 358 | + ASP2_D_RX_CTRL1, // reg 0x4f 359 | + ASP2_D_RX_CTRL2, // reg 0x50 360 | + ASP2_E_RX_CTRL1, // reg 0x51 361 | + ASP2_E_RX_CTRL2, // reg 0x52 362 | + ASP2_F_RX_CTRL1, // reg 0x53 363 | + ASP2_F_RX_CTRL2, // reg 0x54 364 | + ASP2_G_RX_CTRL1, // reg 0x55 365 | + ASP2_G_RX_CTRL2, // reg 0x56 366 | + ASP2_H_RX_CTRL1, // reg 0x57 367 | + ASP2_H_RX_CTRL2, // reg 0x58 368 | + CS8409_I2C_ADDR, // reg 0x59 369 | + CS8409_I2C_DATA, // reg 0x5a 370 | + CS8409_I2C_CTRL, // reg 0x5b 371 | + CS8409_I2C_STS, // reg 0x5c 372 | + CS8409_I2C_QWRITE, // reg 0x5d 373 | + CS8409_I2C_QREAD, // reg 0x5e 374 | + CS8409_SPI_CTRL, // reg 0x5f 375 | + CS8409_SPI_TX_DATA, // reg 0x60 376 | + CS8409_SPI_RX_DATA, // reg 0x61 377 | + CS8409_SPI_STS, // reg 0x62 378 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 379 | + CS8409_PFE_COEF_W2, // reg 0x64 380 | + CS8409_PFE_CTRL1, // reg 0x65 381 | + CS8409_PFE_CTRL2, // reg 0x66 382 | + CS8409_PRE_SCALE_ATTN1, // reg 0x67 383 | + CS8409_PRE_SCALE_ATTN2, // reg 0x68 384 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 385 | + CS8409_PFE_COEF_MON2, // reg 0x6a 386 | + CS8409_ASP1_INTRN_STS, // reg 0x6b 387 | + CS8409_ASP2_INTRN_STS, // reg 0x6c 388 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 389 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 390 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 391 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 392 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x71 393 | CS8409_LOOPBACK_CTRL = 0x80, 394 | - CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 395 | + CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 396 | }; 397 | 398 | /* CS42L42 Specific Definitions */ 399 | @@ -296,6 +302,23 @@ 400 | unsigned int coeff; 401 | }; 402 | 403 | + 404 | +#ifdef APPLE_CODECS 405 | +struct unsol_item { 406 | + struct list_head list; 407 | + unsigned int idx; 408 | + unsigned int res; 409 | +}; 410 | +struct hda_cvt_setup_apple { 411 | + hda_nid_t nid; 412 | + u8 stream_tag; 413 | + u8 channel_id; 414 | + u16 format_id; 415 | + unsigned char active; /* cvt is currently used */ 416 | + unsigned char dirty; /* setups should be cleared */ 417 | +}; 418 | +#endif 419 | + 420 | struct sub_codec { 421 | struct hda_codec *codec; 422 | unsigned int addr; 423 | @@ -306,6 +329,9 @@ 424 | 425 | unsigned int hp_jack_in:1; 426 | unsigned int mic_jack_in:1; 427 | +#ifdef APPLE_CODECS 428 | + unsigned int linein_jack_in:1; 429 | +#endif 430 | unsigned int suspended:1; 431 | unsigned int paged:1; 432 | unsigned int last_page; 433 | @@ -339,6 +365,129 @@ 434 | unsigned int init_done:1; 435 | unsigned int build_ctrl_done:1; 436 | 437 | +#ifdef APPLE_CODECS 438 | + 439 | + // additional data for Apple 8409 system 440 | + 441 | + unsigned int spdif_detect:1; 442 | + unsigned int spdif_present:1; 443 | + unsigned int sense_b:1; 444 | + hda_nid_t vendor_nid; 445 | + 446 | + /* digital beep */ 447 | + hda_nid_t beep_nid; 448 | + 449 | + /* for MBP SPDIF control */ 450 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 451 | + struct snd_ctl_elem_value *ucontrol); 452 | + 453 | + // so it appears we have "concurrency" in the linux HDA code 454 | + // in that if unsolicited responses occur which perform extensive verbs 455 | + // the hda verbs are intermixed with eg extensive start playback verbs 456 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 457 | + // are logged but the unsolicited verbs occur after the verb block 458 | + // this flag is used to flag such verb blocks and the list will store the 459 | + // responses 460 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 461 | + // we will drop 462 | + // not clear if mutexes would be the way to go 463 | + int block_unsol; 464 | + struct list_head unsol_list; 465 | + struct unsol_item unsol_items_prealloc[10]; 466 | + int unsol_items_prealloc_used[10]; 467 | + 468 | + // add in specific nids for the intmike and linein as they seem to swap 469 | + // between macbook pros (14,3) and imacs (18,3) 470 | + int intmike_nid; 471 | + int linein_nid; 472 | + int intmike_adc_nid; 473 | + int linein_amp_nid; 474 | + 475 | + // the following flag bits also need swapping 476 | + int reg9_intmike_dmic_mo; 477 | + int reg9_linein_dmic_mo; 478 | + int reg82_intmike_dmic_scl; 479 | + int reg82_linein_dmic_scl; 480 | + 481 | + 482 | + // add explicit stream format store entries as per hda_codec using a local definition 483 | + // of hda_cvt_setup (which is local to hda_codec.c) 484 | + // also use explicit nid versions 485 | + // (except that means either need explicit functions for each nid or have to lookup 486 | + // nid each time want to use in a generic function with nid argument) 487 | + struct hda_cvt_setup_apple nid_0x02; 488 | + struct hda_cvt_setup_apple nid_0x03; 489 | + struct hda_cvt_setup_apple nid_0x0a; 490 | + struct hda_cvt_setup_apple nid_0x22; 491 | + struct hda_cvt_setup_apple nid_0x23; 492 | + struct hda_cvt_setup_apple nid_0x1a; 493 | + 494 | + 495 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 496 | + // the HDA spec by using a separate headphone chip 497 | + int jack_present; 498 | + 499 | + // save the type of headphone connected 500 | + int headset_type; 501 | + 502 | + // if headphone has mike or not 503 | + int have_mike; 504 | + 505 | + // if headphone has buttons or not 506 | + int have_buttons; 507 | + 508 | + // current stream channel count 509 | + int stream_channels; 510 | + 511 | + // set when playing for plug/unplug events while playing 512 | + int playing; 513 | + 514 | + // set when capturing for plug/unplug events while capturing 515 | + int capturing; 516 | + 517 | + // changing coding - OSX sets up the format on plugin 518 | + // then does some minimal setup when start play 519 | + // initial coding delayed any format setup till actually play 520 | + // this works for no mike but not for mike - we need to initialize 521 | + // the mike on plugin 522 | + // this flag will be set when we have done the format setup 523 | + // so know if need to do it on play or not 524 | + // now need 2 flags - one for play and one for capture 525 | + int headset_play_format_setup_needed; 526 | + int headset_capture_format_setup_needed; 527 | + 528 | + int headset_presetup_done; 529 | + 530 | + 531 | + int use_data; 532 | + 533 | + 534 | + // this is new item for dealing with headset plugins 535 | + // so can distinguish which phase we are in if have multiple interrupts 536 | + // not really used now have analyzed interrupts properly 537 | + int headset_phase; 538 | + 539 | + // another dirty hack item to manage the different headset enable codes 540 | + int headset_enable; 541 | + 542 | + int play_init; 543 | + int capture_init; 544 | + 545 | + int play_init_count; 546 | + int capture_init_count; 547 | + 548 | + 549 | + // new item to limit times we redo unmute/play 550 | + struct timespec64 last_play_time; 551 | + // record the first play time - we have a problem there 552 | + // some initial plays that I dont understand - so skip any setup 553 | + // till sometime after the first play 554 | + struct timespec64 first_play_time; 555 | + 556 | + 557 | +#endif 558 | + 559 | + 560 | /* verb exec op override */ 561 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 562 | unsigned int *res); 563 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | 283 | How to Apply These Terms to Your New Programs 284 | 285 | If you develop a new program, and you want it to be of the greatest 286 | possible use to the public, the best way to achieve this is to make it 287 | free software which everyone can redistribute and change under these terms. 288 | 289 | To do so, attach the following notices to the program. It is safest 290 | to attach them to the start of each source file to most effectively 291 | convey the exclusion of warranty; and each file should have at least 292 | the "copyright" line and a pointer to where the full notice is found. 293 | 294 | 295 | Copyright (C) 19yy 296 | 297 | This program is free software; you can redistribute it and/or modify 298 | it under the terms of the GNU General Public License as published by 299 | the Free Software Foundation; either version 2 of the License, or 300 | (at your option) any later version. 301 | 302 | This program is distributed in the hope that it will be useful, 303 | but WITHOUT ANY WARRANTY; without even the implied warranty of 304 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 305 | GNU General Public License for more details. 306 | 307 | You should have received a copy of the GNU General Public License 308 | along with this program; if not, write to the Free Software 309 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 310 | 311 | 312 | Also add information on how to contact you by electronic and paper mail. 313 | 314 | If the program is interactive, make it output a short notice like this 315 | when it starts in an interactive mode: 316 | 317 | Gnomovision version 69, Copyright (C) 19yy name of author 318 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 319 | This is free software, and you are welcome to redistribute it 320 | under certain conditions; type `show c' for details. 321 | 322 | The hypothetical commands `show w' and `show c' should show the appropriate 323 | parts of the General Public License. Of course, the commands you use may 324 | be called something other than `show w' and `show c'; they could even be 325 | mouse-clicks or menu items--whatever suits your program. 326 | 327 | You should also get your employer (if you work as a programmer) or your 328 | school, if any, to sign a "copyright disclaimer" for the program, if 329 | necessary. Here is a sample; alter the names: 330 | 331 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 332 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 333 | 334 | , 1 April 1989 335 | Ty Coon, President of Vice 336 | 337 | This General Public License does not permit incorporating your program into 338 | proprietary programs. If your program is a subroutine library, you may 339 | consider it more useful to permit linking proprietary applications with the 340 | library. If this is what you want to do, use the GNU Library General 341 | Public License instead of this License. 342 | -------------------------------------------------------------------------------- /patches/patch_patch_cs8409.h.main.pre519.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.h b/patch_cirrus/patch_cs8409.h 2 | index d0b725c..d8b5232 100644 3 | --- a/kernel_sources/patch_cs8409.h 4 | +++ b/patch_cirrus/patch_cs8409.h 5 | @@ -18,200 +18,206 @@ 6 | #include "hda_jack.h" 7 | #include "hda_generic.h" 8 | 9 | +//#ifdef APPLE_CODECS 10 | +//#include 11 | +//#include 12 | +//#include 13 | +//#endif 14 | + 15 | /* CS8409 Specific Definitions */ 16 | 17 | enum cs8409_pins { 18 | - CS8409_PIN_ROOT, 19 | - CS8409_PIN_AFG, 20 | - CS8409_PIN_ASP1_OUT_A, 21 | - CS8409_PIN_ASP1_OUT_B, 22 | - CS8409_PIN_ASP1_OUT_C, 23 | - CS8409_PIN_ASP1_OUT_D, 24 | - CS8409_PIN_ASP1_OUT_E, 25 | - CS8409_PIN_ASP1_OUT_F, 26 | - CS8409_PIN_ASP1_OUT_G, 27 | - CS8409_PIN_ASP1_OUT_H, 28 | - CS8409_PIN_ASP2_OUT_A, 29 | - CS8409_PIN_ASP2_OUT_B, 30 | - CS8409_PIN_ASP2_OUT_C, 31 | - CS8409_PIN_ASP2_OUT_D, 32 | - CS8409_PIN_ASP2_OUT_E, 33 | - CS8409_PIN_ASP2_OUT_F, 34 | - CS8409_PIN_ASP2_OUT_G, 35 | - CS8409_PIN_ASP2_OUT_H, 36 | - CS8409_PIN_ASP1_IN_A, 37 | - CS8409_PIN_ASP1_IN_B, 38 | - CS8409_PIN_ASP1_IN_C, 39 | - CS8409_PIN_ASP1_IN_D, 40 | - CS8409_PIN_ASP1_IN_E, 41 | - CS8409_PIN_ASP1_IN_F, 42 | - CS8409_PIN_ASP1_IN_G, 43 | - CS8409_PIN_ASP1_IN_H, 44 | - CS8409_PIN_ASP2_IN_A, 45 | - CS8409_PIN_ASP2_IN_B, 46 | - CS8409_PIN_ASP2_IN_C, 47 | - CS8409_PIN_ASP2_IN_D, 48 | - CS8409_PIN_ASP2_IN_E, 49 | - CS8409_PIN_ASP2_IN_F, 50 | - CS8409_PIN_ASP2_IN_G, 51 | - CS8409_PIN_ASP2_IN_H, 52 | - CS8409_PIN_DMIC1, 53 | - CS8409_PIN_DMIC2, 54 | - CS8409_PIN_ASP1_TRANSMITTER_A, 55 | - CS8409_PIN_ASP1_TRANSMITTER_B, 56 | - CS8409_PIN_ASP1_TRANSMITTER_C, 57 | - CS8409_PIN_ASP1_TRANSMITTER_D, 58 | - CS8409_PIN_ASP1_TRANSMITTER_E, 59 | - CS8409_PIN_ASP1_TRANSMITTER_F, 60 | - CS8409_PIN_ASP1_TRANSMITTER_G, 61 | - CS8409_PIN_ASP1_TRANSMITTER_H, 62 | - CS8409_PIN_ASP2_TRANSMITTER_A, 63 | - CS8409_PIN_ASP2_TRANSMITTER_B, 64 | - CS8409_PIN_ASP2_TRANSMITTER_C, 65 | - CS8409_PIN_ASP2_TRANSMITTER_D, 66 | - CS8409_PIN_ASP2_TRANSMITTER_E, 67 | - CS8409_PIN_ASP2_TRANSMITTER_F, 68 | - CS8409_PIN_ASP2_TRANSMITTER_G, 69 | - CS8409_PIN_ASP2_TRANSMITTER_H, 70 | - CS8409_PIN_ASP1_RECEIVER_A, 71 | - CS8409_PIN_ASP1_RECEIVER_B, 72 | - CS8409_PIN_ASP1_RECEIVER_C, 73 | - CS8409_PIN_ASP1_RECEIVER_D, 74 | - CS8409_PIN_ASP1_RECEIVER_E, 75 | - CS8409_PIN_ASP1_RECEIVER_F, 76 | - CS8409_PIN_ASP1_RECEIVER_G, 77 | - CS8409_PIN_ASP1_RECEIVER_H, 78 | - CS8409_PIN_ASP2_RECEIVER_A, 79 | - CS8409_PIN_ASP2_RECEIVER_B, 80 | - CS8409_PIN_ASP2_RECEIVER_C, 81 | - CS8409_PIN_ASP2_RECEIVER_D, 82 | - CS8409_PIN_ASP2_RECEIVER_E, 83 | - CS8409_PIN_ASP2_RECEIVER_F, 84 | - CS8409_PIN_ASP2_RECEIVER_G, 85 | - CS8409_PIN_ASP2_RECEIVER_H, 86 | - CS8409_PIN_DMIC1_IN, 87 | - CS8409_PIN_DMIC2_IN, 88 | - CS8409_PIN_BEEP_GEN, 89 | - CS8409_PIN_VENDOR_WIDGET 90 | + CS8409_PIN_ROOT, // nid 0x00 91 | + CS8409_PIN_AFG, // nid 0x01 92 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 93 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 94 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 95 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_E, // nid 0x06 97 | + CS8409_PIN_ASP1_OUT_F, // nid 0x07 98 | + CS8409_PIN_ASP1_OUT_G, // nid 0x08 99 | + CS8409_PIN_ASP1_OUT_H, // nid 0x09 100 | + CS8409_PIN_ASP2_OUT_A, // nid 0x0a 101 | + CS8409_PIN_ASP2_OUT_B, // nid 0x0b 102 | + CS8409_PIN_ASP2_OUT_C, // nid 0x0c 103 | + CS8409_PIN_ASP2_OUT_D, // nid 0x0d 104 | + CS8409_PIN_ASP2_OUT_E, // nid 0x0e 105 | + CS8409_PIN_ASP2_OUT_F, // nid 0x0f 106 | + CS8409_PIN_ASP2_OUT_G, // nid 0x10 107 | + CS8409_PIN_ASP2_OUT_H, // nid 0x11 108 | + CS8409_PIN_ASP1_IN_A, // nid 0x12 109 | + CS8409_PIN_ASP1_IN_B, // nid 0x13 110 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 111 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_E, // nid 0x16 113 | + CS8409_PIN_ASP1_IN_F, // nid 0x17 114 | + CS8409_PIN_ASP1_IN_G, // nid 0x18 115 | + CS8409_PIN_ASP1_IN_H, // nid 0x19 116 | + CS8409_PIN_ASP2_IN_A, // nid 0x1a 117 | + CS8409_PIN_ASP2_IN_B, // nid 0x1b 118 | + CS8409_PIN_ASP2_IN_C, // nid 0x1c 119 | + CS8409_PIN_ASP2_IN_D, // nid 0x1d 120 | + CS8409_PIN_ASP2_IN_E, // nid 0x1e 121 | + CS8409_PIN_ASP2_IN_F, // nid 0x1f 122 | + CS8409_PIN_ASP2_IN_G, // nid 0x20 123 | + CS8409_PIN_ASP2_IN_H, // nid 0x21 124 | + CS8409_PIN_DMIC1, // nid 0x22 125 | + CS8409_PIN_DMIC2, // nid 0x23 126 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 127 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 129 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 130 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 131 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 132 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 133 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 134 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 135 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 136 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 137 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 138 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 139 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 140 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 141 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 142 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 144 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 145 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 146 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 147 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 148 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 149 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 150 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 151 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 152 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 153 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 154 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 155 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 156 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 157 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 158 | + CS8409_PIN_DMIC1_IN, // nid 0x44 159 | + CS8409_PIN_DMIC2_IN, // nid 0x45 160 | + CS8409_PIN_BEEP_GEN, // nid 0x46 161 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 162 | }; 163 | 164 | enum cs8409_coefficient_index_registers { 165 | - CS8409_DEV_CFG1, 166 | - CS8409_DEV_CFG2, 167 | - CS8409_DEV_CFG3, 168 | - CS8409_ASP1_CLK_CTRL1, 169 | - CS8409_ASP1_CLK_CTRL2, 170 | - CS8409_ASP1_CLK_CTRL3, 171 | - CS8409_ASP2_CLK_CTRL1, 172 | - CS8409_ASP2_CLK_CTRL2, 173 | - CS8409_ASP2_CLK_CTRL3, 174 | - CS8409_DMIC_CFG, 175 | - CS8409_BEEP_CFG, 176 | - ASP1_RX_NULL_INS_RMV, 177 | - ASP1_Rx_RATE1, 178 | - ASP1_Rx_RATE2, 179 | - ASP1_Tx_NULL_INS_RMV, 180 | - ASP1_Tx_RATE1, 181 | - ASP1_Tx_RATE2, 182 | - ASP2_Rx_NULL_INS_RMV, 183 | - ASP2_Rx_RATE1, 184 | - ASP2_Rx_RATE2, 185 | - ASP2_Tx_NULL_INS_RMV, 186 | - ASP2_Tx_RATE1, 187 | - ASP2_Tx_RATE2, 188 | - ASP1_SYNC_CTRL, 189 | - ASP2_SYNC_CTRL, 190 | - ASP1_A_TX_CTRL1, 191 | - ASP1_A_TX_CTRL2, 192 | - ASP1_B_TX_CTRL1, 193 | - ASP1_B_TX_CTRL2, 194 | - ASP1_C_TX_CTRL1, 195 | - ASP1_C_TX_CTRL2, 196 | - ASP1_D_TX_CTRL1, 197 | - ASP1_D_TX_CTRL2, 198 | - ASP1_E_TX_CTRL1, 199 | - ASP1_E_TX_CTRL2, 200 | - ASP1_F_TX_CTRL1, 201 | - ASP1_F_TX_CTRL2, 202 | - ASP1_G_TX_CTRL1, 203 | - ASP1_G_TX_CTRL2, 204 | - ASP1_H_TX_CTRL1, 205 | - ASP1_H_TX_CTRL2, 206 | - ASP2_A_TX_CTRL1, 207 | - ASP2_A_TX_CTRL2, 208 | - ASP2_B_TX_CTRL1, 209 | - ASP2_B_TX_CTRL2, 210 | - ASP2_C_TX_CTRL1, 211 | - ASP2_C_TX_CTRL2, 212 | - ASP2_D_TX_CTRL1, 213 | - ASP2_D_TX_CTRL2, 214 | - ASP2_E_TX_CTRL1, 215 | - ASP2_E_TX_CTRL2, 216 | - ASP2_F_TX_CTRL1, 217 | - ASP2_F_TX_CTRL2, 218 | - ASP2_G_TX_CTRL1, 219 | - ASP2_G_TX_CTRL2, 220 | - ASP2_H_TX_CTRL1, 221 | - ASP2_H_TX_CTRL2, 222 | - ASP1_A_RX_CTRL1, 223 | - ASP1_A_RX_CTRL2, 224 | - ASP1_B_RX_CTRL1, 225 | - ASP1_B_RX_CTRL2, 226 | - ASP1_C_RX_CTRL1, 227 | - ASP1_C_RX_CTRL2, 228 | - ASP1_D_RX_CTRL1, 229 | - ASP1_D_RX_CTRL2, 230 | - ASP1_E_RX_CTRL1, 231 | - ASP1_E_RX_CTRL2, 232 | - ASP1_F_RX_CTRL1, 233 | - ASP1_F_RX_CTRL2, 234 | - ASP1_G_RX_CTRL1, 235 | - ASP1_G_RX_CTRL2, 236 | - ASP1_H_RX_CTRL1, 237 | - ASP1_H_RX_CTRL2, 238 | - ASP2_A_RX_CTRL1, 239 | - ASP2_A_RX_CTRL2, 240 | - ASP2_B_RX_CTRL1, 241 | - ASP2_B_RX_CTRL2, 242 | - ASP2_C_RX_CTRL1, 243 | - ASP2_C_RX_CTRL2, 244 | - ASP2_D_RX_CTRL1, 245 | - ASP2_D_RX_CTRL2, 246 | - ASP2_E_RX_CTRL1, 247 | - ASP2_E_RX_CTRL2, 248 | - ASP2_F_RX_CTRL1, 249 | - ASP2_F_RX_CTRL2, 250 | - ASP2_G_RX_CTRL1, 251 | - ASP2_G_RX_CTRL2, 252 | - ASP2_H_RX_CTRL1, 253 | - ASP2_H_RX_CTRL2, 254 | - CS8409_I2C_ADDR, 255 | - CS8409_I2C_DATA, 256 | - CS8409_I2C_CTRL, 257 | - CS8409_I2C_STS, 258 | - CS8409_I2C_QWRITE, 259 | - CS8409_I2C_QREAD, 260 | - CS8409_SPI_CTRL, 261 | - CS8409_SPI_TX_DATA, 262 | - CS8409_SPI_RX_DATA, 263 | - CS8409_SPI_STS, 264 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 265 | - CS8409_PFE_COEF_W2, 266 | - CS8409_PFE_CTRL1, 267 | - CS8409_PFE_CTRL2, 268 | - CS8409_PRE_SCALE_ATTN1, 269 | - CS8409_PRE_SCALE_ATTN2, 270 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 271 | - CS8409_PFE_COEF_MON2, 272 | - CS8409_ASP1_INTRN_STS, 273 | - CS8409_ASP2_INTRN_STS, 274 | - CS8409_ASP1_RX_SCLK_COUNT, 275 | - CS8409_ASP1_TX_SCLK_COUNT, 276 | - CS8409_ASP2_RX_SCLK_COUNT, 277 | - CS8409_ASP2_TX_SCLK_COUNT, 278 | - CS8409_ASP_UNS_RESP_MASK, 279 | + CS8409_DEV_CFG1, // reg 0x00 280 | + CS8409_DEV_CFG2, // reg 0x01 281 | + CS8409_DEV_CFG3, // reg 0x02 282 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 283 | + CS8409_ASP1_CLK_CTRL2, // reg 0x04 284 | + CS8409_ASP1_CLK_CTRL3, // reg 0x05 285 | + CS8409_ASP2_CLK_CTRL1, // reg 0x06 286 | + CS8409_ASP2_CLK_CTRL2, // reg 0x07 287 | + CS8409_ASP2_CLK_CTRL3, // reg 0x08 288 | + CS8409_DMIC_CFG, // reg 0x09 289 | + CS8409_BEEP_CFG, // reg 0x0a 290 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 291 | + ASP1_Rx_RATE1, // reg 0x0c 292 | + ASP1_Rx_RATE2, // reg 0x0d 293 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 294 | + ASP1_Tx_RATE1, // reg 0x0f 295 | + ASP1_Tx_RATE2, // reg 0x10 296 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 297 | + ASP2_Rx_RATE1, // reg 0x12 298 | + ASP2_Rx_RATE2, // reg 0x13 299 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 300 | + ASP2_Tx_RATE1, // reg 0x15 301 | + ASP2_Tx_RATE2, // reg 0x16 302 | + ASP1_SYNC_CTRL, // reg 0x17 303 | + ASP2_SYNC_CTRL, // reg 0x18 304 | + ASP1_A_TX_CTRL1, // reg 0x19 305 | + ASP1_A_TX_CTRL2, // reg 0x1a 306 | + ASP1_B_TX_CTRL1, // reg 0x1b 307 | + ASP1_B_TX_CTRL2, // reg 0x1c 308 | + ASP1_C_TX_CTRL1, // reg 0x1d 309 | + ASP1_C_TX_CTRL2, // reg 0x1e 310 | + ASP1_D_TX_CTRL1, // reg 0x1f 311 | + ASP1_D_TX_CTRL2, // reg 0x20 312 | + ASP1_E_TX_CTRL1, // reg 0x21 313 | + ASP1_E_TX_CTRL2, // reg 0x22 314 | + ASP1_F_TX_CTRL1, // reg 0x23 315 | + ASP1_F_TX_CTRL2, // reg 0x24 316 | + ASP1_G_TX_CTRL1, // reg 0x25 317 | + ASP1_G_TX_CTRL2, // reg 0x26 318 | + ASP1_H_TX_CTRL1, // reg 0x27 319 | + ASP1_H_TX_CTRL2, // reg 0x28 320 | + ASP2_A_TX_CTRL1, // reg 0x29 321 | + ASP2_A_TX_CTRL2, // reg 0x2a 322 | + ASP2_B_TX_CTRL1, // reg 0x2b 323 | + ASP2_B_TX_CTRL2, // reg 0x2c 324 | + ASP2_C_TX_CTRL1, // reg 0x2d 325 | + ASP2_C_TX_CTRL2, // reg 0x2e 326 | + ASP2_D_TX_CTRL1, // reg 0x2f 327 | + ASP2_D_TX_CTRL2, // reg 0x30 328 | + ASP2_E_TX_CTRL1, // reg 0x31 329 | + ASP2_E_TX_CTRL2, // reg 0x32 330 | + ASP2_F_TX_CTRL1, // reg 0x33 331 | + ASP2_F_TX_CTRL2, // reg 0x34 332 | + ASP2_G_TX_CTRL1, // reg 0x35 333 | + ASP2_G_TX_CTRL2, // reg 0x36 334 | + ASP2_H_TX_CTRL1, // reg 0x37 335 | + ASP2_H_TX_CTRL2, // reg 0x38 336 | + ASP1_A_RX_CTRL1, // reg 0x39 337 | + ASP1_A_RX_CTRL2, // reg 0x3a 338 | + ASP1_B_RX_CTRL1, // reg 0x3b 339 | + ASP1_B_RX_CTRL2, // reg 0x3c 340 | + ASP1_C_RX_CTRL1, // reg 0x3d 341 | + ASP1_C_RX_CTRL2, // reg 0x3e 342 | + ASP1_D_RX_CTRL1, // reg 0x3f 343 | + ASP1_D_RX_CTRL2, // reg 0x40 344 | + ASP1_E_RX_CTRL1, // reg 0x41 345 | + ASP1_E_RX_CTRL2, // reg 0x42 346 | + ASP1_F_RX_CTRL1, // reg 0x43 347 | + ASP1_F_RX_CTRL2, // reg 0x44 348 | + ASP1_G_RX_CTRL1, // reg 0x45 349 | + ASP1_G_RX_CTRL2, // reg 0x46 350 | + ASP1_H_RX_CTRL1, // reg 0x47 351 | + ASP1_H_RX_CTRL2, // reg 0x48 352 | + ASP2_A_RX_CTRL1, // reg 0x49 353 | + ASP2_A_RX_CTRL2, // reg 0x4a 354 | + ASP2_B_RX_CTRL1, // reg 0x4b 355 | + ASP2_B_RX_CTRL2, // reg 0x4c 356 | + ASP2_C_RX_CTRL1, // reg 0x4d 357 | + ASP2_C_RX_CTRL2, // reg 0x4e 358 | + ASP2_D_RX_CTRL1, // reg 0x4f 359 | + ASP2_D_RX_CTRL2, // reg 0x50 360 | + ASP2_E_RX_CTRL1, // reg 0x51 361 | + ASP2_E_RX_CTRL2, // reg 0x52 362 | + ASP2_F_RX_CTRL1, // reg 0x53 363 | + ASP2_F_RX_CTRL2, // reg 0x54 364 | + ASP2_G_RX_CTRL1, // reg 0x55 365 | + ASP2_G_RX_CTRL2, // reg 0x56 366 | + ASP2_H_RX_CTRL1, // reg 0x57 367 | + ASP2_H_RX_CTRL2, // reg 0x58 368 | + CS8409_I2C_ADDR, // reg 0x59 369 | + CS8409_I2C_DATA, // reg 0x5a 370 | + CS8409_I2C_CTRL, // reg 0x5b 371 | + CS8409_I2C_STS, // reg 0x5c 372 | + CS8409_I2C_QWRITE, // reg 0x5d 373 | + CS8409_I2C_QREAD, // reg 0x5e 374 | + CS8409_SPI_CTRL, // reg 0x5f 375 | + CS8409_SPI_TX_DATA, // reg 0x60 376 | + CS8409_SPI_RX_DATA, // reg 0x61 377 | + CS8409_SPI_STS, // reg 0x62 378 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 379 | + CS8409_PFE_COEF_W2, // reg 0x64 380 | + CS8409_PFE_CTRL1, // reg 0x65 381 | + CS8409_PFE_CTRL2, // reg 0x66 382 | + CS8409_PRE_SCALE_ATTN1, // reg 0x67 383 | + CS8409_PRE_SCALE_ATTN2, // reg 0x68 384 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 385 | + CS8409_PFE_COEF_MON2, // reg 0x6a 386 | + CS8409_ASP1_INTRN_STS, // reg 0x6b 387 | + CS8409_ASP2_INTRN_STS, // reg 0x6c 388 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 389 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 390 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 391 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 392 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x71 393 | CS8409_LOOPBACK_CTRL = 0x80, 394 | - CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 395 | + CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 396 | }; 397 | 398 | /* CS42L42 Specific Definitions */ 399 | @@ -295,6 +301,23 @@ struct cs8409_cir_param { 400 | unsigned int coeff; 401 | }; 402 | 403 | + 404 | +#ifdef APPLE_CODECS 405 | +struct unsol_item { 406 | + struct list_head list; 407 | + unsigned int idx; 408 | + unsigned int res; 409 | +}; 410 | +struct hda_cvt_setup_apple { 411 | + hda_nid_t nid; 412 | + u8 stream_tag; 413 | + u8 channel_id; 414 | + u16 format_id; 415 | + unsigned char active; /* cvt is currently used */ 416 | + unsigned char dirty; /* setups should be cleared */ 417 | +}; 418 | +#endif 419 | + 420 | struct sub_codec { 421 | struct hda_codec *codec; 422 | unsigned int addr; 423 | @@ -305,6 +328,9 @@ struct sub_codec { 424 | 425 | unsigned int hp_jack_in:1; 426 | unsigned int mic_jack_in:1; 427 | +#ifdef APPLE_CODECS 428 | + unsigned int linein_jack_in:1; 429 | +#endif 430 | unsigned int force_status_change:1; 431 | unsigned int suspended:1; 432 | unsigned int paged:1; 433 | @@ -337,6 +363,126 @@ struct cs8409_spec { 434 | unsigned int init_done:1; 435 | unsigned int build_ctrl_done:1; 436 | 437 | +#ifdef APPLE_CODECS 438 | + 439 | + // additional data for Apple 8409 system 440 | + 441 | + unsigned int spdif_detect:1; 442 | + unsigned int spdif_present:1; 443 | + unsigned int sense_b:1; 444 | + hda_nid_t vendor_nid; 445 | + 446 | + /* digital beep */ 447 | + hda_nid_t beep_nid; 448 | + 449 | + /* for MBP SPDIF control */ 450 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 451 | + struct snd_ctl_elem_value *ucontrol); 452 | + 453 | + // so it appears we have "concurrency" in the linux HDA code 454 | + // in that if unsolicited responses occur which perform extensive verbs 455 | + // the hda verbs are intermixed with eg extensive start playback verbs 456 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 457 | + // are logged but the unsolicited verbs occur after the verb block 458 | + // this flag is used to flag such verb blocks and the list will store the 459 | + // responses 460 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 461 | + // we will drop 462 | + // not clear if mutexes would be the way to go 463 | + int block_unsol; 464 | + struct list_head unsol_list; 465 | + struct unsol_item unsol_items_prealloc[10]; 466 | + int unsol_items_prealloc_used[10]; 467 | + 468 | + // add in specific nids for the intmike and linein as they seem to swap 469 | + // between macbook pros (14,3) and imacs (18,3) 470 | + int intmike_nid; 471 | + int linein_nid; 472 | + int intmike_adc_nid; 473 | + int linein_amp_nid; 474 | + 475 | + // the following flag bits also need swapping 476 | + int reg9_intmike_dmic_mo; 477 | + int reg9_linein_dmic_mo; 478 | + int reg82_intmike_dmic_scl; 479 | + int reg82_linein_dmic_scl; 480 | + 481 | + 482 | + // add explicit stream format store entries as per hda_codec using a local definition 483 | + // of hda_cvt_setup (which is local to hda_codec.c) 484 | + // also use explicit nid versions 485 | + // (except that means either need explicit functions for each nid or have to lookup 486 | + // nid each time want to use in a generic function with nid argument) 487 | + struct hda_cvt_setup_apple nid_0x02; 488 | + struct hda_cvt_setup_apple nid_0x03; 489 | + struct hda_cvt_setup_apple nid_0x0a; 490 | + struct hda_cvt_setup_apple nid_0x22; 491 | + struct hda_cvt_setup_apple nid_0x23; 492 | + struct hda_cvt_setup_apple nid_0x1a; 493 | + 494 | + 495 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 496 | + // the HDA spec by using a separate headphone chip 497 | + int jack_present; 498 | + 499 | + // save the type of headphone connected 500 | + int headset_type; 501 | + 502 | + // if headphone has mike or not 503 | + int have_mike; 504 | + 505 | + // if headphone has buttons or not 506 | + int have_buttons; 507 | + 508 | + // current stream channel count 509 | + int stream_channels; 510 | + 511 | + // set when playing for plug/unplug events while playing 512 | + int playing; 513 | + 514 | + // set when capturing for plug/unplug events while capturing 515 | + int capturing; 516 | + 517 | + // changing coding - OSX sets up the format on plugin 518 | + // then does some minimal setup when start play 519 | + // initial coding delayed any format setup till actually play 520 | + // this works for no mike but not for mike - we need to initialize 521 | + // the mike on plugin 522 | + // this flag will be set when we have done the format setup 523 | + // so know if need to do it on play or not 524 | + // now need 2 flags - one for play and one for capture 525 | + int headset_play_format_setup_needed; 526 | + int headset_capture_format_setup_needed; 527 | + 528 | + int headset_presetup_done; 529 | + 530 | + 531 | + int use_data; 532 | + 533 | + 534 | + // this is new item for dealing with headset plugins 535 | + // so can distinguish which phase we are in if have multiple interrupts 536 | + // not really used now have analyzed interrupts properly 537 | + int headset_phase; 538 | + 539 | + // another dirty hack item to manage the different headset enable codes 540 | + int headset_enable; 541 | + 542 | + int play_init; 543 | + int capture_init; 544 | + 545 | + 546 | + // new item to limit times we redo unmute/play 547 | + struct timespec64 last_play_time; 548 | + // record the first play time - we have a problem there 549 | + // some initial plays that I dont understand - so skip any setup 550 | + // till sometime after the first play 551 | + struct timespec64 first_play_time; 552 | + 553 | + 554 | +#endif 555 | + 556 | + 557 | /* verb exec op override */ 558 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 559 | unsigned int *res); 560 | -------------------------------------------------------------------------------- /patches/patch_patch_cs8409.h.ubuntu.pre51547.diff: -------------------------------------------------------------------------------- 1 | diff --git a/kernel_sources/patch_cs8409.h b/patch_cirrus/patch_cs8409.h 2 | index d0b725c..d8b5232 100644 3 | --- a/kernel_sources/patch_cs8409.h 4 | +++ b/patch_cirrus/patch_cs8409.h 5 | @@ -18,200 +18,206 @@ 6 | #include "hda_jack.h" 7 | #include "hda_generic.h" 8 | 9 | +//#ifdef APPLE_CODECS 10 | +//#include 11 | +//#include 12 | +//#include 13 | +//#endif 14 | + 15 | /* CS8409 Specific Definitions */ 16 | 17 | enum cs8409_pins { 18 | - CS8409_PIN_ROOT, 19 | - CS8409_PIN_AFG, 20 | - CS8409_PIN_ASP1_OUT_A, 21 | - CS8409_PIN_ASP1_OUT_B, 22 | - CS8409_PIN_ASP1_OUT_C, 23 | - CS8409_PIN_ASP1_OUT_D, 24 | - CS8409_PIN_ASP1_OUT_E, 25 | - CS8409_PIN_ASP1_OUT_F, 26 | - CS8409_PIN_ASP1_OUT_G, 27 | - CS8409_PIN_ASP1_OUT_H, 28 | - CS8409_PIN_ASP2_OUT_A, 29 | - CS8409_PIN_ASP2_OUT_B, 30 | - CS8409_PIN_ASP2_OUT_C, 31 | - CS8409_PIN_ASP2_OUT_D, 32 | - CS8409_PIN_ASP2_OUT_E, 33 | - CS8409_PIN_ASP2_OUT_F, 34 | - CS8409_PIN_ASP2_OUT_G, 35 | - CS8409_PIN_ASP2_OUT_H, 36 | - CS8409_PIN_ASP1_IN_A, 37 | - CS8409_PIN_ASP1_IN_B, 38 | - CS8409_PIN_ASP1_IN_C, 39 | - CS8409_PIN_ASP1_IN_D, 40 | - CS8409_PIN_ASP1_IN_E, 41 | - CS8409_PIN_ASP1_IN_F, 42 | - CS8409_PIN_ASP1_IN_G, 43 | - CS8409_PIN_ASP1_IN_H, 44 | - CS8409_PIN_ASP2_IN_A, 45 | - CS8409_PIN_ASP2_IN_B, 46 | - CS8409_PIN_ASP2_IN_C, 47 | - CS8409_PIN_ASP2_IN_D, 48 | - CS8409_PIN_ASP2_IN_E, 49 | - CS8409_PIN_ASP2_IN_F, 50 | - CS8409_PIN_ASP2_IN_G, 51 | - CS8409_PIN_ASP2_IN_H, 52 | - CS8409_PIN_DMIC1, 53 | - CS8409_PIN_DMIC2, 54 | - CS8409_PIN_ASP1_TRANSMITTER_A, 55 | - CS8409_PIN_ASP1_TRANSMITTER_B, 56 | - CS8409_PIN_ASP1_TRANSMITTER_C, 57 | - CS8409_PIN_ASP1_TRANSMITTER_D, 58 | - CS8409_PIN_ASP1_TRANSMITTER_E, 59 | - CS8409_PIN_ASP1_TRANSMITTER_F, 60 | - CS8409_PIN_ASP1_TRANSMITTER_G, 61 | - CS8409_PIN_ASP1_TRANSMITTER_H, 62 | - CS8409_PIN_ASP2_TRANSMITTER_A, 63 | - CS8409_PIN_ASP2_TRANSMITTER_B, 64 | - CS8409_PIN_ASP2_TRANSMITTER_C, 65 | - CS8409_PIN_ASP2_TRANSMITTER_D, 66 | - CS8409_PIN_ASP2_TRANSMITTER_E, 67 | - CS8409_PIN_ASP2_TRANSMITTER_F, 68 | - CS8409_PIN_ASP2_TRANSMITTER_G, 69 | - CS8409_PIN_ASP2_TRANSMITTER_H, 70 | - CS8409_PIN_ASP1_RECEIVER_A, 71 | - CS8409_PIN_ASP1_RECEIVER_B, 72 | - CS8409_PIN_ASP1_RECEIVER_C, 73 | - CS8409_PIN_ASP1_RECEIVER_D, 74 | - CS8409_PIN_ASP1_RECEIVER_E, 75 | - CS8409_PIN_ASP1_RECEIVER_F, 76 | - CS8409_PIN_ASP1_RECEIVER_G, 77 | - CS8409_PIN_ASP1_RECEIVER_H, 78 | - CS8409_PIN_ASP2_RECEIVER_A, 79 | - CS8409_PIN_ASP2_RECEIVER_B, 80 | - CS8409_PIN_ASP2_RECEIVER_C, 81 | - CS8409_PIN_ASP2_RECEIVER_D, 82 | - CS8409_PIN_ASP2_RECEIVER_E, 83 | - CS8409_PIN_ASP2_RECEIVER_F, 84 | - CS8409_PIN_ASP2_RECEIVER_G, 85 | - CS8409_PIN_ASP2_RECEIVER_H, 86 | - CS8409_PIN_DMIC1_IN, 87 | - CS8409_PIN_DMIC2_IN, 88 | - CS8409_PIN_BEEP_GEN, 89 | - CS8409_PIN_VENDOR_WIDGET 90 | + CS8409_PIN_ROOT, // nid 0x00 91 | + CS8409_PIN_AFG, // nid 0x01 92 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 93 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 94 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 95 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_E, // nid 0x06 97 | + CS8409_PIN_ASP1_OUT_F, // nid 0x07 98 | + CS8409_PIN_ASP1_OUT_G, // nid 0x08 99 | + CS8409_PIN_ASP1_OUT_H, // nid 0x09 100 | + CS8409_PIN_ASP2_OUT_A, // nid 0x0a 101 | + CS8409_PIN_ASP2_OUT_B, // nid 0x0b 102 | + CS8409_PIN_ASP2_OUT_C, // nid 0x0c 103 | + CS8409_PIN_ASP2_OUT_D, // nid 0x0d 104 | + CS8409_PIN_ASP2_OUT_E, // nid 0x0e 105 | + CS8409_PIN_ASP2_OUT_F, // nid 0x0f 106 | + CS8409_PIN_ASP2_OUT_G, // nid 0x10 107 | + CS8409_PIN_ASP2_OUT_H, // nid 0x11 108 | + CS8409_PIN_ASP1_IN_A, // nid 0x12 109 | + CS8409_PIN_ASP1_IN_B, // nid 0x13 110 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 111 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_E, // nid 0x16 113 | + CS8409_PIN_ASP1_IN_F, // nid 0x17 114 | + CS8409_PIN_ASP1_IN_G, // nid 0x18 115 | + CS8409_PIN_ASP1_IN_H, // nid 0x19 116 | + CS8409_PIN_ASP2_IN_A, // nid 0x1a 117 | + CS8409_PIN_ASP2_IN_B, // nid 0x1b 118 | + CS8409_PIN_ASP2_IN_C, // nid 0x1c 119 | + CS8409_PIN_ASP2_IN_D, // nid 0x1d 120 | + CS8409_PIN_ASP2_IN_E, // nid 0x1e 121 | + CS8409_PIN_ASP2_IN_F, // nid 0x1f 122 | + CS8409_PIN_ASP2_IN_G, // nid 0x20 123 | + CS8409_PIN_ASP2_IN_H, // nid 0x21 124 | + CS8409_PIN_DMIC1, // nid 0x22 125 | + CS8409_PIN_DMIC2, // nid 0x23 126 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 127 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x26 129 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x27 130 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x28 131 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x29 132 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x2a 133 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x2b 134 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x2c 135 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x2d 136 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x2e 137 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x2f 138 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x30 139 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x31 140 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x32 141 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x33 142 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x35 144 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x36 145 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x37 146 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x38 147 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x39 148 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x3a 149 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x3b 150 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x3c 151 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x3d 152 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x3e 153 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x3f 154 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x40 155 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x41 156 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x42 157 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x43 158 | + CS8409_PIN_DMIC1_IN, // nid 0x44 159 | + CS8409_PIN_DMIC2_IN, // nid 0x45 160 | + CS8409_PIN_BEEP_GEN, // nid 0x46 161 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 162 | }; 163 | 164 | enum cs8409_coefficient_index_registers { 165 | - CS8409_DEV_CFG1, 166 | - CS8409_DEV_CFG2, 167 | - CS8409_DEV_CFG3, 168 | - CS8409_ASP1_CLK_CTRL1, 169 | - CS8409_ASP1_CLK_CTRL2, 170 | - CS8409_ASP1_CLK_CTRL3, 171 | - CS8409_ASP2_CLK_CTRL1, 172 | - CS8409_ASP2_CLK_CTRL2, 173 | - CS8409_ASP2_CLK_CTRL3, 174 | - CS8409_DMIC_CFG, 175 | - CS8409_BEEP_CFG, 176 | - ASP1_RX_NULL_INS_RMV, 177 | - ASP1_Rx_RATE1, 178 | - ASP1_Rx_RATE2, 179 | - ASP1_Tx_NULL_INS_RMV, 180 | - ASP1_Tx_RATE1, 181 | - ASP1_Tx_RATE2, 182 | - ASP2_Rx_NULL_INS_RMV, 183 | - ASP2_Rx_RATE1, 184 | - ASP2_Rx_RATE2, 185 | - ASP2_Tx_NULL_INS_RMV, 186 | - ASP2_Tx_RATE1, 187 | - ASP2_Tx_RATE2, 188 | - ASP1_SYNC_CTRL, 189 | - ASP2_SYNC_CTRL, 190 | - ASP1_A_TX_CTRL1, 191 | - ASP1_A_TX_CTRL2, 192 | - ASP1_B_TX_CTRL1, 193 | - ASP1_B_TX_CTRL2, 194 | - ASP1_C_TX_CTRL1, 195 | - ASP1_C_TX_CTRL2, 196 | - ASP1_D_TX_CTRL1, 197 | - ASP1_D_TX_CTRL2, 198 | - ASP1_E_TX_CTRL1, 199 | - ASP1_E_TX_CTRL2, 200 | - ASP1_F_TX_CTRL1, 201 | - ASP1_F_TX_CTRL2, 202 | - ASP1_G_TX_CTRL1, 203 | - ASP1_G_TX_CTRL2, 204 | - ASP1_H_TX_CTRL1, 205 | - ASP1_H_TX_CTRL2, 206 | - ASP2_A_TX_CTRL1, 207 | - ASP2_A_TX_CTRL2, 208 | - ASP2_B_TX_CTRL1, 209 | - ASP2_B_TX_CTRL2, 210 | - ASP2_C_TX_CTRL1, 211 | - ASP2_C_TX_CTRL2, 212 | - ASP2_D_TX_CTRL1, 213 | - ASP2_D_TX_CTRL2, 214 | - ASP2_E_TX_CTRL1, 215 | - ASP2_E_TX_CTRL2, 216 | - ASP2_F_TX_CTRL1, 217 | - ASP2_F_TX_CTRL2, 218 | - ASP2_G_TX_CTRL1, 219 | - ASP2_G_TX_CTRL2, 220 | - ASP2_H_TX_CTRL1, 221 | - ASP2_H_TX_CTRL2, 222 | - ASP1_A_RX_CTRL1, 223 | - ASP1_A_RX_CTRL2, 224 | - ASP1_B_RX_CTRL1, 225 | - ASP1_B_RX_CTRL2, 226 | - ASP1_C_RX_CTRL1, 227 | - ASP1_C_RX_CTRL2, 228 | - ASP1_D_RX_CTRL1, 229 | - ASP1_D_RX_CTRL2, 230 | - ASP1_E_RX_CTRL1, 231 | - ASP1_E_RX_CTRL2, 232 | - ASP1_F_RX_CTRL1, 233 | - ASP1_F_RX_CTRL2, 234 | - ASP1_G_RX_CTRL1, 235 | - ASP1_G_RX_CTRL2, 236 | - ASP1_H_RX_CTRL1, 237 | - ASP1_H_RX_CTRL2, 238 | - ASP2_A_RX_CTRL1, 239 | - ASP2_A_RX_CTRL2, 240 | - ASP2_B_RX_CTRL1, 241 | - ASP2_B_RX_CTRL2, 242 | - ASP2_C_RX_CTRL1, 243 | - ASP2_C_RX_CTRL2, 244 | - ASP2_D_RX_CTRL1, 245 | - ASP2_D_RX_CTRL2, 246 | - ASP2_E_RX_CTRL1, 247 | - ASP2_E_RX_CTRL2, 248 | - ASP2_F_RX_CTRL1, 249 | - ASP2_F_RX_CTRL2, 250 | - ASP2_G_RX_CTRL1, 251 | - ASP2_G_RX_CTRL2, 252 | - ASP2_H_RX_CTRL1, 253 | - ASP2_H_RX_CTRL2, 254 | - CS8409_I2C_ADDR, 255 | - CS8409_I2C_DATA, 256 | - CS8409_I2C_CTRL, 257 | - CS8409_I2C_STS, 258 | - CS8409_I2C_QWRITE, 259 | - CS8409_I2C_QREAD, 260 | - CS8409_SPI_CTRL, 261 | - CS8409_SPI_TX_DATA, 262 | - CS8409_SPI_RX_DATA, 263 | - CS8409_SPI_STS, 264 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 265 | - CS8409_PFE_COEF_W2, 266 | - CS8409_PFE_CTRL1, 267 | - CS8409_PFE_CTRL2, 268 | - CS8409_PRE_SCALE_ATTN1, 269 | - CS8409_PRE_SCALE_ATTN2, 270 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 271 | - CS8409_PFE_COEF_MON2, 272 | - CS8409_ASP1_INTRN_STS, 273 | - CS8409_ASP2_INTRN_STS, 274 | - CS8409_ASP1_RX_SCLK_COUNT, 275 | - CS8409_ASP1_TX_SCLK_COUNT, 276 | - CS8409_ASP2_RX_SCLK_COUNT, 277 | - CS8409_ASP2_TX_SCLK_COUNT, 278 | - CS8409_ASP_UNS_RESP_MASK, 279 | + CS8409_DEV_CFG1, // reg 0x00 280 | + CS8409_DEV_CFG2, // reg 0x01 281 | + CS8409_DEV_CFG3, // reg 0x02 282 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 283 | + CS8409_ASP1_CLK_CTRL2, // reg 0x04 284 | + CS8409_ASP1_CLK_CTRL3, // reg 0x05 285 | + CS8409_ASP2_CLK_CTRL1, // reg 0x06 286 | + CS8409_ASP2_CLK_CTRL2, // reg 0x07 287 | + CS8409_ASP2_CLK_CTRL3, // reg 0x08 288 | + CS8409_DMIC_CFG, // reg 0x09 289 | + CS8409_BEEP_CFG, // reg 0x0a 290 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 291 | + ASP1_Rx_RATE1, // reg 0x0c 292 | + ASP1_Rx_RATE2, // reg 0x0d 293 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 294 | + ASP1_Tx_RATE1, // reg 0x0f 295 | + ASP1_Tx_RATE2, // reg 0x10 296 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 297 | + ASP2_Rx_RATE1, // reg 0x12 298 | + ASP2_Rx_RATE2, // reg 0x13 299 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 300 | + ASP2_Tx_RATE1, // reg 0x15 301 | + ASP2_Tx_RATE2, // reg 0x16 302 | + ASP1_SYNC_CTRL, // reg 0x17 303 | + ASP2_SYNC_CTRL, // reg 0x18 304 | + ASP1_A_TX_CTRL1, // reg 0x19 305 | + ASP1_A_TX_CTRL2, // reg 0x1a 306 | + ASP1_B_TX_CTRL1, // reg 0x1b 307 | + ASP1_B_TX_CTRL2, // reg 0x1c 308 | + ASP1_C_TX_CTRL1, // reg 0x1d 309 | + ASP1_C_TX_CTRL2, // reg 0x1e 310 | + ASP1_D_TX_CTRL1, // reg 0x1f 311 | + ASP1_D_TX_CTRL2, // reg 0x20 312 | + ASP1_E_TX_CTRL1, // reg 0x21 313 | + ASP1_E_TX_CTRL2, // reg 0x22 314 | + ASP1_F_TX_CTRL1, // reg 0x23 315 | + ASP1_F_TX_CTRL2, // reg 0x24 316 | + ASP1_G_TX_CTRL1, // reg 0x25 317 | + ASP1_G_TX_CTRL2, // reg 0x26 318 | + ASP1_H_TX_CTRL1, // reg 0x27 319 | + ASP1_H_TX_CTRL2, // reg 0x28 320 | + ASP2_A_TX_CTRL1, // reg 0x29 321 | + ASP2_A_TX_CTRL2, // reg 0x2a 322 | + ASP2_B_TX_CTRL1, // reg 0x2b 323 | + ASP2_B_TX_CTRL2, // reg 0x2c 324 | + ASP2_C_TX_CTRL1, // reg 0x2d 325 | + ASP2_C_TX_CTRL2, // reg 0x2e 326 | + ASP2_D_TX_CTRL1, // reg 0x2f 327 | + ASP2_D_TX_CTRL2, // reg 0x30 328 | + ASP2_E_TX_CTRL1, // reg 0x31 329 | + ASP2_E_TX_CTRL2, // reg 0x32 330 | + ASP2_F_TX_CTRL1, // reg 0x33 331 | + ASP2_F_TX_CTRL2, // reg 0x34 332 | + ASP2_G_TX_CTRL1, // reg 0x35 333 | + ASP2_G_TX_CTRL2, // reg 0x36 334 | + ASP2_H_TX_CTRL1, // reg 0x37 335 | + ASP2_H_TX_CTRL2, // reg 0x38 336 | + ASP1_A_RX_CTRL1, // reg 0x39 337 | + ASP1_A_RX_CTRL2, // reg 0x3a 338 | + ASP1_B_RX_CTRL1, // reg 0x3b 339 | + ASP1_B_RX_CTRL2, // reg 0x3c 340 | + ASP1_C_RX_CTRL1, // reg 0x3d 341 | + ASP1_C_RX_CTRL2, // reg 0x3e 342 | + ASP1_D_RX_CTRL1, // reg 0x3f 343 | + ASP1_D_RX_CTRL2, // reg 0x40 344 | + ASP1_E_RX_CTRL1, // reg 0x41 345 | + ASP1_E_RX_CTRL2, // reg 0x42 346 | + ASP1_F_RX_CTRL1, // reg 0x43 347 | + ASP1_F_RX_CTRL2, // reg 0x44 348 | + ASP1_G_RX_CTRL1, // reg 0x45 349 | + ASP1_G_RX_CTRL2, // reg 0x46 350 | + ASP1_H_RX_CTRL1, // reg 0x47 351 | + ASP1_H_RX_CTRL2, // reg 0x48 352 | + ASP2_A_RX_CTRL1, // reg 0x49 353 | + ASP2_A_RX_CTRL2, // reg 0x4a 354 | + ASP2_B_RX_CTRL1, // reg 0x4b 355 | + ASP2_B_RX_CTRL2, // reg 0x4c 356 | + ASP2_C_RX_CTRL1, // reg 0x4d 357 | + ASP2_C_RX_CTRL2, // reg 0x4e 358 | + ASP2_D_RX_CTRL1, // reg 0x4f 359 | + ASP2_D_RX_CTRL2, // reg 0x50 360 | + ASP2_E_RX_CTRL1, // reg 0x51 361 | + ASP2_E_RX_CTRL2, // reg 0x52 362 | + ASP2_F_RX_CTRL1, // reg 0x53 363 | + ASP2_F_RX_CTRL2, // reg 0x54 364 | + ASP2_G_RX_CTRL1, // reg 0x55 365 | + ASP2_G_RX_CTRL2, // reg 0x56 366 | + ASP2_H_RX_CTRL1, // reg 0x57 367 | + ASP2_H_RX_CTRL2, // reg 0x58 368 | + CS8409_I2C_ADDR, // reg 0x59 369 | + CS8409_I2C_DATA, // reg 0x5a 370 | + CS8409_I2C_CTRL, // reg 0x5b 371 | + CS8409_I2C_STS, // reg 0x5c 372 | + CS8409_I2C_QWRITE, // reg 0x5d 373 | + CS8409_I2C_QREAD, // reg 0x5e 374 | + CS8409_SPI_CTRL, // reg 0x5f 375 | + CS8409_SPI_TX_DATA, // reg 0x60 376 | + CS8409_SPI_RX_DATA, // reg 0x61 377 | + CS8409_SPI_STS, // reg 0x62 378 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 379 | + CS8409_PFE_COEF_W2, // reg 0x64 380 | + CS8409_PFE_CTRL1, // reg 0x65 381 | + CS8409_PFE_CTRL2, // reg 0x66 382 | + CS8409_PRE_SCALE_ATTN1, // reg 0x67 383 | + CS8409_PRE_SCALE_ATTN2, // reg 0x68 384 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 385 | + CS8409_PFE_COEF_MON2, // reg 0x6a 386 | + CS8409_ASP1_INTRN_STS, // reg 0x6b 387 | + CS8409_ASP2_INTRN_STS, // reg 0x6c 388 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6d 389 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6e 390 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6f 391 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x70 392 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x71 393 | CS8409_LOOPBACK_CTRL = 0x80, 394 | - CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 395 | + CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 396 | }; 397 | 398 | /* CS42L42 Specific Definitions */ 399 | @@ -295,6 +301,23 @@ struct cs8409_cir_param { 400 | unsigned int coeff; 401 | }; 402 | 403 | + 404 | +#ifdef APPLE_CODECS 405 | +struct unsol_item { 406 | + struct list_head list; 407 | + unsigned int idx; 408 | + unsigned int res; 409 | +}; 410 | +struct hda_cvt_setup_apple { 411 | + hda_nid_t nid; 412 | + u8 stream_tag; 413 | + u8 channel_id; 414 | + u16 format_id; 415 | + unsigned char active; /* cvt is currently used */ 416 | + unsigned char dirty; /* setups should be cleared */ 417 | +}; 418 | +#endif 419 | + 420 | struct sub_codec { 421 | struct hda_codec *codec; 422 | unsigned int addr; 423 | @@ -305,6 +328,9 @@ struct sub_codec { 424 | 425 | unsigned int hp_jack_in:1; 426 | unsigned int mic_jack_in:1; 427 | +#ifdef APPLE_CODECS 428 | + unsigned int linein_jack_in:1; 429 | +#endif 430 | unsigned int force_status_change:1; 431 | unsigned int suspended:1; 432 | unsigned int paged:1; 433 | @@ -337,6 +363,126 @@ struct cs8409_spec { 434 | unsigned int init_done:1; 435 | unsigned int build_ctrl_done:1; 436 | 437 | +#ifdef APPLE_CODECS 438 | + 439 | + // additional data for Apple 8409 system 440 | + 441 | + unsigned int spdif_detect:1; 442 | + unsigned int spdif_present:1; 443 | + unsigned int sense_b:1; 444 | + hda_nid_t vendor_nid; 445 | + 446 | + /* digital beep */ 447 | + hda_nid_t beep_nid; 448 | + 449 | + /* for MBP SPDIF control */ 450 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 451 | + struct snd_ctl_elem_value *ucontrol); 452 | + 453 | + // so it appears we have "concurrency" in the linux HDA code 454 | + // in that if unsolicited responses occur which perform extensive verbs 455 | + // the hda verbs are intermixed with eg extensive start playback verbs 456 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 457 | + // are logged but the unsolicited verbs occur after the verb block 458 | + // this flag is used to flag such verb blocks and the list will store the 459 | + // responses 460 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 461 | + // we will drop 462 | + // not clear if mutexes would be the way to go 463 | + int block_unsol; 464 | + struct list_head unsol_list; 465 | + struct unsol_item unsol_items_prealloc[10]; 466 | + int unsol_items_prealloc_used[10]; 467 | + 468 | + // add in specific nids for the intmike and linein as they seem to swap 469 | + // between macbook pros (14,3) and imacs (18,3) 470 | + int intmike_nid; 471 | + int linein_nid; 472 | + int intmike_adc_nid; 473 | + int linein_amp_nid; 474 | + 475 | + // the following flag bits also need swapping 476 | + int reg9_intmike_dmic_mo; 477 | + int reg9_linein_dmic_mo; 478 | + int reg82_intmike_dmic_scl; 479 | + int reg82_linein_dmic_scl; 480 | + 481 | + 482 | + // add explicit stream format store entries as per hda_codec using a local definition 483 | + // of hda_cvt_setup (which is local to hda_codec.c) 484 | + // also use explicit nid versions 485 | + // (except that means either need explicit functions for each nid or have to lookup 486 | + // nid each time want to use in a generic function with nid argument) 487 | + struct hda_cvt_setup_apple nid_0x02; 488 | + struct hda_cvt_setup_apple nid_0x03; 489 | + struct hda_cvt_setup_apple nid_0x0a; 490 | + struct hda_cvt_setup_apple nid_0x22; 491 | + struct hda_cvt_setup_apple nid_0x23; 492 | + struct hda_cvt_setup_apple nid_0x1a; 493 | + 494 | + 495 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 496 | + // the HDA spec by using a separate headphone chip 497 | + int jack_present; 498 | + 499 | + // save the type of headphone connected 500 | + int headset_type; 501 | + 502 | + // if headphone has mike or not 503 | + int have_mike; 504 | + 505 | + // if headphone has buttons or not 506 | + int have_buttons; 507 | + 508 | + // current stream channel count 509 | + int stream_channels; 510 | + 511 | + // set when playing for plug/unplug events while playing 512 | + int playing; 513 | + 514 | + // set when capturing for plug/unplug events while capturing 515 | + int capturing; 516 | + 517 | + // changing coding - OSX sets up the format on plugin 518 | + // then does some minimal setup when start play 519 | + // initial coding delayed any format setup till actually play 520 | + // this works for no mike but not for mike - we need to initialize 521 | + // the mike on plugin 522 | + // this flag will be set when we have done the format setup 523 | + // so know if need to do it on play or not 524 | + // now need 2 flags - one for play and one for capture 525 | + int headset_play_format_setup_needed; 526 | + int headset_capture_format_setup_needed; 527 | + 528 | + int headset_presetup_done; 529 | + 530 | + 531 | + int use_data; 532 | + 533 | + 534 | + // this is new item for dealing with headset plugins 535 | + // so can distinguish which phase we are in if have multiple interrupts 536 | + // not really used now have analyzed interrupts properly 537 | + int headset_phase; 538 | + 539 | + // another dirty hack item to manage the different headset enable codes 540 | + int headset_enable; 541 | + 542 | + int play_init; 543 | + int capture_init; 544 | + 545 | + 546 | + // new item to limit times we redo unmute/play 547 | + struct timespec64 last_play_time; 548 | + // record the first play time - we have a problem there 549 | + // some initial plays that I dont understand - so skip any setup 550 | + // till sometime after the first play 551 | + struct timespec64 first_play_time; 552 | + 553 | + 554 | +#endif 555 | + 556 | + 557 | /* verb exec op override */ 558 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 559 | unsigned int *res); 560 | -------------------------------------------------------------------------------- /patch_cs8409.h.diff: -------------------------------------------------------------------------------- 1 | --- a/codecs/cirrus/cs8409.h.orig 2025-09-15 12:53:58.000000000 +0100 2 | +++ b/codecs/cirrus/cs8409.h 2025-11-01 20:14:30.053248236 +0000 3 | @@ -19,198 +19,204 @@ 4 | #include "hda_jack.h" 5 | #include "../generic.h" 6 | 7 | +//#ifdef APPLE_CODECS 8 | +//#include 9 | +//#include 10 | +//#include 11 | +//#endif 12 | + 13 | /* CS8409 Specific Definitions */ 14 | 15 | enum cs8409_pins { 16 | - CS8409_PIN_ROOT, 17 | - CS8409_PIN_AFG, 18 | - CS8409_PIN_ASP1_OUT_A, 19 | - CS8409_PIN_ASP1_OUT_B, 20 | - CS8409_PIN_ASP1_OUT_C, 21 | - CS8409_PIN_ASP1_OUT_D, 22 | - CS8409_PIN_ASP1_OUT_E, 23 | - CS8409_PIN_ASP1_OUT_F, 24 | - CS8409_PIN_ASP1_OUT_G, 25 | - CS8409_PIN_ASP1_OUT_H, 26 | - CS8409_PIN_ASP2_OUT_A, 27 | - CS8409_PIN_ASP2_OUT_B, 28 | - CS8409_PIN_ASP2_OUT_C, 29 | - CS8409_PIN_ASP2_OUT_D, 30 | - CS8409_PIN_ASP2_OUT_E, 31 | - CS8409_PIN_ASP2_OUT_F, 32 | - CS8409_PIN_ASP2_OUT_G, 33 | - CS8409_PIN_ASP2_OUT_H, 34 | - CS8409_PIN_ASP1_IN_A, 35 | - CS8409_PIN_ASP1_IN_B, 36 | - CS8409_PIN_ASP1_IN_C, 37 | - CS8409_PIN_ASP1_IN_D, 38 | - CS8409_PIN_ASP1_IN_E, 39 | - CS8409_PIN_ASP1_IN_F, 40 | - CS8409_PIN_ASP1_IN_G, 41 | - CS8409_PIN_ASP1_IN_H, 42 | - CS8409_PIN_ASP2_IN_A, 43 | - CS8409_PIN_ASP2_IN_B, 44 | - CS8409_PIN_ASP2_IN_C, 45 | - CS8409_PIN_ASP2_IN_D, 46 | - CS8409_PIN_ASP2_IN_E, 47 | - CS8409_PIN_ASP2_IN_F, 48 | - CS8409_PIN_ASP2_IN_G, 49 | - CS8409_PIN_ASP2_IN_H, 50 | - CS8409_PIN_DMIC1, 51 | - CS8409_PIN_DMIC2, 52 | - CS8409_PIN_ASP1_TRANSMITTER_A, 53 | - CS8409_PIN_ASP1_TRANSMITTER_B, 54 | - CS8409_PIN_ASP1_TRANSMITTER_C, 55 | - CS8409_PIN_ASP1_TRANSMITTER_D, 56 | - CS8409_PIN_ASP1_TRANSMITTER_E, 57 | - CS8409_PIN_ASP1_TRANSMITTER_F, 58 | - CS8409_PIN_ASP1_TRANSMITTER_G, 59 | - CS8409_PIN_ASP1_TRANSMITTER_H, 60 | - CS8409_PIN_ASP2_TRANSMITTER_A, 61 | - CS8409_PIN_ASP2_TRANSMITTER_B, 62 | - CS8409_PIN_ASP2_TRANSMITTER_C, 63 | - CS8409_PIN_ASP2_TRANSMITTER_D, 64 | - CS8409_PIN_ASP2_TRANSMITTER_E, 65 | - CS8409_PIN_ASP2_TRANSMITTER_F, 66 | - CS8409_PIN_ASP2_TRANSMITTER_G, 67 | - CS8409_PIN_ASP2_TRANSMITTER_H, 68 | - CS8409_PIN_ASP1_RECEIVER_A, 69 | - CS8409_PIN_ASP1_RECEIVER_B, 70 | - CS8409_PIN_ASP1_RECEIVER_C, 71 | - CS8409_PIN_ASP1_RECEIVER_D, 72 | - CS8409_PIN_ASP1_RECEIVER_E, 73 | - CS8409_PIN_ASP1_RECEIVER_F, 74 | - CS8409_PIN_ASP1_RECEIVER_G, 75 | - CS8409_PIN_ASP1_RECEIVER_H, 76 | - CS8409_PIN_ASP2_RECEIVER_A, 77 | - CS8409_PIN_ASP2_RECEIVER_B, 78 | - CS8409_PIN_ASP2_RECEIVER_C, 79 | - CS8409_PIN_ASP2_RECEIVER_D, 80 | - CS8409_PIN_ASP2_RECEIVER_E, 81 | - CS8409_PIN_ASP2_RECEIVER_F, 82 | - CS8409_PIN_ASP2_RECEIVER_G, 83 | - CS8409_PIN_ASP2_RECEIVER_H, 84 | - CS8409_PIN_DMIC1_IN, 85 | - CS8409_PIN_DMIC2_IN, 86 | - CS8409_PIN_BEEP_GEN, 87 | - CS8409_PIN_VENDOR_WIDGET 88 | + CS8409_PIN_ROOT, // nid 0x00 89 | + CS8409_PIN_AFG, // nid 0x01 90 | + CS8409_PIN_ASP1_OUT_A, // nid 0x02 91 | + CS8409_PIN_ASP1_OUT_B, // nid 0x03 92 | + CS8409_PIN_ASP1_OUT_C, // nid 0x04 93 | + CS8409_PIN_ASP1_OUT_D, // nid 0x05 94 | + CS8409_PIN_ASP1_OUT_E, // nid 0x05 95 | + CS8409_PIN_ASP1_OUT_F, // nid 0x05 96 | + CS8409_PIN_ASP1_OUT_G, // nid 0x05 97 | + CS8409_PIN_ASP1_OUT_H, // nid 0x05 98 | + CS8409_PIN_ASP2_OUT_A, // nid 0x05 99 | + CS8409_PIN_ASP2_OUT_B, // nid 0x05 100 | + CS8409_PIN_ASP2_OUT_C, // nid 0x05 101 | + CS8409_PIN_ASP2_OUT_D, // nid 0x05 102 | + CS8409_PIN_ASP2_OUT_E, // nid 0x05 103 | + CS8409_PIN_ASP2_OUT_F, // nid 0x05 104 | + CS8409_PIN_ASP2_OUT_G, // nid 0x05 105 | + CS8409_PIN_ASP2_OUT_H, // nid 0x05 106 | + CS8409_PIN_ASP1_IN_A, // nid 0x05 107 | + CS8409_PIN_ASP1_IN_B, // nid 0x05 108 | + CS8409_PIN_ASP1_IN_C, // nid 0x14 109 | + CS8409_PIN_ASP1_IN_D, // nid 0x15 110 | + CS8409_PIN_ASP1_IN_E, // nid 0x15 111 | + CS8409_PIN_ASP1_IN_F, // nid 0x15 112 | + CS8409_PIN_ASP1_IN_G, // nid 0x15 113 | + CS8409_PIN_ASP1_IN_H, // nid 0x15 114 | + CS8409_PIN_ASP2_IN_A, // nid 0x15 115 | + CS8409_PIN_ASP2_IN_B, // nid 0x15 116 | + CS8409_PIN_ASP2_IN_C, // nid 0x15 117 | + CS8409_PIN_ASP2_IN_D, // nid 0x15 118 | + CS8409_PIN_ASP2_IN_E, // nid 0x15 119 | + CS8409_PIN_ASP2_IN_F, // nid 0x15 120 | + CS8409_PIN_ASP2_IN_G, // nid 0x15 121 | + CS8409_PIN_ASP2_IN_H, // nid 0x15 122 | + CS8409_PIN_DMIC1, // nid 0x22 123 | + CS8409_PIN_DMIC2, // nid 0x23 124 | + CS8409_PIN_ASP1_TRANSMITTER_A, // nid 0x24 125 | + CS8409_PIN_ASP1_TRANSMITTER_B, // nid 0x25 126 | + CS8409_PIN_ASP1_TRANSMITTER_C, // nid 0x25 127 | + CS8409_PIN_ASP1_TRANSMITTER_D, // nid 0x25 128 | + CS8409_PIN_ASP1_TRANSMITTER_E, // nid 0x25 129 | + CS8409_PIN_ASP1_TRANSMITTER_F, // nid 0x25 130 | + CS8409_PIN_ASP1_TRANSMITTER_G, // nid 0x25 131 | + CS8409_PIN_ASP1_TRANSMITTER_H, // nid 0x25 132 | + CS8409_PIN_ASP2_TRANSMITTER_A, // nid 0x25 133 | + CS8409_PIN_ASP2_TRANSMITTER_B, // nid 0x25 134 | + CS8409_PIN_ASP2_TRANSMITTER_C, // nid 0x25 135 | + CS8409_PIN_ASP2_TRANSMITTER_D, // nid 0x25 136 | + CS8409_PIN_ASP2_TRANSMITTER_E, // nid 0x25 137 | + CS8409_PIN_ASP2_TRANSMITTER_F, // nid 0x25 138 | + CS8409_PIN_ASP2_TRANSMITTER_G, // nid 0x25 139 | + CS8409_PIN_ASP2_TRANSMITTER_H, // nid 0x25 140 | + CS8409_PIN_ASP1_RECEIVER_A, // nid 0x34 141 | + CS8409_PIN_ASP1_RECEIVER_B, // nid 0x34 142 | + CS8409_PIN_ASP1_RECEIVER_C, // nid 0x34 143 | + CS8409_PIN_ASP1_RECEIVER_D, // nid 0x34 144 | + CS8409_PIN_ASP1_RECEIVER_E, // nid 0x34 145 | + CS8409_PIN_ASP1_RECEIVER_F, // nid 0x34 146 | + CS8409_PIN_ASP1_RECEIVER_G, // nid 0x34 147 | + CS8409_PIN_ASP1_RECEIVER_H, // nid 0x34 148 | + CS8409_PIN_ASP2_RECEIVER_A, // nid 0x34 149 | + CS8409_PIN_ASP2_RECEIVER_B, // nid 0x34 150 | + CS8409_PIN_ASP2_RECEIVER_C, // nid 0x34 151 | + CS8409_PIN_ASP2_RECEIVER_D, // nid 0x34 152 | + CS8409_PIN_ASP2_RECEIVER_E, // nid 0x34 153 | + CS8409_PIN_ASP2_RECEIVER_F, // nid 0x34 154 | + CS8409_PIN_ASP2_RECEIVER_G, // nid 0x34 155 | + CS8409_PIN_ASP2_RECEIVER_H, // nid 0x34 156 | + CS8409_PIN_DMIC1_IN, // nid 0x44 157 | + CS8409_PIN_DMIC2_IN, // nid 0x45 158 | + CS8409_PIN_BEEP_GEN, // nid 0x46 159 | + CS8409_PIN_VENDOR_WIDGET // nid 0x47 160 | }; 161 | 162 | enum cs8409_coefficient_index_registers { 163 | - CS8409_DEV_CFG1, 164 | - CS8409_DEV_CFG2, 165 | - CS8409_DEV_CFG3, 166 | - CS8409_ASP1_CLK_CTRL1, 167 | - CS8409_ASP1_CLK_CTRL2, 168 | - CS8409_ASP1_CLK_CTRL3, 169 | - CS8409_ASP2_CLK_CTRL1, 170 | - CS8409_ASP2_CLK_CTRL2, 171 | - CS8409_ASP2_CLK_CTRL3, 172 | - CS8409_DMIC_CFG, 173 | - CS8409_BEEP_CFG, 174 | - ASP1_RX_NULL_INS_RMV, 175 | - ASP1_Rx_RATE1, 176 | - ASP1_Rx_RATE2, 177 | - ASP1_Tx_NULL_INS_RMV, 178 | - ASP1_Tx_RATE1, 179 | - ASP1_Tx_RATE2, 180 | - ASP2_Rx_NULL_INS_RMV, 181 | - ASP2_Rx_RATE1, 182 | - ASP2_Rx_RATE2, 183 | - ASP2_Tx_NULL_INS_RMV, 184 | - ASP2_Tx_RATE1, 185 | - ASP2_Tx_RATE2, 186 | - ASP1_SYNC_CTRL, 187 | - ASP2_SYNC_CTRL, 188 | - ASP1_A_TX_CTRL1, 189 | - ASP1_A_TX_CTRL2, 190 | - ASP1_B_TX_CTRL1, 191 | - ASP1_B_TX_CTRL2, 192 | - ASP1_C_TX_CTRL1, 193 | - ASP1_C_TX_CTRL2, 194 | - ASP1_D_TX_CTRL1, 195 | - ASP1_D_TX_CTRL2, 196 | - ASP1_E_TX_CTRL1, 197 | - ASP1_E_TX_CTRL2, 198 | - ASP1_F_TX_CTRL1, 199 | - ASP1_F_TX_CTRL2, 200 | - ASP1_G_TX_CTRL1, 201 | - ASP1_G_TX_CTRL2, 202 | - ASP1_H_TX_CTRL1, 203 | - ASP1_H_TX_CTRL2, 204 | - ASP2_A_TX_CTRL1, 205 | - ASP2_A_TX_CTRL2, 206 | - ASP2_B_TX_CTRL1, 207 | - ASP2_B_TX_CTRL2, 208 | - ASP2_C_TX_CTRL1, 209 | - ASP2_C_TX_CTRL2, 210 | - ASP2_D_TX_CTRL1, 211 | - ASP2_D_TX_CTRL2, 212 | - ASP2_E_TX_CTRL1, 213 | - ASP2_E_TX_CTRL2, 214 | - ASP2_F_TX_CTRL1, 215 | - ASP2_F_TX_CTRL2, 216 | - ASP2_G_TX_CTRL1, 217 | - ASP2_G_TX_CTRL2, 218 | - ASP2_H_TX_CTRL1, 219 | - ASP2_H_TX_CTRL2, 220 | - ASP1_A_RX_CTRL1, 221 | - ASP1_A_RX_CTRL2, 222 | - ASP1_B_RX_CTRL1, 223 | - ASP1_B_RX_CTRL2, 224 | - ASP1_C_RX_CTRL1, 225 | - ASP1_C_RX_CTRL2, 226 | - ASP1_D_RX_CTRL1, 227 | - ASP1_D_RX_CTRL2, 228 | - ASP1_E_RX_CTRL1, 229 | - ASP1_E_RX_CTRL2, 230 | - ASP1_F_RX_CTRL1, 231 | - ASP1_F_RX_CTRL2, 232 | - ASP1_G_RX_CTRL1, 233 | - ASP1_G_RX_CTRL2, 234 | - ASP1_H_RX_CTRL1, 235 | - ASP1_H_RX_CTRL2, 236 | - ASP2_A_RX_CTRL1, 237 | - ASP2_A_RX_CTRL2, 238 | - ASP2_B_RX_CTRL1, 239 | - ASP2_B_RX_CTRL2, 240 | - ASP2_C_RX_CTRL1, 241 | - ASP2_C_RX_CTRL2, 242 | - ASP2_D_RX_CTRL1, 243 | - ASP2_D_RX_CTRL2, 244 | - ASP2_E_RX_CTRL1, 245 | - ASP2_E_RX_CTRL2, 246 | - ASP2_F_RX_CTRL1, 247 | - ASP2_F_RX_CTRL2, 248 | - ASP2_G_RX_CTRL1, 249 | - ASP2_G_RX_CTRL2, 250 | - ASP2_H_RX_CTRL1, 251 | - ASP2_H_RX_CTRL2, 252 | - CS8409_I2C_ADDR, 253 | - CS8409_I2C_DATA, 254 | - CS8409_I2C_CTRL, 255 | - CS8409_I2C_STS, 256 | - CS8409_I2C_QWRITE, 257 | - CS8409_I2C_QREAD, 258 | - CS8409_SPI_CTRL, 259 | - CS8409_SPI_TX_DATA, 260 | - CS8409_SPI_RX_DATA, 261 | - CS8409_SPI_STS, 262 | - CS8409_PFE_COEF_W1, /* Parametric filter engine coefficient write 1*/ 263 | - CS8409_PFE_COEF_W2, 264 | - CS8409_PFE_CTRL1, 265 | - CS8409_PFE_CTRL2, 266 | - CS8409_PRE_SCALE_ATTN1, 267 | - CS8409_PRE_SCALE_ATTN2, 268 | - CS8409_PFE_COEF_MON1, /* Parametric filter engine coefficient monitor 1*/ 269 | - CS8409_PFE_COEF_MON2, 270 | - CS8409_ASP1_INTRN_STS, 271 | - CS8409_ASP2_INTRN_STS, 272 | - CS8409_ASP1_RX_SCLK_COUNT, 273 | - CS8409_ASP1_TX_SCLK_COUNT, 274 | - CS8409_ASP2_RX_SCLK_COUNT, 275 | - CS8409_ASP2_TX_SCLK_COUNT, 276 | - CS8409_ASP_UNS_RESP_MASK, 277 | + CS8409_DEV_CFG1, // reg 0x00 278 | + CS8409_DEV_CFG2, // reg 0x00 279 | + CS8409_DEV_CFG3, // reg 0x00 280 | + CS8409_ASP1_CLK_CTRL1, // reg 0x03 281 | + CS8409_ASP1_CLK_CTRL2, // reg 0x03 282 | + CS8409_ASP1_CLK_CTRL3, // reg 0x03 283 | + CS8409_ASP2_CLK_CTRL1, // reg 0x03 284 | + CS8409_ASP2_CLK_CTRL2, // reg 0x03 285 | + CS8409_ASP2_CLK_CTRL3, // reg 0x03 286 | + CS8409_DMIC_CFG, // reg 0x09 287 | + CS8409_BEEP_CFG, // reg 0x0a 288 | + ASP1_RX_NULL_INS_RMV, // reg 0x0b 289 | + ASP1_Rx_RATE1, // reg 0x0c 290 | + ASP1_Rx_RATE2, // reg 0x0d 291 | + ASP1_Tx_NULL_INS_RMV, // reg 0x0e 292 | + ASP1_Tx_RATE1, // reg 0x0f 293 | + ASP1_Tx_RATE2, // reg 0x10 294 | + ASP2_Rx_NULL_INS_RMV, // reg 0x11 295 | + ASP2_Rx_RATE1, // reg 0x12 296 | + ASP2_Rx_RATE2, // reg 0x13 297 | + ASP2_Tx_NULL_INS_RMV, // reg 0x14 298 | + ASP2_Tx_RATE1, // reg 0x15 299 | + ASP2_Tx_RATE2, // reg 0x16 300 | + ASP1_SYNC_CTRL, // reg 0x17 301 | + ASP2_SYNC_CTRL, // reg 0x18 302 | + ASP1_A_TX_CTRL1, // reg 0x19 303 | + ASP1_A_TX_CTRL2, // reg 0x19 304 | + ASP1_B_TX_CTRL1, // reg 0x19 305 | + ASP1_B_TX_CTRL2, // reg 0x19 306 | + ASP1_C_TX_CTRL1, // reg 0x19 307 | + ASP1_C_TX_CTRL2, // reg 0x19 308 | + ASP1_D_TX_CTRL1, // reg 0x19 309 | + ASP1_D_TX_CTRL2, // reg 0x19 310 | + ASP1_E_TX_CTRL1, // reg 0x19 311 | + ASP1_E_TX_CTRL2, // reg 0x19 312 | + ASP1_F_TX_CTRL1, // reg 0x19 313 | + ASP1_F_TX_CTRL2, // reg 0x19 314 | + ASP1_G_TX_CTRL1, // reg 0x19 315 | + ASP1_G_TX_CTRL2, // reg 0x19 316 | + ASP1_H_TX_CTRL1, // reg 0x19 317 | + ASP1_H_TX_CTRL2, // reg 0x19 318 | + ASP2_A_TX_CTRL1, // reg 0x19 319 | + ASP2_A_TX_CTRL2, // reg 0x19 320 | + ASP2_B_TX_CTRL1, // reg 0x19 321 | + ASP2_B_TX_CTRL2, // reg 0x19 322 | + ASP2_C_TX_CTRL1, // reg 0x19 323 | + ASP2_C_TX_CTRL2, // reg 0x19 324 | + ASP2_D_TX_CTRL1, // reg 0x19 325 | + ASP2_D_TX_CTRL2, // reg 0x19 326 | + ASP2_E_TX_CTRL1, // reg 0x19 327 | + ASP2_E_TX_CTRL2, // reg 0x19 328 | + ASP2_F_TX_CTRL1, // reg 0x19 329 | + ASP2_F_TX_CTRL2, // reg 0x19 330 | + ASP2_G_TX_CTRL1, // reg 0x19 331 | + ASP2_G_TX_CTRL2, // reg 0x19 332 | + ASP2_H_TX_CTRL1, // reg 0x19 333 | + ASP2_H_TX_CTRL2, // reg 0x19 334 | + ASP1_A_RX_CTRL1, // reg 0x19 335 | + ASP1_A_RX_CTRL2, // reg 0x19 336 | + ASP1_B_RX_CTRL1, // reg 0x19 337 | + ASP1_B_RX_CTRL2, // reg 0x19 338 | + ASP1_C_RX_CTRL1, // reg 0x19 339 | + ASP1_C_RX_CTRL2, // reg 0x19 340 | + ASP1_D_RX_CTRL1, // reg 0x19 341 | + ASP1_D_RX_CTRL2, // reg 0x19 342 | + ASP1_E_RX_CTRL1, // reg 0x19 343 | + ASP1_E_RX_CTRL2, // reg 0x19 344 | + ASP1_F_RX_CTRL1, // reg 0x19 345 | + ASP1_F_RX_CTRL2, // reg 0x19 346 | + ASP1_G_RX_CTRL1, // reg 0x19 347 | + ASP1_G_RX_CTRL2, // reg 0x19 348 | + ASP1_H_RX_CTRL1, // reg 0x19 349 | + ASP1_H_RX_CTRL2, // reg 0x19 350 | + ASP2_A_RX_CTRL1, // reg 0x19 351 | + ASP2_A_RX_CTRL2, // reg 0x19 352 | + ASP2_B_RX_CTRL1, // reg 0x19 353 | + ASP2_B_RX_CTRL2, // reg 0x19 354 | + ASP2_C_RX_CTRL1, // reg 0x19 355 | + ASP2_C_RX_CTRL2, // reg 0x19 356 | + ASP2_D_RX_CTRL1, // reg 0x19 357 | + ASP2_D_RX_CTRL2, // reg 0x19 358 | + ASP2_E_RX_CTRL1, // reg 0x19 359 | + ASP2_E_RX_CTRL2, // reg 0x19 360 | + ASP2_F_RX_CTRL1, // reg 0x19 361 | + ASP2_F_RX_CTRL2, // reg 0x19 362 | + ASP2_G_RX_CTRL1, // reg 0x19 363 | + ASP2_G_RX_CTRL2, // reg 0x19 364 | + ASP2_H_RX_CTRL1, // reg 0x19 365 | + ASP2_H_RX_CTRL2, // reg 0x19 366 | + CS8409_I2C_ADDR, // reg 0x59 367 | + CS8409_I2C_DATA, // reg 0x59 368 | + CS8409_I2C_CTRL, // reg 0x59 369 | + CS8409_I2C_STS, // reg 0x59 370 | + CS8409_I2C_QWRITE, // reg 0x59 371 | + CS8409_I2C_QREAD, // reg 0x59 372 | + CS8409_SPI_CTRL, // reg 0x59 373 | + CS8409_SPI_TX_DATA, // reg 0x59 374 | + CS8409_SPI_RX_DATA, // reg 0x59 375 | + CS8409_SPI_STS, // reg 0x59 376 | + CS8409_PFE_COEF_W1, // reg 0x63 /* Parametric filter engine coefficient write 1*/ 377 | + CS8409_PFE_COEF_W2, // reg 0x64 378 | + CS8409_PFE_CTRL1, // reg 0x64 379 | + CS8409_PFE_CTRL2, // reg 0x64 380 | + CS8409_PRE_SCALE_ATTN1, // reg 0x64 381 | + CS8409_PRE_SCALE_ATTN2, // reg 0x64 382 | + CS8409_PFE_COEF_MON1, // reg 0x69 /* Parametric filter engine coefficient monitor 1*/ 383 | + CS8409_PFE_COEF_MON2, // reg 0x6a 384 | + CS8409_ASP1_INTRN_STS, // reg 0x6a 385 | + CS8409_ASP2_INTRN_STS, // reg 0x6a 386 | + CS8409_ASP1_RX_SCLK_COUNT, // reg 0x6a 387 | + CS8409_ASP1_TX_SCLK_COUNT, // reg 0x6a 388 | + CS8409_ASP2_RX_SCLK_COUNT, // reg 0x6a 389 | + CS8409_ASP2_TX_SCLK_COUNT, // reg 0x6a 390 | + CS8409_ASP_UNS_RESP_MASK, // reg 0x6a 391 | CS8409_LOOPBACK_CTRL = 0x80, 392 | CS8409_PAD_CFG_SLW_RATE_CTRL = 0x82, /* Pad Config and Slew Rate Control (CIR = 0x0082) */ 393 | }; 394 | @@ -299,6 +305,23 @@ 395 | unsigned int coeff; 396 | }; 397 | 398 | + 399 | +#ifdef APPLE_CODECS 400 | +struct unsol_item { 401 | + struct list_head list; 402 | + unsigned int idx; 403 | + unsigned int res; 404 | +}; 405 | +struct hda_cvt_setup_apple { 406 | + hda_nid_t nid; 407 | + u8 stream_tag; 408 | + u8 channel_id; 409 | + u16 format_id; 410 | + unsigned char active; /* cvt is currently used */ 411 | + unsigned char dirty; /* setups should be cleared */ 412 | +}; 413 | +#endif 414 | + 415 | struct sub_codec { 416 | struct hda_codec *codec; 417 | unsigned int addr; 418 | @@ -309,6 +332,9 @@ 419 | 420 | unsigned int hp_jack_in:1; 421 | unsigned int mic_jack_in:1; 422 | +#ifdef APPLE_CODECS 423 | + unsigned int linein_jack_in:1; 424 | +#endif 425 | unsigned int suspended:1; 426 | unsigned int paged:1; 427 | unsigned int last_page; 428 | @@ -342,6 +368,129 @@ 429 | unsigned int init_done:1; 430 | unsigned int build_ctrl_done:1; 431 | 432 | +#ifdef APPLE_CODECS 433 | + 434 | + // additional data for Apple 8409 system 435 | + 436 | + unsigned int spdif_detect:1; 437 | + unsigned int spdif_present:1; 438 | + unsigned int sense_b:1; 439 | + hda_nid_t vendor_nid; 440 | + 441 | + /* digital beep */ 442 | + hda_nid_t beep_nid; 443 | + 444 | + /* for MBP SPDIF control */ 445 | + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 446 | + struct snd_ctl_elem_value *ucontrol); 447 | + 448 | + // so it appears we have "concurrency" in the linux HDA code 449 | + // in that if unsolicited responses occur which perform extensive verbs 450 | + // the hda verbs are intermixed with eg extensive start playback verbs 451 | + // on OSX we appear to have blocks of verbs during which unsolicited responses 452 | + // are logged but the unsolicited verbs occur after the verb block 453 | + // this flag is used to flag such verb blocks and the list will store the 454 | + // responses 455 | + // we use a pre-allocated list - if we have more than 10 outstanding unsols 456 | + // we will drop 457 | + // not clear if mutexes would be the way to go 458 | + int block_unsol; 459 | + struct list_head unsol_list; 460 | + struct unsol_item unsol_items_prealloc[10]; 461 | + int unsol_items_prealloc_used[10]; 462 | + 463 | + // add in specific nids for the intmike and linein as they seem to swap 464 | + // between macbook pros (14,3) and imacs (18,3) 465 | + int intmike_nid; 466 | + int linein_nid; 467 | + int intmike_adc_nid; 468 | + int linein_amp_nid; 469 | + 470 | + // the following flag bits also need swapping 471 | + int reg9_intmike_dmic_mo; 472 | + int reg9_linein_dmic_mo; 473 | + int reg82_intmike_dmic_scl; 474 | + int reg82_linein_dmic_scl; 475 | + 476 | + 477 | + // add explicit stream format store entries as per hda_codec using a local definition 478 | + // of hda_cvt_setup (which is local to hda_codec.c) 479 | + // also use explicit nid versions 480 | + // (except that means either need explicit functions for each nid or have to lookup 481 | + // nid each time want to use in a generic function with nid argument) 482 | + struct hda_cvt_setup_apple nid_0x02; 483 | + struct hda_cvt_setup_apple nid_0x03; 484 | + struct hda_cvt_setup_apple nid_0x0a; 485 | + struct hda_cvt_setup_apple nid_0x22; 486 | + struct hda_cvt_setup_apple nid_0x23; 487 | + struct hda_cvt_setup_apple nid_0x1a; 488 | + 489 | + 490 | + // new item to deal with jack presence as Apple (and now Dell) seems to have barfed 491 | + // the HDA spec by using a separate headphone chip 492 | + int jack_present; 493 | + 494 | + // save the type of headphone connected 495 | + int headset_type; 496 | + 497 | + // if headphone has mike or not 498 | + int have_mike; 499 | + 500 | + // if headphone has buttons or not 501 | + int have_buttons; 502 | + 503 | + // current stream channel count 504 | + int stream_channels; 505 | + 506 | + // set when playing for plug/unplug events while playing 507 | + int playing; 508 | + 509 | + // set when capturing for plug/unplug events while capturing 510 | + int capturing; 511 | + 512 | + // changing coding - OSX sets up the format on plugin 513 | + // then does some minimal setup when start play 514 | + // initial coding delayed any format setup till actually play 515 | + // this works for no mike but not for mike - we need to initialize 516 | + // the mike on plugin 517 | + // this flag will be set when we have done the format setup 518 | + // so know if need to do it on play or not 519 | + // now need 2 flags - one for play and one for capture 520 | + int headset_play_format_setup_needed; 521 | + int headset_capture_format_setup_needed; 522 | + 523 | + int headset_presetup_done; 524 | + 525 | + 526 | + int use_data; 527 | + 528 | + 529 | + // this is new item for dealing with headset plugins 530 | + // so can distinguish which phase we are in if have multiple interrupts 531 | + // not really used now have analyzed interrupts properly 532 | + int headset_phase; 533 | + 534 | + // another dirty hack item to manage the different headset enable codes 535 | + int headset_enable; 536 | + 537 | + int play_init; 538 | + int capture_init; 539 | + 540 | + int play_init_count; 541 | + int capture_init_count; 542 | + 543 | + 544 | + // new item to limit times we redo unmute/play 545 | + struct timespec64 last_play_time; 546 | + // record the first play time - we have a problem there 547 | + // some initial plays that I dont understand - so skip any setup 548 | + // till sometime after the first play 549 | + struct timespec64 first_play_time; 550 | + 551 | + 552 | +#endif 553 | + 554 | + 555 | /* verb exec op override */ 556 | int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, 557 | unsigned int *res); 558 | --------------------------------------------------------------------------------