[alsa-devel] CS8409 Macbook Pro 2016 2017

David Ulricht david.ulricht434 at gmail.com
Tue Nov 27 03:42:17 CET 2018


 One thing to note on all I2C interfaces is that when GPIO is driven high
(IN direction,dir=0) on the master (e.g. CS8409), SDA should be a constant
HIGH, e.g. data=1.
No matter if there is any I2C device connected to the bus, if you have a
pull-up it will always pull-up the constant value 1. This 1 is usually a
NACK that get received if you dont find the address.

So far I couldn't get the IO[7] (SDA) with dir=0 (in,also known as HIGH
direction) to deliver a data=1. IO[7] is with constant data=0.  This means
the pull-up is not pulling 1, and the I2C interface is not enabled by
default after reset of the CS8409 codec.
this is expected value for enabled I2C:
  IO[7]: enable=1, dir=0, wake=0, sticky=0, data=*1*, unsol=0
but what I get is:
  IO[7]: enable=1, dir=0, wake=0, sticky=0, data=0, unsol=0  which means
I2C mode not initialized.

I was just going to give up totally, and i looked up into one of my emails
where i found the following:
  IO[7]: enable=1, dir=0, wake=0, sticky=0, data=1, unsol=0
after using my amateur send_sequence script (when i had no idea how I2C
works) or some random sequence of events i executed and I had at this point
IO[7] data as HIGH which means I2C was working at that exact moment.

tho i did decipher the GPIO1ExtAmpCFG=hex:01,00,00,01 which if you check
the schematics, the daisy-chained  CS42L83A codec is powered by GPIO1 on
CS8409 by keeping data=1, because there is pull-down on the CS42L83A's
CODEC_RESET_L.
There is also CODEC_INT_L which is the interrupt line, which is directly
tied to GPIO[0] on CS8409. This actually returns a constant data=1, which
gives some hope as well.
  IO[0]: enable=1, dir=0, wake=0, sticky=0, data=*1*, unsol=1


Opening AppleHDA in IDA reveals AppleHDAFunctionGroupCS4208::enableI2C(bool)
Anyone knowing anything about TDM Config in Cirrus Logic ? Enabling I2C ?
Is it Vendor specific verb ? Maybe it's some general way on most HDA's ?
The reason to have I2C disabled on reset is that some of the devices like
the amps and the speakers need to be configured in a specific order to save
power and to avoid sound glitches.

On Fri, Nov 23, 2018 at 7:26 PM David Ulricht <david.ulricht434 at gmail.com>
wrote:

