Letux/Alpha 400: small progress with sound

9 views
Skip to first unread message

H. Nikolaus Schaller

unread,
Apr 27, 2021, 7:12:56 AM4/27/21
to Paul Boddie, Discussions about the Letux Kernel, Riccardo Mottola, Lubomir Rintel, Zhou Yanjie, MIPS Creator CI20 Development
Hi Paul,
I have managed to get the headset detection work with lewtux-5.12 by modifying the DTS [1]:

root@letux:~# evtest /dev/input/event2
Input driver version is 1.0.1
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "Alpha 400 Headphones"
Supported events:
Event type 0 (EV_SYN)
Event type 5 (EV_SW)
Event code 2 (SW_HEADPHONE_INSERT)
Properties:
Testing ... (interrupt to exit)
Event: time 6397.560368, type 5 (EV_SW), code 2 (SW_HEADPHONE_INSERT), value 1
Event: time 6397.560368, -------------- EV_SYN ------------
Event: time 6401.050375, type 5 (EV_SW), code 2 (SW_HEADPHONE_INSERT), value 0
Event: time 6401.050375, -------------- EV_SYN ------------
^C
root@letux:~#

Still no success with I2S/Codec/DMA/aplay/arecord:

root@letux:~# aplay /usr/share/sounds/alsa/Front_Center.wav
[ 7637.981286] jz4740_i2s_startup
[ 7637.984612] ak4642_dai_startup: play=1
Playing WAVE '/usr/share/sounds/alsa/Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
[ 7638.024581] ak4642_dai_hw_params mcko=12000000
[ 7638.029615] ak4642_set_mcko: freq=12000000
[ 7638.033961] jz4740_i2s_hw_params
[ 7638.039801] jz4780_dma_config
[ 7638.054218] jz4780_dma_prep_dma_cyclic
[ 7638.058211] jz4780_dma_desc_alloc
[ 7638.061724] jz4780_dma_setup_hwdesc
[ 7638.065403] jz4780_dma_transfer_size
[ 7638.069167] jz4780_dma_setup_hwdesc
[ 7638.072841] jz4780_dma_transfer_size
[ 7638.076603] jz4780_dma_setup_hwdesc
[ 7638.080277] jz4780_dma_transfer_size
[ 7638.084038] jz4780_dma_setup_hwdesc
[ 7638.087713] jz4780_dma_transfer_size
[ 7638.091482] jz4780_dma_begin
[ 7638.094547] jz4780_dma_chan_enable
[ 7638.098145] jz4740_i2s_trigger
[ 7638.106437] jz4780_dma_tx_status
^CAborted by signal Interrupt...
[ 7641.548540] jz4740_i2s_trigger
[ 7641.553011] jz4780_dma_terminate_all
[ 7641.556778] jz4780_dma_chan_disable
[ 7641.560456] jz4780_dma_desc_free
aplay: pcm_write:1939: write error: Inte[ 7641.567445] jz4740_i2s_shutdown
rrupted system c[ 7641.571680] ak4642_dai_shutdown: play=1
all
[ 7641.577012] jz4780_dma_synchronize
[ 7641.583599] jz4780_dma_chan_disable
root@letux:~#

Most likely the clocks of the I2S interface are not enabled properly or the pinctrl
function / direction is wrong. The fact that aplay gets stuck indicates that the
jz4730 I2S is in slave mode (waiting for external clock) which is not provided by
the codec (master). If it were the other way round, sound data would be emitted
independently of the codec listening or not.

For the microphone/line in I am not sure if it is supported by the ak4642 driver
at all. There is no SND_SOC_DAPM_INPUT definition and I had to comment out
the routing.

We have the old 2.6 driver in sound/oss/ak4642en.c but that is too far away
from modern Sound architecture...

BR,
Nikolaus

[1]: https://git.goldelico.com/?p=letux-kernel.git;a=shortlog;h=refs/heads/work-jz4730-sound

H. Nikolaus Schaller

unread,
Apr 28, 2021, 2:19:25 PM4/28/21
to Paul Boddie, Discussions about the Letux Kernel, Riccardo Mottola, Lubomir Rintel, Zhou Yanjie, MIPS Creator CI20 Development
Hi Paul,


> Am 27.04.2021 um 13:12 schrieb H. Nikolaus Schaller <h...@goldelico.com>:
>
> Hi Paul,
> I have managed to get the headset detection work with lewtux-5.12 by modifying the DTS [1]:
>
I have hacked some ioremap() into jz4740_i2s_trigger() to be able to modify
pinctrl on the fly and read the gpio bits directly.

