[openfirmware] [commit] r2512 - cpu/arm/olpc/1.75 dev/hdaudio
repository service
svn at openfirmware.info
Fri Sep 16 02:40:48 CEST 2011
Author: wmb
Date: Fri Sep 16 02:40:48 2011
New Revision: 2512
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2512
Log:
OLPC XO-1.75 - checkpoint of revised audio code. May still have rough edges.
Modified:
cpu/arm/olpc/1.75/alc5631.fth
cpu/arm/olpc/1.75/sound.fth
dev/hdaudio/noiseburst.fth
dev/hdaudio/test.fth
Modified: cpu/arm/olpc/1.75/alc5631.fth
==============================================================================
--- cpu/arm/olpc/1.75/alc5631.fth Fri Sep 16 01:34:00 2011 (r2511)
+++ cpu/arm/olpc/1.75/alc5631.fth Fri Sep 16 02:40:48 2011 (r2512)
@@ -5,38 +5,53 @@
: adc-off ( -- ) h# 0c00 h# 3a codec-clr ;
: dac-on ( -- ) h# 0300 h# 3a codec-set ;
: dac-off ( -- ) h# 0300 h# 3a codec-clr ;
+: adc+dac-on ( -- ) h# 0f00 h# 3a codec-set ;
+
+: set-routing ( -- )
+ h# c0c0 h# 02 codec-set \ SPKMIXLR -> SPKVOLLR, muted
+ h# c0c0 h# 04 codec-set \ OUTMIXLR -> HPOVOLLR, muted
+\ h# a080 h# 06 codec! \ AXO1/AXO2 channel volume select OUTMIXER,0DB by default
+ h# b0b0 h# 14 codec! \ Record Mixer source from Mic1/Mic2 by default
+\ h# 5500 h# 22 codec! \ Mic1/Mic2 boost 20DB by default (done in set-default-gains)
+ h# dfc0 h# 1a codec! \ DACL -> OUTMIXL - c0 is "don't change it" per datasheet 0.91
+ h# dfc0 h# 1c codec! \ DACR -> OUTMIXR - c0 is "don't change it" per datasheet 0.91
+ h# d8d8 h# 28 codec! \ DACLR -> SPKMIXLR - 808 is "don't change it" per datasheet 0.91
+ h# 6c00 h# 2a codec! \ unmute SPKVOLL -> SPOLMIX, SPKVOLR -> SPORMIX, mute L>R, R>L, and L/R>MONO
+ h# 0f18 h# 4a codec! \ (undocumented bit 11) enables HP zero-cross detection
+
+ h# 0000 h# 2c codec! \ SPOxMIX -> SPKRMUX, HPOVOL -> HPMUX
+;
: codec-on ( -- )
0 0 codec! \ Reset
- b# 1010.0000.0001.1101 h# 3c codec! \ All on except AX and MONO
- d# 110 ms
- b# 1110.0000.0001.1101 h# 3c codec! \ Fast VREF control
- d# 100 ms
+ b# 1010.0000.0000.0000 h# 3c codec! \ All on except AX and MONO
+ d# 80 ms
+ b# 1110.0000.0000.0000 h# 3c codec! \ Fast VREF control
+
+ set-routing
+
+ h# 8001 h# 34 codec! \ Slave mode, 16 bits, left justified, exchange L and R on playback
+
+ \ The speaker gain ratio must be <= the ratio of SPKVDD to AVDD.
+ \ In our system, SPKVDD is 5V and AVDD is 3.3V, so we need a gain ratio <= 1.51 .
+ \ The value 3 gives a ratio of 1.44, and value 4 gives a ratio of 1.56 . We use 3.
+ h# 3e00 h# 40 codec! \ Speaker Amp Ratio GAIN is 1.44x, no HPFs
- h# 8001 h# 34 codec! \ Slave mode, 16 bits, left justified
+ h# 0000 h# 42 codec! \ Use MCLK, not PLL
+\ b# 1110.1100.1001.0000 h# 52 codec! \ Protection on
+\ h# 4000 h# 56 codec! \ HP depop by register control
h# 1010 h# 38 codec! \ Divisors; the values in this register don't seem to make much
\ difference unless you set the divisors to very high values.
-
+;
+: elided ( -- )
\ The ADC and DAC will be turned on as needed by adc-on and dac-on, after
\ the BCLK clock from the SoC is on. If you turn on the ADC when BCLK is
\ not clocking, the ADC often doesn't output any data.
b# 1001.0000.1110.0000 h# 3a codec! \ All on except ADC and DAC
b# 1111.1100.0011.1100 h# 3b codec! \ All on except PLL
b# 1111.1100.0000.0000 h# 3e codec! \ AXI and MONO IN off
-
-\ h# 8c00 h# 40 codec! \ Speaker Amp Auto Ratio GAIN, use HPFs
- h# 4e00 h# 40 codec! \ Speaker Amp Ratio GAIN is 1.44x, no HPFs
- h# 0000 h# 42 codec! \ Use MCLK, not PLL
-\ b# 1110.1100.1001.0000 h# 52 codec! \ Protection on
- h# 8000 h# 56 codec! \ HP depop by register control
-;
-: codec-off ( -- )
- 0 h# 3a codec! \ All off
- 0 h# 3b codec! \ All off
- 0 h# 3c codec! \ All off
- 0 h# 3e codec! \ All off
;
: mic-bias-off ( -- ) h# 000c h# 3b codec-clr ;
: mic-bias-on ( -- ) h# 000c h# 3b codec-set ;
@@ -46,60 +61,204 @@
: mic2-high-bias ( -- ) h# 08 h# 22 codec-clr mic-bias-on ; \ 0.90*AVDD, e.g. 3V with AVDD=3.3V
: mic2-low-bias ( -- ) h# 08 h# 22 codec-set mic-bias-on ; \ 0.75*AVDD, e.g. 2.5V with AVDD=3.3V
+: depop! ( value -- ) h# 54 codec! ;
+: pwr3a! ( value -- ) h# 3a codec! ;
+: pwr3b! ( value -- ) h# 3b codec! ;
+: pwr3c! ( value -- ) h# 3c codec! ;
+: pwr3e! ( value -- ) h# 3e codec! ;
+: depop( ( current -- )
+ h# 0000 h# 5c codec! \ Disable ZCD
+ h# 0710 h# 4a codec! \ Bit 11=0 disables HP zero-cross detection. 71 is reserved bits.
+ d# 10 ms
+ ( current ) h# 56 codec-i! \ Index 56 - depop current control
+;
+: )depop ( -- )
+ h# 04c0 h# 5c codec! \ Power on ZCD, enable ZCD for SPOL/R
+ h# 0f10 h# 4a codec! \ Bit 11 enables HP zero-cross detection. 71 is reserved bits
+;
+
+0 value headphones-on?
+0 value speakers-on?
+
+: mute-speakers ( -- ) h# 8080 2 codec-set ;
+: unmute-speakers ( -- ) h# 8080 2 codec-clr ;
+
\ The range is from -46.5 db to +12 dB
-: gain>lr-12 ( db -- true | regval false )
+: gain>lr-12 ( db -- regval on? )
d# 12 min ( db' )
2* 3 / ( steps ) \ Converts -46.5 .. 12 db to -31 .. 8 steps
dup d# -31 < if ( steps )
- drop true
+ drop h# 2727 ( regval )
+ false ( regval on? )
else ( steps )
8 swap - ( -steps )
0 max ( clipped-steps )
dup 8 lshift or ( regval )
- false
+ true ( regval on? )
then
;
+: set-speaker-volume ( n -- )
+ gain>lr-12 to speakers-on? h# bfbf 2 codec-field
+;
+
+: mute-headphones ( -- ) h# 8080 4 codec-set ;
+: unmute-headphones ( -- ) h# 8080 4 codec-clr ;
+
\ The range is from -46.5 db to 0 dB
-: gain>lr ( db -- true | regval false )
+: gain>lr ( db -- regval on? )
0 min ( db' )
2* 3 / ( steps ) \ Converts -46.5 .. 12 db to -31 .. 8 steps
dup d# -31 < if ( steps )
- drop true
+ drop h# 1f1f ( regval )
+ false ( regval on? )
else ( steps )
0 swap - ( -steps )
0 max ( clipped-steps )
dup 8 lshift or ( regval )
- false
+ true ( regval on? )
then
;
-
-\ This sets up a simple routing from the DAC to the headphone and speaker outputs
-: output-config ( -- )
- h# df00 h# 1a codec! \ DACL -> OUTMIXL
- h# df00 h# 1c codec! \ DACR -> OUTMIXR
- h# 4040 h# 04 codec-set \ OUTMIXLR -> HPOVOLLR
- h# d0d0 h# 28 codec! \ DACLR -> SPKMIXLR
- h# 4040 h# 02 codec-set \ SPKMIXLR -> SPKVOLLR
- h# 9000 h# 2a codec! \ SPKVOLL -> SPOLMIX, SPKVOLR -> SPORMIX
- h# 0000 h# 2c codec! \ SPOxMIX -> SPKRMUX, HPOVOL -> HPMUX
+: set-headphone-volume ( n -- )
+ gain>lr to headphones-on? h# 9f9f 4 codec-field
;
-: mute-speakers ( -- ) h# 8080 2 codec-set ;
-: set-speaker-volume ( n -- ) \ DONE
- gain>lr-12 if h# 8080 then h# bfbf 2 codec-field
+: codec-off ( -- )
+ mute-speakers
+ mute-headphones
+ 0 h# 3a codec! \ All off
+ 0 h# 3b codec! \ All off
+ 0 h# 3c codec! \ All off
+ 0 h# 3e codec! \ All off
;
-: mute-headphones ( -- ) h# 8080 4 codec-set ;
-: set-headphone-volume ( n -- ) \ DONE
- gain>lr if h# 8080 then h# 9f9f 4 codec-field
+
+: hp-powerup-depop ( -- )
+ \ powerup depop
+ h# 303e depop( \ App note says 303f, engineer says to use 303e
+ h# e01c pwr3c! \ 1c powers on charge pump, HP Amp L/R
+ h# 8080 depop! \ Power on HP Soft Generator, (datasheet says 80 bit is "reserved-0", engineer says datasheet is wrong)
+ d# 100 ms
+ h# e01e pwr3c! \ Now put HP output in normal, not depop, mode
+ )depop
+
+ \ unmute depop
+ h# 302f depop( \ This is the only case where 10 ms delay is actually needed
+ h# c003 depop! \ Power on HP Soft Generator, HP Softgen Trigger, ena HPOL/R depop
+ unmute-headphones
+ d# 160 ms
+ )depop
+;
+: hp-powerdown-depop ( -- )
+ \ mute depop
+ h# 302f depop(
+ h# c003 depop! \ Power on HP Soft Generator, HP Softgen Trigger, ena HPOL/R depop
+ mute-headphones
+ d# 150 ms
+ )depop
+
+ \ powerdown depop
+ h# 303f depop(
+ h# c030 depop! \ ..30 enables HPOL/R startup, disables HPOL/R depop
+ d# 75 ms
+ h# 8030 depop! \ !4000 powers down HP softgen trigger
+ h# e01c pwr3c! \ !2 puts HP output in depop mode
+ h# 80b0 depop!
+ d# 80 ms
+ h# 8000 depop! \ !30 disables HPOL/R startup
+ h# e000 pwr3c! \ !1c powers off charge pump, HP Amp L/R
+ )depop
+;
+
+: open-common ( -- )
+ h# 8080 h# 3a codec-set \ Power on I2S, DAC ref (which is also used for ADC according to the engineer)
+;
+: close-common ( -- )
+ h# 8080 h# 3a codec-clr \ Power off I2S, DAC ref
+\ h# 0000 pwr3b! \ Power off PLL
+;
+: open-out-specific ( -- )
+ h# 0060 h# 3a codec-set \ Power on DAC to mixer
+ speakers-on? if h# 1000 h# 3a codec-set then \ Power on ClassD amp
+ speakers-on? if h# c000 h# 3e codec-set then \ Power on SPKL/RVOL
+ headphones-on? if h# 0c00 h# 3e codec-set then \ Power on HPOVOLL/R
+\ h# 0300 h# 3a codec-set \ Power on DACL/R - defer until dac-on is called by start-audio-out or out-in
+ h# c000 pwr3b! \ Power on OUTMIXL/R
+ speakers-on? if h# 3000 h# 3b codec-set then \ Power on SPKMIXL/R
+
+ speakers-on? if unmute-speakers then
+ headphones-on? if hp-powerup-depop then
+;
+
+: open-out ( -- )
+ open-common
+ open-out-specific
+;
+
+: close-out-specific ( -- )
+ speakers-on? if mute-speakers then
+ headphones-on? if hp-powerdown-depop then
+
+ h# f000 h# 3b codec-clr \ Power off OUTMIXL/R, SPKMIXL/R
+ h# 0300 h# 3a codec-clr \ Power off DACs
+ h# cc00 h# 3e codec-clr \ Power off SPKL/RVOL, HPOVOLL/R
+ h# 1060 h# 3a codec-clr \ Power off ClassD amp, DAC to mixer
+;
+: close-out ( -- )
+ close-out-specific
+ close-common
+;
+
+: adc-source ( value -- ) h# c000 h# 4a codec-field ;
+: adc-stereo ( -- ) 0 adc-source ; \ L->L, R->R
+: adc-mono-left ( -- ) h# 4000 adc-source ; \ L->L+R
+: adc-mono-right ( -- ) h# 8000 adc-source ; \ R->L+R
+: adc-stereo-reversed ( -- ) h# c000 adc-source ; \ L->R, R->L (channels swapped)
+
+: open-in-specific ( -- )
+ h# 000c h# 3b codec-set \ Power on MIC1/2 bias
+ adc-stereo
+ h# 0c00 h# 3b codec-set \ Power on RECMIXLR
+ h# 0030 h# 3b codec-set \ Power on MIC1/2 boost gain
+\ h# 0c00 h# 3a codec-set \ Power on ADCL/R - defer until adc-on is called by audio-in or out-in
+;
+: open-in ( -- )
+\ h# 46f0 h# 44 codec! \ pll: 256000 -> 2048000 ??? why is this different from playback? - 8khz record?
+ open-common
+ open-in-specific
+;
+
+: close-in-specific ( -- )
+ h# 0c00 h# 3a codec-clr \ Power off ADCL/R
+ h# 0030 h# 3b codec-clr \ Power off MIC1/2 boost gain
+ h# 0c0c h# 3b codec-clr \ Power off RECMIXLR, MIC1/2 bias
+;
+: close-in ( -- )
+ close-in-specific
+ close-common
+;
+
+: open-out-in ( -- )
+ open-common
+ open-out-specific
+ open-in-specific
+;
+
+: close-out-in ( -- )
+ close-in-specific
+ close-out-specific
+ close-common
;
false value force-speakers?
: set-volume ( n -- )
+ mute-speakers mute-headphones \ Start with both muted, will be unmuted later
headphones-inserted? ( force-speakers? 0= and ) if
- set-headphone-volume mute-speakers
+ d# 30 - set-headphone-volume
+ true false
else
- set-speaker-volume mute-headphones
+ set-speaker-volume
+ false true
then
+ to speakers-on? to headphones-on?
;
d# 0 constant default-adc-gain \ 0 dB - range is -96.625 to +28.5
d# 0 constant default-dac-gain \ 0 dB - range is -96.625 to +28.5
@@ -108,9 +267,9 @@
d# -10 constant default-headphone-volume \ -10 dB - range is -46.5 to 0
: speakers-on ( -- ) default-speaker-volume set-speaker-volume ;
-: speakers-off ( -- ) d# -100 set-speaker-volume ;
+: speakers-off ( -- ) d# -100 set-speaker-volume ;
: headphones-on ( -- ) default-headphone-volume set-headphone-volume ;
-: headphones-off ( -- ) d# -100 set-headphone-volume ;
+: headphones-off ( -- ) d# -100 set-headphone-volume ;
: adc-mute-all ( -- ) h# f0f0 h# 14 codec! ;
: adc-mute-mic ( -- ) h# 4040 h# 14 codec-set ;
@@ -126,28 +285,40 @@
: outmix-mute-recmix ( -- ) h# 8000 dup h# 1a codec-set h# 1c codec-set ;
: outmix-unmute-recmix ( -- ) h# 8000 dup h# 1a codec-clr h# 1c codec-clr ;
-: gain>lr-3/8 ( -- lrgain boost )
- d# 28 min
- dup 0>= if ( n )
+: attenuation-3/8 ( db -- lrgain boost )
+ dup d# -96 <= if ( db )
+ drop ( )
+ h# ffff h# 8080 ( lrgain boost-muted )
+ else ( db )
+ negate 8 3 */ ( steps )
+ dup bwjoin ( lrgain )
+ 0 ( lrgain boost )
+ then ( lrgain boost )
+;
+: gain>lr-3/8 ( db -- lrgain boost )
+ d# 28 min ( db )
+ dup 0>= if ( db )
8 3 */ ( boost ) \ Convert to .375 dB increments
0 swap ( lrgain boost )
- else ( n )
- dup d# -96 <= if ( n )
- drop ( )
- h# ffff h# 8080 ( lrgain boost )
- else ( n )
- negate 8 3 */ ( steps )
- dup bwjoin ( lrgain )
- 0 ( lrgain boost )
- then ( lrgain boost )
- then ( lrgain boost )
+ else ( db )
+ attenuation-3/8 ( lrgain boost )
+ then ( lrgain boost )
;
-: set-dac-gain ( n -- )
+: set-dac-gain ( db -- )
dup d# -96 < if outmix-mute-dac else outmix-unmute-dac then
gain>lr-3/8 h# 0c codec! h# 10 codec!
;
-: set-adc-gain ( n -- )
- gain>lr-3/8 h# 12 codec! h# 16 codec!
+: gain>lr-3/2+3/8 ( db -- lrgain boost )
+ d# 28 min ( db )
+ dup 0>= if ( db )
+ 2 3 */ ( boost ) \ Convert to 1.5 dB increments
+ 0 swap ( lrgain boost )
+ else ( db )
+ attenuation-3/8 ( lrgain boost )
+ then ( lrgain boost )
+;
+: set-adc-gain ( db -- )
+ gain>lr-3/2+3/8 h# 12 codec! h# 16 codec!
;
: mic1-balanced ( -- ) h# 8000 h# 8000 h# 0e codec-field ;
: mic1-single-ended ( -- ) 0 h# 8000 h# 0e codec-field ;
@@ -178,7 +349,6 @@
: mic+0db ( -- ) 0 set-mic-gain ;
: mic+20db ( -- ) d# 20 set-mic-gain ;
: set-default-gains ( -- )
- output-config
headphones-inserted? ( force-speakers? 0= and ) if
headphones-on
speakers-off
Modified: cpu/arm/olpc/1.75/sound.fth
==============================================================================
--- cpu/arm/olpc/1.75/sound.fth Fri Sep 16 01:34:00 2011 (r2511)
+++ cpu/arm/olpc/1.75/sound.fth Fri Sep 16 02:40:48 2011 (r2512)
@@ -112,8 +112,7 @@
0 d# 18 lshift or \ External clock - slave configuration (Rx is master)
0 d# 17 lshift or \ Sample on rising edge of clock
-\ Empirically, this needs to be backwards from what we think it should be
- 0 d# 16 lshift or \ Active high frame sync (should be active low, but that gives backwards results)
+ 1 d# 16 lshift or \ Active low frame sync (I2S standard)
d# 31 d# 4 lshift or \ Frame sync period
1 d# 2 lshift or \ Flush the FIFO
@@ -259,11 +258,6 @@
: dma-alloc ( len -- adr ) " dma-alloc" $call-parent ;
: dma-free ( adr len -- ) " dma-free" $call-parent ;
-: open-in ( -- ) ;
-: close-in ( -- ) ;
-: open-out ( -- ) ;
-: close-out ( -- ) ;
-
: wait-out ( -- )
buf-timeout 0 do
1 ms h# a0 adma@ 1 and ?leave
@@ -292,6 +286,7 @@
stop-out-ring
uninstall-playback-alarm
false to playing?
+ close-out
;
: out-ready? ( -- flag )
@@ -387,7 +382,7 @@
disable-sspa-rx ( actual )
reset-rx ( actual )
;
-: read ( adr len -- actual ) open-in audio-in ;
+: read ( adr len -- actual ) open-in audio-in close-in ;
0 value mono?
0 value in-adr0
@@ -398,13 +393,15 @@
loop
;
: out-in ( out-adr out-len in-adr in-len -- )
+ open-out-in
+
to in-len0 to in-adr0 ( out-adr out-len )
to out-len to out-adr ( )
in-adr0 to in-adr ( )
in-len0 mono? if 2* then to in-len
- audio-clock-on ( ) \ This will mess up any frequency settings
+ ( audio-clock-on ) ( ) \ This will mess up any frequency settings
setup-sspa-tx ( )
setup-sspa-rx ( )
@@ -421,8 +418,7 @@
master-rx ( ) \ Now the clock is on
slave-tx ( )
- adc-on ( )
- dac-on ( )
+ adc+dac-on ( )
true to playing?
@@ -439,6 +435,8 @@
dac-off adc-off ( )
mono? if collapse-in then ( )
+
+ close-out-in
;
0 [if] \ Interactive test words for out-in
@@ -527,7 +525,7 @@
2 value #channels
\ Unless you do the audio-clock-on, the L/R phase is often wrong
-: input-test-settings ( -- ) audio-clock-on ;
+: input-test-settings ( -- ) ( audio-clock-on ) ;
: output-test-settings ( -- ) ;
d# -1 constant case-test-volume
Modified: dev/hdaudio/noiseburst.fth
==============================================================================
--- dev/hdaudio/noiseburst.fth Fri Sep 16 01:34:00 2011 (r2511)
+++ dev/hdaudio/noiseburst.fth Fri Sep 16 02:40:48 2011 (r2512)
@@ -562,8 +562,40 @@
defer analyze-right
defer fix-dc
+[ifdef] notdef
+fload ${BP}/forth/lib/isin.fth
+fload ${BP}/forth/lib/tones.fth
+
+\ This version puts the tone first into the left channel for
+\ half the time, then into the right channel for the remainder
+: make-2tones ( adr len freq sample-rate -- )
+ 2dup set-freq ( adr len freq sample-rate )
+
+ 3 pick make-cycle drop ( adr len freq sample-rate )
+
+ swap 2* swap set-freq ( adr len )
+ over wa1+ make-cycle drop ( adr len )
+
+
+ \ Copy the wave template into the remainder of the buffer
+ over /cycle + over /cycle - bounds ?do ( adr len )
+ over i /cycle move ( adr len )
+ /cycle +loop ( adr len )
+ 2drop
+;
+1 value debug-analyzer?
+[then]
+
: prepare-signal ( -- out-adr, len in-adr,len )
+[ifdef] debug-analyzer?
+ debug-analyzer? if
+ pb /pb d# 1000 d# 48000 make-2tones
+ else
+ pb /pb bounds do random-long i l! /l +loop
+ then
+[else]
pb /pb bounds do random-long i l! /l +loop
+[then]
pb /pb -stereo-wmean
pb wa1+ /pb -stereo-wmean
pb /pb lose-6db
Modified: dev/hdaudio/test.fth
==============================================================================
--- dev/hdaudio/test.fth Fri Sep 16 01:34:00 2011 (r2511)
+++ dev/hdaudio/test.fth Fri Sep 16 02:40:48 2011 (r2512)
@@ -102,7 +102,7 @@
false value plot? \ Set to true to plot the impulse response, for debugging
: plot-impulse ( adr -- )
d# 600 ( adr #samples )
- " 0 set-fg h# ffff set-bg single-drawing clear-drawing wave" evaluate
+ " 0 set-fg h# ffffffff set-bg single-drawing clear-drawing wave" evaluate
key ascii d = if debug-me then
;
More information about the openfirmware
mailing list