>
> Once when it's confirmed to work from user-space, we can think of the
>> kernel-side implementation, too.  Instead of setting up the whole
>> complex i2c subsystem, we may wire up the existing stuff in
>> sound/i2c/*, too.
>>
> Okay
>
> You should try to initialize over i2c over HD-audio GPIO pins using a
>> user-space program at first.  The GPIO pins can be read/written via
>> hda-verb as I already mentioned, hence you can access to i2c bus from
>> the user-space directly.
>
>
> I have written the following bash script,
>
>> #!/bin/bash
>> # DIR              0 (low) = out   40 (high) = in
>> #            low to write,      high to read
>> # SCL == 0x40      SDA == 0x80
>> function send() {
>> str1=$1
>> str2=$2
>> str3=$3
>> hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_MASK 0x$str1
>> # we send 0 to bus by enabling gpio_dir
>> hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_DIR 0x$str2
>> # we send data=0 to send to the bus
>> hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_DATA 0x$str3
>> }
>> # reads the values I set, no different return value from i2c/codec
>> function recv() {
>> hda-verb /dev/snd/hwC0D0 0x01 GET_GPIO_MASK 0x$str1
>> hda-verb /dev/snd/hwC0D0 0x01 GET_GPIO_DIR 0x$str2
>> hda-verb /dev/snd/hwC0D0 0x01 GET_GPIO_DATA 0x$str3
>> }
>>
>>
>> function send_sequence() {
>>     data=$1
>>         #split hexes by coma to be able to send 1 by 1
>>     hexes=$(echo $data|tr "," "\n")
>>     for hex in $hexes; do
>>         echo 'sending hex: ' $hex
>>         send 40 0 0 # 0 to scl
>>
> mask of SCL enabled, data 0 , dir 0, is that correct ?
>
>>         sleep 0.003
>>         send 80 0 $hex # send 0x28 to sda if $hex=28
>>
> mask of SDA enabled, direction 0, hex to data
>
>>         sleep 0.003
>>         send 0 40 40 # 1 to scl
>>
> mask of SCL disabled, direction 1, data 1
>
>>         sleep 0.003
>>         echo sent
>>     done
>> }
>>
> below i'm sending the hexes from Win10ini but in the exact same order,
> which worries me a bit, maybe they need to be reversed 4by4?
> like 01,90,02,00,11,01,02 could become: 00,02,90,01,02,01,11 .. because
> for the InitVerbs i did that reversing 4by4 and it works only correctly if
> the hexes are reversed 4by4. (at the end of the email i am attaching the
> exitverbs conversion which is perfect).
>
>> #initi2c
>> send_sequence
>> "01,90,3a,00,10,10,b0,00,1d,01,00,02,06,00,11,07,01,00,10,09,02,07,03,00,12,01,00,08,13,05,ff,06,00,07,20,02,0d,00,2a,02,02,03,00,04,00,05,02,06,00,07,20,08,02,09,00,0a,80,0b,02,0c,00,0d,a0,01,0c,00,29,02,01,03,02,04,00,05,00,01,01,00,11,01,0a,02,84,00,23,01,00,03,00,02,3f,00,20,01,03,00,1b,75,b6,73,c2,00,11,29,01,21,f3,03,20,05,00,12,00,13,80,00,1c,03,c0"
>> #streamstarti2c
>> send_sequence "01,90,02,00,11,01,02"
>> #powerup-amps
>> send_sequence
>> "04,28,2a,2c,2e,07,00,81,01,11,02,32,03,48,04,11,05,10,00,80"
>> send_sequence
>> "01,28,01,05,00,01,2a,01,05,02,01,2c,01,05,01,01,2e,01,05,03"
>> #streamstopi2c
>> send_sequence "01,90,02,00,11,01,0a"
>> #echo read
>> #recv 0 0 0
>>
>
> For example something that works is
>
> "ExitVerbs"=hex:00,05,17,00,01,00,75,04,00,00,74,04,82,00,75,04,00,00,74,04,03,\
>
> 00,75,04,00,80,74,04,04,00,75,04,01,28,74,04,06,00,75,04,00,80,74,04,07,00,\
>   75,04,01,28,74,04,65,00,75,04,00,00,74,04,00,03,77,04,03,05,17,00
>
>> hda-verb /dev/snd/hwC0D0 0x01 0x705 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x01
>> hda-verb /dev/snd/hwC0D0 0x47 0x400 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x82
>> hda-verb /dev/snd/hwC0D0 0x47 0x400 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x03
>> hda-verb /dev/snd/hwC0D0 0x47 0x480 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x04
>> hda-verb /dev/snd/hwC0D0 0x47 0x428 0x01
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x06
>> hda-verb /dev/snd/hwC0D0 0x47 0x480 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x07
>> hda-verb /dev/snd/hwC0D0 0x47 0x428 0x01
>> hda-verb /dev/snd/hwC0D0 0x47 0x500 0x65
>> hda-verb /dev/snd/hwC0D0 0x47 0x400 0x00
>> hda-verb /dev/snd/hwC0D0 0x47 0x703 0x00
>> hda-verb /dev/snd/hwC0D0 0x01 0x705 0x03
>>
>> Also InitVerbs from windows10ini and ExitVerbs from windows10ini reversed
> hexes 4by4 sent with hda-verb work perfect. They initiate the CS8409 codec
> or shut it down properly as i can see in the codec#0 status changing from
> D3 to D0 and D0 to D3.
> But the above exitverbs are sent to the widgets AFG node and the 0x47
> widget, (InitVerbs have a few more widgets).
>
> I tried to do the same for the InitI2C hexes, but apperently they are not
> supposed to be send as hexes directly to the widgets like InitVerbs or
> ExitVerbs. All the I2C related stuff are strictly I2C related for executing
> on the SDA/SCL GPIO7/6.
>
> So my idea is, do I need to reverse the hexes 4 by 4, when sending to the
> SDA ?
> And if you have any examples how can i get a read value from the SDA
> please.
>
>
> Btw:
> root at debian:~# cat /proc/asound/card0/codec#0 |head -n 25|tail -n 8
>   IO[0]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[1]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[2]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[3]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[4]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[5]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[6]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[7]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
> the default values are IO7 which is GPIO7 which is SDA. is enabled=0 dir=0
> data=0
>
> root at debian:~# hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_MASK 0x80
> nid = 0x1, verb = 0x716, param = 0x80
> value = 0x0
> root at debian:~# hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_DIR 0x0
> nid = 0x1, verb = 0x717, param = 0x0
> value = 0x0
> root at debian:~# hda-verb /dev/snd/hwC0D0 0x01 SET_GPIO_DATA 0x28
> nid = 0x1, verb = 0x715, param = 0x28
> value = 0x0
> After i send the above, data becomes data=1  but i sent 0x28.
>
> root at debian:~# cat /proc/asound/card0/codec#0 |head -n 25|tail -n 8
>   IO[0]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[1]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[2]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[3]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[4]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[5]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[6]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
>   IO[7]: enable=1, dir=0, wake=0, sticky=0, data=1, unsol=0
>
> But if i read GPIO_DATA,
> root at debian:~# hda-verb /dev/snd/hwC0D0 0x01 GET_GPIO_DATA 0x0
> nid = 0x1, verb = 0xf15, param = 0x0
> value = 0x80
>
> the value returned is 0x80.
> Which leads me to the idea the only type of data you can send is either
> 0x40 for 1 on SCL, 0x80 for 1 on SDA, or 0x00 for 0 on both( if you enable
> mask of SCL it will send 0 to SCL only, and if you enable mask of SDA it
> will send 0 to SDA only).
>
> If thats true, you can only send 0/1 to the GPIOs, which means if i have
> to send the address of 1st SSM3515 "0x28", I have to send it as "101000" to
> the SDA.
>
> How could I try to read register 0x00 of I2C address 0x28  (one of the
> four SSM3515 amplifier) ? It should return value 0x83 according to the
> documentation of SSM3515 as a "reset value for register 0x00".
>
> If it is true that I can read data with GET_GPIO_DATA will it return as
> well only one bit of data like 0/1  at a time? If I need get a value of
> 0x83 thru the GPIO7 its binary value should be 10000011 , so this means
> that If i execute GET_GPIO_DATA   8 times in a row i will receive this
> piece by piece 1, 0 , 0 , 0 , 0 , 0 , 1, 1. Meanwhile I try to execute 8
> times GET_GPIO_DATA  should i be sending to the SCL (GPIO6) each time a
> clock value 0 ? or also a SET_GPIO_DATA value to the GPIO7 with value 0 for
> reading?
> Please advise.
>


More information about the Alsa-devel mailing list