There is clock activity on both BITCLK and SYNC obviously coming from the codec.
And switching to ping function 0x2 makes these pins an output.

So I think we can rule out codec and pinctrl problems as the main blocking point
for completely stuck communication. It still may happen that there is no sound
if we fix that but aplay Front_Center.wav should finish playing after ca. 3 seconds.

There remains only the AC97/I2S driver as the location of the issue.

I have now checked the register model of jz4730 and jz4740 and there is a handful
of extra bits for the jz4740. Mainly it is possible to control input and output
channel which separately and jz4740 can do fancy things linke swapping byte order
or outputting stereo for mono etc.

Maybe the driver is setting some register under the wrong assumption that it is
a jz4740.

Next, I'll try to dump the AC97 registers in jz4740_i2s_trigger() where everything
should have been set up properly...

Modifying code isn't difficult. We already have a DT compatible for jz4730-i2s and
a ->version field in the device struct. Small differences are already handled
for jz4760 and jz4770 by this mechanism.

BR,
Nikolaus

H. Nikolaus Schaller

unread,
Apr 28, 2021, 2:45:53 PM4/28/21
to Paul Boddie, Discussions about the Letux Kernel, Riccardo Mottola, Lubomir Rintel, Zhou Yanjie, MIPS Creator CI20 Development
s/ping/pin/

>
> So I think we can rule out codec and pinctrl problems as the main blocking point
> for completely stuck communication. It still may happen that there is no sound
> if we fix that but aplay Front_Center.wav should finish playing after ca. 3 seconds.
>
> There remains only the AC97/I2S driver as the location of the issue.
>
> I have now checked the register model of jz4730 and jz4740 and there is a handful
> of extra bits for the jz4740. Mainly it is possible to control input and output
> channel which separately and jz4740 can do fancy things linke swapping byte order

s/which/width/

> or outputting stereo for mono etc.
>
> Maybe the driver is setting some register under the wrong assumption that it is
> a jz4740.
>
> Next, I'll try to dump the AC97 registers in jz4740_i2s_trigger() where everything
> should have been set up properly...
>
> Modifying code isn't difficult. We already have a DT compatible for jz4730-i2s and
> a ->version field in the device struct. Small differences are already handled
> for jz4760 and jz4770 by this mechanism.
>
> BR,
> Nikolaus

s/Nikolaus/Nikolaus, please do more proofreading :)/

>
> --
> You received this message because you are subscribed to the Google Groups "MIPS Creator CI20 Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to mips-creator-ci2...@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/mips-creator-ci20-dev/6CB989ED-5B6D-4C71-9824-FD7DE4172C6D%40goldelico.com.

Paul Boddie

unread,
Apr 28, 2021, 3:39:41 PM4/28/21
to H. Nikolaus Schaller, Discussions about the Letux Kernel, Riccardo Mottola, Lubomir Rintel, Zhou Yanjie, MIPS Creator CI20 Development
On Wednesday, 28 April 2021 20:19:15 CEST H. Nikolaus Schaller wrote:
>
> I have hacked some ioremap() into jz4740_i2s_trigger() to be able to modify
> pinctrl on the fly and read the gpio bits directly.
>
> There is clock activity on both BITCLK and SYNC obviously coming from the
> codec. And switching to ping function 0x2 makes these pins an output.
>
> So I think we can rule out codec and pinctrl problems as the main blocking
> point for completely stuck communication. It still may happen that there is
> no sound if we fix that but aplay Front_Center.wav should finish playing
> after ca. 3 seconds.
>
> There remains only the AC97/I2S driver as the location of the issue.

I would have to look at it properly to have an opinion about it. Is there some
DMA involvement in this as well?

> I have now checked the register model of jz4730 and jz4740 and there is a
> handful of extra bits for the jz4740. Mainly it is possible to control
> input and output channel which separately and jz4740 can do fancy things
> linke swapping byte order or outputting stereo for mono etc.
>
> Maybe the driver is setting some register under the wrong assumption that it
> is a jz4740.
>
> Next, I'll try to dump the AC97 registers in jz4740_i2s_trigger() where
> everything should have been set up properly...
>
> Modifying code isn't difficult. We already have a DT compatible for
> jz4730-i2s and a ->version field in the device struct. Small differences
> are already handled for jz4760 and jz4770 by this mechanism.

Maybe I should take a closer look. I have been slowly working back towards the
Minibook in another project of mine, but this has been proceeding rather
slowly. One thing that will be necessary will be an investigation of DMA
beyond the simple memory-to-memory transfers that I tested, and that might be
informative for both the MMC and I2S peripherals.

Paul


H. Nikolaus Schaller

unread,
Apr 28, 2021, 3:58:55 PM4/28/21
to Paul Boddie, Discussions about the Letux Kernel, Riccardo Mottola, Lubomir Rintel, Zhou Yanjie, MIPS Creator CI20 Development
Hi Paul,

> Am 28.04.2021 um 21:39 schrieb Paul Boddie <pa...@boddie.org.uk>:
>
> On Wednesday, 28 April 2021 20:19:15 CEST H. Nikolaus Schaller wrote:
>>
>> I have hacked some ioremap() into jz4740_i2s_trigger() to be able to modify
>> pinctrl on the fly and read the gpio bits directly.
>>
>> There is clock activity on both BITCLK and SYNC obviously coming from the
>> codec. And switching to ping function 0x2 makes these pins an output.
>>
>> So I think we can rule out codec and pinctrl problems as the main blocking
>> point for completely stuck communication. It still may happen that there is
>> no sound if we fix that but aplay Front_Center.wav should finish playing
>> after ca. 3 seconds.
>>
>> There remains only the AC97/I2S driver as the location of the issue.
>
> I would have to look at it properly to have an opinion about it. Is there some
> DMA involvement in this as well?

Yes... But it looks as if the I2S interface isn't properly initialized and therefore
gets stuck. No interrupt, no timeout no anything. Just waiting after setting up
everything. A register dump seems to indicate that the TX FIFO is being filled.
So maybe even DMA might work in this case but I can't know...

What I found is that there is very special code in the old driver:

https://git.goldelico.com/?p=letux-kernel.git;a=blob;f=sound/soc/jz4740/jz4740-i2s.c;h=c58d9c3c844d242da1a8d357270eec87197b385c;hb=86df48ade42a3e852b10b26f11676da0e8c13ccc#l200

It does some initialization, then a mdelay, a reset and the same again...

But I can't find anything similar here:

https://elixir.bootlin.com/linux/latest/source/sound/soc/jz4740/jz4740-i2s.c#L416

Here, it simply sets the reset bit and writes the new config. Assuming that the
controller reset can be done in one processor write cycle.

Maybe the jz4730 hardware needs more time to reset and hence setting the config
is lost.

But I can't write it by devmem2 either. devmem2 tells that it reads back the right
value but a second devmem has lost the bits...

Another idea is that the I2S module is not clocked properly.

>>
>> Modifying code isn't difficult. We already have a DT compatible for
>> jz4730-i2s and a ->version field in the device struct. Small differences
>> are already handled for jz4760 and jz4770 by this mechanism.
>
> Maybe I should take a closer look. I have been slowly working back towards the
> Minibook in another project of mine, but this has been proceeding rather
> slowly.

:) My work had also stalled for a while...

> One thing that will be necessary will be an investigation of DMA
> beyond the simple memory-to-memory transfers that I tested, and that might be
> informative for both the MMC and I2S peripherals.

That is exactly my plan. To debug I2S + DMA until it works. This can be easily
done from user-space on a booted machine. Then we can try to switch MMC to DMA.

BR,
Nikolaus

H. Nikolaus Schaller

unread,
Apr 29, 2021, 3:50:08 AM4/29/21
to Paul Boddie, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
Ok, the jz4780 has (at least 99%) the same i2s as the jz4740 which has 95% the same
as jz4730. This is good since it means I can compare the same driver code on both...

What I have found in the programming manuals of all jz47* is:

Please set this bit to 1 to stop BIT_CLK when change AICFR.AUSEL and AICFR.BCKD.

But I can't find that in the (new) driver. This might explain why the driver or
devmem2 does not set AUSEL.

So my plan was to compare to CI20.

But it turns out that the CI20 has no sound. We can try to port it from FreeBSD:

https://github.com/freebsd/freebsd-src/blob/master/sys/gnu/dts/mips/ingenic/jz4780.dtsi

But it uses the internal codec:

codec: codec@100200a4 {
compatible = "ingenic,jz4780-codec";
reg = <0x100200a4 0x8>;

clocks = <&cgu JZ4780_CLK_I2SPLL>;
clock-names = "i2s";

};

for which we have no Linux driver :(

BTW: there seem to be two i2s instances on jz4780 (at least from DMA and IRQ) but
there is only one base address.

Cul-de-sac...

BR,
Nikolaus

Maarten ter Huurne

unread,
Apr 29, 2021, 7:32:00 AM4/29/21
to mips-creat...@googlegroups.com
On Thursday, 29 April 2021 09:49:47 CEST H. Nikolaus Schaller wrote:
> [...]
>
> So my plan was to compare to CI20.
>
> But it turns out that the CI20 has no sound. We can try to port it
> from FreeBSD:
>
> https://github.com/freebsd/freebsd-src/blob/master/sys/gnu/
dts/mips/i
> ngenic/jz4780.dtsi
>
> But it uses the internal codec:
>
> codec: codec@100200a4 {
> compatible = "ingenic,jz4780-codec";
> reg = <0x100200a4 0x8>;
>
> clocks = <&cgu JZ4780_CLK_I2SPLL>;
> clock-names = "i2s";
>
> };
>
> for which we have no Linux driver :(

There is a Linux driver for the JZ4770 internal codec, Paul Cercueil is
maintaining it. A quick look at both programming manuals suggests it
won't work as-is, but the 4780 codec is an evolution of the 4770 one, so
a lot of code could be re-used. Register numbers are different, but most
of the names and bit fields within the registers are the same.

By the way, when debugging sound issues on the JZ4770, I found debugfs
very useful. It allows you to inspect the ALSA power management graph
(problems here can also lead to no sound playing) and allows live
inspection of register banks that are accessed via regmap (such as the
codec registers).

Bye,
Maarten



H. Nikolaus Schaller

unread,
Apr 29, 2021, 7:48:37 AM4/29/21
to Maarten ter Huurne, MIPS Creator CI20 Development, Discussions about the Letux Kernel
Hi Maarten,

> Am 29.04.2021 um 13:31 schrieb Maarten ter Huurne <maa...@treewalker.org>:
>
> On Thursday, 29 April 2021 09:49:47 CEST H. Nikolaus Schaller wrote:
>> [...]
>>
>> So my plan was to compare to CI20.
>>
>> But it turns out that the CI20 has no sound. We can try to port it
>> from FreeBSD:
>>
>> https://github.com/freebsd/freebsd-src/blob/master/sys/gnu/
> dts/mips/i
>> ngenic/jz4780.dtsi
>>
>> But it uses the internal codec:
>>
>> codec: codec@100200a4 {
>> compatible = "ingenic,jz4780-codec";
>> reg = <0x100200a4 0x8>;
>>
>> clocks = <&cgu JZ4780_CLK_I2SPLL>;
>> clock-names = "i2s";
>>
>> };
>>
>> for which we have no Linux driver :(
>
> There is a Linux driver for the JZ4770 internal codec, Paul Cercueil is
> maintaining it. A quick look at both programming manuals suggests it
> won't work as-is, but the 4780 codec is an evolution of the 4770 one, so
> a lot of code could be re-used. Register numbers are different, but most
> of the names and bit fields within the registers are the same.

Good to know! So at least this is a good starting point for debugging...

I'll give it a try what happens if we use the ingenic,jz4770-codec on
the CI20.

Alternatively we could check if one of the other codecs (4725, 4740, 4760)
is more similar to find the best starting point.

BTW: there seems to be a typo in the DTS node name/address of jz4770.dtsi

codec: audio-codec@100200a0 {
reg = <0x100200a4 0x8>;

>
> By the way, when debugging sound issues on the JZ4770, I found debugfs
> very useful. It allows you to inspect the ALSA power management graph
> (problems here can also lead to no sound playing) and allows live
> inspection of register banks that are accessed via regmap (such as the
> codec registers).

For the jz4730 there is only an external codec (ak4642). And that appears
to work.

Potential issues so far were with pinctrl (has been verified to be ok).

But there seems to be an initialization bug in jz4740-i2s. So I wonder
how it can work on some other boards. But the issue (clock dividers need
to be set up before being able to write to JZ_REG_AIC_CONF) may be
jz4730 specific.

And somehow DMA seems to be stuck. But we know that DMA on the jz4730
isn't working yet...

BR and thanks,
Nikolaus

Maarten ter Huurne

unread,
Apr 29, 2021, 8:15:21 AM4/29/21
to H. Nikolaus Schaller, MIPS Creator CI20 Development, Discussions about the Letux Kernel
On Thursday, 29 April 2021 13:48:13 CEST H. Nikolaus Schaller wrote:
> > Am 29.04.2021 um 13:31 schrieb Maarten ter Huurne
> > <maa...@treewalker.org>:>
> > There is a Linux driver for the JZ4770 internal codec, Paul Cercueil
> > is maintaining it. A quick look at both programming manuals
> > suggests it won't work as-is, but the 4780 codec is an evolution of
> > the 4770 one, so a lot of code could be re-used. Register numbers
> > are different, but most of the names and bit fields within the
> > registers are the same.
> Good to know! So at least this is a good starting point for
> debugging...
>
> I'll give it a try what happens if we use the ingenic,jz4770-codec on
> the CI20.

You would have to at least update the register number enum at the top,
since almost all of the registers got renumbered.

> Alternatively we could check if one of the other codecs (4725, 4740,
> 4760) is more similar to find the best starting point.

I would expect 4770 to be the most similar, since it's the closest on
the timeline and it's a full-featured SoC like the 4780 is. But it
wouldn't hurt to check.

> BTW: there seems to be a typo in the DTS node name/address of
> jz4770.dtsi
>
> codec: audio-codec@100200a0 {
> reg = <0x100200a4 0x8>;

I'm not sure whether that's a typo or just the address being rounded
down. I'll ask Paul.

Bye,
Maarten



Paul Boddie

unread,
Apr 29, 2021, 6:20:50 PM4/29/21
to H. Nikolaus Schaller, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
On Thursday, 29 April 2021 09:49:47 CEST H. Nikolaus Schaller wrote:
>
> Ok, the jz4780 has (at least 99%) the same i2s as the jz4740 which has 95%
> the same as jz4730. This is good since it means I can compare the same
> driver code on both...
>
> What I have found in the programming manuals of all jz47* is:
>
> Please set this bit to 1 to stop BIT_CLK when change AICFR.AUSEL and
> AICFR.BCKD.
>
> But I can't find that in the (new) driver. This might explain why the driver
> or devmem2 does not set AUSEL.

It starts to sound like I have to investigate a few different peripherals now.
:-)

> So my plan was to compare to CI20.
>
> But it turns out that the CI20 has no sound. We can try to port it from
> FreeBSD:
>
> https://github.com/freebsd/freebsd-src/blob/master/sys/gnu/dts/mips/ingenic
> /jz4780.dtsi
>
> But it uses the internal codec:
>
> codec: codec@100200a4 {
> compatible = "ingenic,jz4780-codec";
> reg = <0x100200a4 0x8>;
>
> clocks = <&cgu JZ4780_CLK_I2SPLL>;
> clock-names = "i2s";
>
> };
>
> for which we have no Linux driver :(

Yes, this is very strange. Although there are device tree nodes in the 3.18
kernel files, I don't find the corresponding drivers. There is audio support
in the HDMI driver, but since I use a DVI monitor, I never tried to use the
audio on the CI20 since the cable won't be passing on any audio signal. But I
imagine that there must be HDMI audio support because there was some effort to
get video playback working with a special version of MPlayer, as I recall.

> BTW: there seem to be two i2s instances on jz4780 (at least from DMA and
> IRQ) but there is only one base address.
>
> Cul-de-sac...

Indeed, I don't see how it could be working unless some kind of generic I2S
support is clever enough, and the hardware is generic enough, for it all to
"just work". The documentation isn't very helpful about the audio socket on
the board, however:

https://www.elinux.org/CI20_Hardware#Audio

Paul


H. Nikolaus Schaller

unread,
Apr 30, 2021, 6:33:07 AM4/30/21
to Maarten ter Huurne, MIPS Creator CI20 Development, Discussions about the Letux Kernel, Paul Boddie
Hi Maarten,

> Am 29.04.2021 um 14:15 schrieb Maarten ter Huurne <maa...@treewalker.org>:
>
> On Thursday, 29 April 2021 13:48:13 CEST H. Nikolaus Schaller wrote:
>>> Am 29.04.2021 um 13:31 schrieb Maarten ter Huurne
>>> <maa...@treewalker.org>:>
>>> There is a Linux driver for the JZ4770 internal codec, Paul Cercueil
>>> is maintaining it. A quick look at both programming manuals
>>> suggests it won't work as-is, but the 4780 codec is an evolution of
>>> the 4770 one, so a lot of code could be re-used. Register numbers
>>> are different, but most of the names and bit fields within the
>>> registers are the same.
>> Good to know! So at least this is a good starting point for
>> debugging...
>>
>> I'll give it a try what happens if we use the ingenic,jz4770-codec on
>> the CI20.
>
> You would have to at least update the register number enum at the top,
> since almost all of the registers got renumbered.

I have copied the jz4770 driver, added Kconfig&Makefile, renamed everything
to jz4780 and added some DTS nodes for jz4780.dtsi and ci20.dts.

As expected I get:

[ 6.233327] jz4780-codec 100200a4.audio-codec: Unable to sync register 0x1. -145
[ 6.236454] asoc-simple-card sound: ASoC: no sink widget found for MIC
[ 6.236475] asoc-simple-card sound: ASoC: Failed to add route Mic -> direct -> MIC
[ 6.236489] asoc-simple-card sound: ASoC: no source widget found for OUTL
[ 6.236498] asoc-simple-card sound: ASoC: Failed to add route OUTL -> direct -> Speaker
[ 6.236509] asoc-simple-card sound: ASoC: no source widget found for OUTR
[ 6.236518] asoc-simple-card sound: ASoC: Failed to add route OUTR -> direct -> Speaker
[ 6.236530] asoc-simple-card sound: ASoC: no sink widget found for INL
[ 6.236539] asoc-simple-card sound: ASoC: Failed to add route LOUT -> direct -> INL
[ 6.236551] asoc-simple-card sound: ASoC: no sink widget found for INR
[ 6.236559] asoc-simple-card sound: ASoC: Failed to add route ROUT -> direct -> INR

So general setup works and I'll dig into the register numbers to see if I can
get the codec starting...

>> Alternatively we could check if one of the other codecs (4725, 4740,
>> 4760) is more similar to find the best starting point.
>
> I would expect 4770 to be the most similar, since it's the closest on
> the timeline and it's a full-featured SoC like the 4780 is. But it
> wouldn't hurt to check.
>
>> BTW: there seems to be a typo in the DTS node name/address of
>> jz4770.dtsi
>>
>> codec: audio-codec@100200a0 {
>> reg = <0x100200a4 0x8>;
>
> I'm not sure whether that's a typo or just the address being rounded
> down. I'll ask Paul.

I am not sure but AFAIR, latest dtbscheck requires and checks the @ value
with the reg entry. At least for I2C client addresses.

BR and thanks,
Nikolaus

H. Nikolaus Schaller

unread,
Apr 30, 2021, 6:45:57 AM4/30/21
to Paul Boddie, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
Hi Paul,

> Am 30.04.2021 um 00:20 schrieb Paul Boddie <pa...@boddie.org.uk>:
>
> On Thursday, 29 April 2021 09:49:47 CEST H. Nikolaus Schaller wrote:
>>
>> Ok, the jz4780 has (at least 99%) the same i2s as the jz4740 which has 95%
>> the same as jz4730. This is good since it means I can compare the same
>> driver code on both...
>>
>> What I have found in the programming manuals of all jz47* is:
>>
>> Please set this bit to 1 to stop BIT_CLK when change AICFR.AUSEL and
>> AICFR.BCKD.
>>
>> But I can't find that in the (new) driver. This might explain why the driver
>> or devmem2 does not set AUSEL.
>
> It starts to sound like I have to investigate a few different peripherals now.
> :-)

Indeed...

I seem to have the AUSEL fixed. The problem is that the clock divider must be
initialized first. This does not happen in jz4740_i2s_dai_probe() but
jz4740_i2s_hw_params().

So I only set the JZ_AIC_CONF_RESET in jz4740_i2s_dai_probe() and have moved
the AUSEL setup into jz4740_i2s_hw_params() which seems to be a more logical
place. There, I also have added a condition for the jz4730 so that it does
not try to set bits that were introduced by jz4740 AIC.

>
>> So my plan was to compare to CI20.
>>
>> But it turns out that the CI20 has no sound. We can try to port it from
>> FreeBSD:
>>
>> https://github.com/freebsd/freebsd-src/blob/master/sys/gnu/dts/mips/ingenic
>> /jz4780.dtsi
>>
>> But it uses the internal codec:
>>
>> codec: codec@100200a4 {
>> compatible = "ingenic,jz4780-codec";
>> reg = <0x100200a4 0x8>;
>>
>> clocks = <&cgu JZ4780_CLK_I2SPLL>;
>> clock-names = "i2s";
>>
>> };
>>
>> for which we have no Linux driver :(
>
> Yes, this is very strange. Although there are device tree nodes in the 3.18
> kernel files, I don't find the corresponding drivers. There is audio support
> in the HDMI driver, but since I use a DVI monitor, I never tried to use the
> audio on the CI20 since the cable won't be passing on any audio signal. But I
> imagine that there must be HDMI audio support because there was some effort to
> get video playback working with a special version of MPlayer, as I recall.

Well, HDMI audio may be separated. I haven't tried either since I use a 7 inch
touch-screen tablet monitor which has no speakers...

>
>> BTW: there seem to be two i2s instances on jz4780 (at least from DMA and
>> IRQ) but there is only one base address.
>>
>> Cul-de-sac...
>
> Indeed, I don't see how it could be working unless some kind of generic I2S
> support is clever enough, and the hardware is generic enough, for it all to
> "just work". The documentation isn't very helpful about the audio socket on
> the board, however:
>
> https://www.elinux.org/CI20_Hardware#Audio

Here, the jz4780 data sheet gives some background. The codec is fully integrated
and it just needs some passive components and a jack to get stereo headset
out and microphone in.

So the I2S happens fully inside the jz4780 SoC in this case.

On the Alpha 400 we have an external ak4642 codec so we see the I2S on external
pins. For that a driver exists and it works. At least I could verify that it
provides bit clock and sync clock.

At the moment my plan is to experiment with the hints by Maarten to try
to make the jz4780 codec driver work.

Then, my hope is to understand the interaction of the i2s driver with DMA which
should be exactly the same between jz4730 and jz4780. The different codecs are
then most likely outside the remaining problems.

BR,
Nikolaus

H. Nikolaus Schaller

unread,
Apr 30, 2021, 10:12:25 AM4/30/21
to Maarten ter Huurne, MIPS Creator CI20 Development, Discussions about the Letux Kernel, Paul Boddie
Hi Marten,
Well, the issue is a little earlier. The AIC can't write successfully to the codec
through RGADW (0x100200a4).

RGADW.RGWR stays 1 until there is a timeout in jz4780_codec_io_wait(). So I think
clocks or some other initialization is missing or not running properly or in a wrong
sequence (like I had for the jz4730).

An indication (I had deleted from the log) is that jz4740_i2s_dai_probe is called
*after* jz4780-codec 100200a4.audio-codec probing. So the whole I2S subsystem is
not initialized when jz4780_codec wants to access the codec.

There is one hint: "the CODEC’s internal control and configure registers can be accessed by write/read these memory mapped registers using 12 MHz clock."

So there must be some 12 MHz clock running to be able to access the codec?

>
>>> Alternatively we could check if one of the other codecs (4725, 4740,
>>> 4760) is more similar to find the best starting point.
>>
>> I would expect 4770 to be the most similar, since it's the closest on
>> the timeline and it's a full-featured SoC like the 4780 is. But it
>> wouldn't hurt to check.

Mapping the registers is >80% similar. The jz4780 has split some registers into two
(e.g. SR -> SR, SR2) and replaced some (e.g. AGC1..5). But nothing which can be solved.

BR and thanks,
Nikolaus

H. Nikolaus Schaller

unread,
Apr 30, 2021, 11:56:22 AM4/30/21
to Paul Boddie, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
Hi Paul,

> Am 30.04.2021 um 00:20 schrieb Paul Boddie <pa...@boddie.org.uk>:
>
> On
>>
>>
>> But it uses the internal codec:
>>
>> codec: codec@100200a4 {
>> compatible = "ingenic,jz4780-codec";
>> reg = <0x100200a4 0x8>;
>>
>> clocks = <&cgu JZ4780_CLK_I2SPLL>;
>> clock-names = "i2s";

as written previously, I have found that I can't read/write the
codec registers of the jz4780. Most likely the codec clock is set up wrongly...

PM says:

14.19 SYS_CLK turn-off and turn-on

The main clock of CODEC is called SYS_CLK, which is generated in CPM module
and called MCLK. During the SLEEP mode and the complete power-down mode,
the main clock SYS_CLK may be stopped to reduce the power consumption t
the leakage currents only. In other modes, the main clock SYS_CLK must not
be stopped.

So referencing JZ4780_CLK_I2SPLL may be wrong...

But what I could not find yet is which clock the MCLK is. I only find a CIMMCLK
(camera). And PCMCLK (PCM).

It should be a 12 (or 13) MHz clock according to description of other registers.

Any ideas as you are a CGU specialist?

BR and thanks,
Nikolaus

H. Nikolaus Schaller

unread,
May 1, 2021, 2:52:12 AM5/1/21
to Paul Boddie, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
Hi Paul,

> Am 30.04.2021 um 00:20 schrieb Paul Boddie <pa...@boddie.org.uk>:
>
> Yes, this is very strange. Although there are device tree nodes in the 3.18
> kernel files, I don't find the corresponding drivers. There is audio support
> in the HDMI driver, but since I use a DVI monitor, I never tried to use the
> audio on the CI20 since the cable won't be passing on any audio signal. But I
> imagine that there must be HDMI audio support because there was some effort to
> get video playback working with a special version of MPlayer, as I recall.

I have looked through the 3.18 kernel and there is an "old style sound board file":

sound/soc/jz4780/ci20.c

which is compatible = "ingenic,ci20-audio"

This defines two dai links. Apparently one which is called "headphones" and one
called "hdmi". Both seem to use the jz4780-i2s. Difference is in the codecs:

dw-hdmi-audio vs. jz4780-codec.

So the hdmi audio seems to be part of a more general ci20 audio driver than
"simple-audio-card". This raises another question: should we forward port
the ci20-audio.c driver or try to make simple-audio-card work?

Anyways the codec driver can be found in sound/soc/codecs/jz4780.c

So I will replace the attempt to modify the jz4770 driver to use the one
from the 3.18 kernel...

BR,
Nikolaus



H. Nikolaus Schaller

unread,
May 1, 2021, 3:32:02 PM5/1/21
to Paul Boddie, Maarten ter Huurne, MIPS Creator CI20 Development, Lubomir Rintel, Riccardo Mottola, Zhou Yanjie, Discussions about the Letux Kernel
Hi Paul and Maarten,
Ok, that was easier than it initially looked. I had to cross-port some
minor improvements from the jz4770 driver to the jz4780 and the main task was
to change the soc_codec etc. to soc_component and track how to get the
struct pointer dereferencing right again.

One major observation is that the jz4780 codec driver turns on clocks before
reading/writing the ragmap backed up registers. This is not part of the jz4770
code and may be the reason why my initial attempts with that driver failed.

The more challenging part was to make the ci20-audio (board) driver work since
it initializes both channels for the headset and HDMI audio of the CI20.

Fortunately, the dw-hdmi-i2s-audio driver is already upstream so I only had to
configure and compile it.

I haven't tried if I really get sound (have to find a 2.5mm headset first and
my HDMI monitor has no speakers), but this is what I can see:

root@letux:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: ci20 [ci20], device 0: headphones 100200a4.audio-codec-0 [headphones 100200a4.audio-codec-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: ci20 [ci20], device 1: hdmi i2s-hifi-1 [hdmi i2s-hifi-1]
Subdevices: 1/1
Subdevice #0: subdevice #0
root@letux:~# amixer
Simple mixer control 'Master',0
Capabilities: pvolume cvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 31 Capture 0 - 63
Front Left: Playback 25 [81%] [on] Capture 51 [81%]
Front Right: Playback 25 [81%] [on] Capture 51 [81%]
Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right
Limits: Playback 0 - 31
Mono:
Front Left: Playback 22 [71%] [on]
Front Right: Playback 22 [71%] [on]
Simple mixer control 'Mic',0
Capabilities: cvolume cvolume-joined cswitch cswitch-joined
Capture channels: Mono
Limits: Capture 0 - 7
Mono: Capture 0 [0%] [off]
Simple mixer control 'ADC',0
Capabilities: cenum
Items: 'AIP1' 'AIP2'
Item0: 'AIP1'
root@letux:~#

There is also a headset detect in /dev/input/event*.

From an architecture point if view a key question will be if we want
to have the CI20 board file or if we can replace it by the simple-audio-card
driver like the lb60 did a while ago:

91c7db5e7c652 "ASoC: jz4740: Drop lb60 board code"

I'll consolidate these changes a little and post them here for all CI20
users. Maybe someone wants to volunteer to help upstreaming (defining the
DAI links should IMHO be done better through device tree) ...

But it looks as if I can now (maybe after fixing some smaller bugs)
compare CI20 sound to Alpha 400 sound and find out differences in
i2s and DMA which seem the blocking components for Alpha 400.

BR,
Nikolaus

Reply all
Reply to author
Forward
0 new messages